aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/AsyncCommandManager.cs270
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/Dataserver.cs127
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/Eventstream.cs76
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/HttpRequest.cs89
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/Listener.cs91
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/SensorRepeat.cs391
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/Timer.cs163
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/XmlRequest.cs115
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/Compiler.cs515
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/EventManager.cs293
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/Executor.cs136
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/ExecutorBase.cs181
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/LSL2CSConverter.cs363
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/LSL_ScriptCommands.cs6474
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/OSSL_ScriptCommands.cs553
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/Script/AssemblyResolver.cs65
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/Script/BuiltIn_Commands_BaseClass.cs2393
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/Script/ILSL_ScriptCommands.cs653
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/Script/IOSSL_ScriptCommands.cs68
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/Script/IScript.cs46
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/Script/LSL_Types.cs1411
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/XEngine.cs1435
-rw-r--r--ThirdParty/SmartThreadPool/AssemblyInfo.cs61
-rw-r--r--ThirdParty/SmartThreadPool/CallerThreadContext.cs223
-rw-r--r--ThirdParty/SmartThreadPool/Exceptions.cs81
-rw-r--r--ThirdParty/SmartThreadPool/Interfaces.cs271
-rw-r--r--ThirdParty/SmartThreadPool/PriorityQueue.cs240
-rw-r--r--ThirdParty/SmartThreadPool/STPPerformanceCounter.cs352
-rw-r--r--ThirdParty/SmartThreadPool/STPStartInfo.cs99
-rw-r--r--ThirdParty/SmartThreadPool/SmartThreadPool.cs1438
-rw-r--r--ThirdParty/SmartThreadPool/WIGStartInfo.cs99
-rw-r--r--ThirdParty/SmartThreadPool/WorkItem.cs1035
-rw-r--r--ThirdParty/SmartThreadPool/WorkItemFactory.cs333
-rw-r--r--ThirdParty/SmartThreadPool/WorkItemInfo.cs102
-rw-r--r--ThirdParty/SmartThreadPool/WorkItemsGroup.cs512
-rw-r--r--ThirdParty/SmartThreadPool/WorkItemsQueue.cs600
-rw-r--r--ThirdPartyLicenses/SmartThreadPool.txt22
-rw-r--r--bin/OpenSim.ini.example37
-rw-r--r--prebuild.xml94
39 files changed, 21507 insertions, 0 deletions
diff --git a/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandManager.cs b/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandManager.cs
new file mode 100644
index 0000000..4ec7916
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandManager.cs
@@ -0,0 +1,270 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Threading;
32using libsecondlife;
33using OpenSim.Framework;
34using OpenSim.Region.Environment.Interfaces;
35using OpenSim.Region.ScriptEngine.XEngine.AsyncCommandPlugins;
36using Timer=OpenSim.Region.ScriptEngine.XEngine.AsyncCommandPlugins.Timer;
37using Dataserver=OpenSim.Region.ScriptEngine.XEngine.AsyncCommandPlugins.Dataserver;
38
39namespace OpenSim.Region.ScriptEngine.XEngine
40{
41 /// <summary>
42 /// Handles LSL commands that takes long time and returns an event, for example timers, HTTP requests, etc.
43 /// </summary>
44 public class AsyncCommandManager
45 {
46 private static Thread cmdHandlerThread;
47 private static int cmdHandlerThreadCycleSleepms;
48
49 public XEngine m_ScriptEngine;
50
51 public Dataserver m_Dataserver;
52 public Timer m_Timer;
53 public HttpRequest m_HttpRequest;
54 public Listener m_Listener;
55 public SensorRepeat m_SensorRepeat;
56 public XmlRequest m_XmlRequest;
57
58 public AsyncCommandManager(XEngine _ScriptEngine)
59 {
60 m_ScriptEngine = _ScriptEngine;
61 ReadConfig();
62
63 // Create instances of all plugins
64 m_Dataserver = new Dataserver(this);
65 m_Timer = new Timer(this);
66 m_HttpRequest = new HttpRequest(this);
67 m_Listener = new Listener(this);
68 m_SensorRepeat = new SensorRepeat(this);
69 m_XmlRequest = new XmlRequest(this);
70
71 StartThread();
72 }
73
74 private static void StartThread()
75 {
76 if (cmdHandlerThread == null)
77 {
78 // Start the thread that will be doing the work
79 cmdHandlerThread = new Thread(CmdHandlerThreadLoop);
80 cmdHandlerThread.Name = "AsyncLSLCmdHandlerThread";
81 cmdHandlerThread.Priority = ThreadPriority.BelowNormal;
82 cmdHandlerThread.IsBackground = true;
83 cmdHandlerThread.Start();
84 ThreadTracker.Add(cmdHandlerThread);
85 }
86 }
87
88 public void ReadConfig()
89 {
90 cmdHandlerThreadCycleSleepms = m_ScriptEngine.ScriptConfigSource.GetInt("AsyncLLCommandLoopms", 100);
91 }
92
93 ~AsyncCommandManager()
94 {
95 // Shut down thread
96 try
97 {
98 if (cmdHandlerThread != null)
99 {
100 if (cmdHandlerThread.IsAlive == true)
101 {
102 cmdHandlerThread.Abort();
103 //cmdHandlerThread.Join();
104 }
105 }
106 }
107 catch
108 {
109 }
110 }
111
112 private static void CmdHandlerThreadLoop()
113 {
114 while (true)
115 {
116 try
117 {
118 while (true)
119 {
120 Thread.Sleep(cmdHandlerThreadCycleSleepms);
121
122 foreach (XEngine xe in XEngine.ScriptEngines)
123 {
124 xe.m_ASYNCLSLCommandManager.DoOneCmdHandlerPass();
125 }
126 }
127 }
128 catch
129 {
130 }
131 }
132 }
133
134 internal void DoOneCmdHandlerPass()
135 {
136 // Check timers
137 m_Timer.CheckTimerEvents();
138 // Check HttpRequests
139 m_HttpRequest.CheckHttpRequests();
140 // Check XMLRPCRequests
141 m_XmlRequest.CheckXMLRPCRequests();
142 // Check Listeners
143 m_Listener.CheckListeners();
144 // Check Sensors
145 m_SensorRepeat.CheckSenseRepeaterEvents();
146 // Check dataserver
147 m_Dataserver.ExpireRequests();
148 }
149
150 /// <summary>
151 /// Remove a specific script (and all its pending commands)
152 /// </summary>
153 /// <param name="localID"></param>
154 /// <param name="itemID"></param>
155 public void RemoveScript(uint localID, LLUUID itemID)
156 {
157 // Remove a specific script
158
159 // Remove dataserver events
160 m_Dataserver.RemoveEvents(localID, itemID);
161
162 // Remove from: Timers
163 m_Timer.UnSetTimerEvents(localID, itemID);
164
165 // Remove from: HttpRequest
166 IHttpRequests iHttpReq =
167 m_ScriptEngine.World.RequestModuleInterface<IHttpRequests>();
168 iHttpReq.StopHttpRequest(localID, itemID);
169
170 IWorldComm comms = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
171 comms.DeleteListener(itemID);
172
173 IXMLRPC xmlrpc = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
174 xmlrpc.DeleteChannels(itemID);
175 xmlrpc.CancelSRDRequests(itemID);
176
177 // Remove Sensors
178 m_SensorRepeat.UnSetSenseRepeaterEvents(localID, itemID);
179
180 }
181
182 public Object[] GetSerializationData(LLUUID itemID)
183 {
184 List<Object> data = new List<Object>();
185
186 Object[] listeners=m_Listener.GetSerializationData(itemID);
187 if(listeners.Length > 0)
188 {
189 data.Add("listener");
190 data.Add(listeners.Length);
191 data.AddRange(listeners);
192 }
193
194 Object[] timers=m_Timer.GetSerializationData(itemID);
195 if(timers.Length > 0)
196 {
197 data.Add("timer");
198 data.Add(timers.Length);
199 data.AddRange(timers);
200 }
201
202 Object[] sensors=m_SensorRepeat.GetSerializationData(itemID);
203 if(sensors.Length > 0)
204 {
205 data.Add("sensor");
206 data.Add(sensors.Length);
207 data.AddRange(sensors);
208 }
209
210 return data.ToArray();
211 }
212
213 public void CreateFromData(uint localID, LLUUID itemID, LLUUID hostID,
214 Object[] data)
215 {
216 int idx=0;
217 int len;
218
219 while(idx < data.Length)
220 {
221 string type = data[idx].ToString();
222 len = (int)data[idx+1];
223 idx+=2;
224
225 if(len > 0)
226 {
227 Object[] item = new Object[len];
228 Array.Copy(data, idx, item, 0, len);
229
230 idx+=len;
231
232 switch(type)
233 {
234 case "listener":
235 m_Listener.CreateFromData(localID, itemID, hostID,
236 item);
237 break;
238 case "timer":
239 m_Timer.CreateFromData(localID, itemID, hostID, item);
240 break;
241 case "sensor":
242 m_SensorRepeat.CreateFromData(localID, itemID, hostID,
243 item);
244 break;
245 }
246 }
247 }
248 }
249
250 #region Check llRemoteData channels
251
252
253 #endregion
254
255 #region Check llListeners
256
257
258 #endregion
259
260 /// <summary>
261 /// If set to true then threads and stuff should try to make a graceful exit
262 /// </summary>
263 public bool PleaseShutdown
264 {
265 get { return _PleaseShutdown; }
266 set { _PleaseShutdown = value; }
267 }
268 private bool _PleaseShutdown = false;
269 }
270}
diff --git a/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/Dataserver.cs b/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/Dataserver.cs
new file mode 100644
index 0000000..794a015
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/Dataserver.cs
@@ -0,0 +1,127 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using libsecondlife;
32using OpenSim.Region.ScriptEngine.XEngine.Script;
33
34namespace OpenSim.Region.ScriptEngine.XEngine.AsyncCommandPlugins
35{
36 public class Dataserver
37 {
38 public AsyncCommandManager m_CmdManager;
39
40 private Dictionary<string, DataserverRequest> DataserverRequests =
41 new Dictionary<string, DataserverRequest>();
42
43 public Dataserver(AsyncCommandManager CmdManager)
44 {
45 m_CmdManager = CmdManager;
46 }
47
48 private class DataserverRequest
49 {
50 public uint localID;
51 public LLUUID itemID;
52
53 public LLUUID ID;
54 public string handle;
55
56 public DateTime startTime;
57 }
58
59 public LLUUID RegisterRequest(uint localID, LLUUID itemID,
60 string identifier)
61 {
62 lock(DataserverRequests)
63 {
64 if(DataserverRequests.ContainsKey(identifier))
65 return LLUUID.Zero;
66
67 DataserverRequest ds = new DataserverRequest();
68
69 ds.localID = localID;
70 ds.itemID = itemID;
71
72 ds.ID = LLUUID.Random();
73 ds.handle = identifier;
74
75 ds.startTime = DateTime.Now;
76
77 DataserverRequests[identifier]=ds;
78
79 return ds.ID;
80 }
81 }
82
83 public void DataserverReply(string identifier, string reply)
84 {
85 DataserverRequest ds;
86
87 lock(DataserverRequests)
88 {
89 if(!DataserverRequests.ContainsKey(identifier))
90 return;
91
92 ds=DataserverRequests[identifier];
93 DataserverRequests.Remove(identifier);
94 }
95
96 m_CmdManager.m_ScriptEngine.PostObjectEvent(ds.localID,
97 new XEventParams( "dataserver", new Object[]
98 { new LSL_Types.LSLString(ds.ID.ToString()),
99 new LSL_Types.LSLString(reply)},
100 new XDetectParams[0]));
101 }
102
103 public void RemoveEvents(uint localID, LLUUID itemID)
104 {
105 lock(DataserverRequests)
106 {
107 foreach (DataserverRequest ds in new List<DataserverRequest>(DataserverRequests.Values))
108 {
109 if(ds.itemID == itemID)
110 DataserverRequests.Remove(ds.handle);
111 }
112 }
113 }
114
115 public void ExpireRequests()
116 {
117 lock(DataserverRequests)
118 {
119 foreach (DataserverRequest ds in new List<DataserverRequest>(DataserverRequests.Values))
120 {
121 if(ds.startTime > DateTime.Now.AddSeconds(30))
122 DataserverRequests.Remove(ds.handle);
123 }
124 }
125 }
126 }
127}
diff --git a/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/Eventstream.cs b/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/Eventstream.cs
new file mode 100644
index 0000000..9112b9c
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/Eventstream.cs
@@ -0,0 +1,76 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using libsecondlife;
32using OpenSim.Region.Environment.Scenes;
33
34namespace OpenSim.Region.ScriptEngine.XEngine.AsyncCommandPlugins
35{
36 public class Eventstream
37 {
38 public AsyncCommandManager m_CmdManager;
39
40 private class Event
41 {
42 public uint LocalID;
43 public string EventName;
44 public Dictionary<LLUUID, XDetectParams> DetectParams;
45 }
46
47 private Dictionary<uint, Dictionary<string, Event> > m_Events =
48 new Dictionary<uint, Dictionary<string, Event> >();
49
50 public Eventstream(AsyncCommandManager CmdManager)
51 {
52 m_CmdManager = CmdManager;
53 }
54
55 public void AddObjectEvent(uint localID, string eventName, XDetectParams det)
56 {
57 SceneObjectPart part = m_CmdManager.m_ScriptEngine.World.
58 GetSceneObjectPart(localID);
59
60 if(part == null) // Can't register events for non-prims
61 return;
62
63 if(!part.ContainsScripts())
64 return;
65
66 }
67
68 public void RemoveObjectEvent(uint localID, string eventName, LLUUID id)
69 {
70 }
71
72 public void RemoveObjects(uint localID)
73 {
74 }
75 }
76}
diff --git a/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/HttpRequest.cs b/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/HttpRequest.cs
new file mode 100644
index 0000000..977e3f9
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/HttpRequest.cs
@@ -0,0 +1,89 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using OpenSim.Region.Environment.Interfaces;
30using OpenSim.Region.Environment.Modules.Scripting.HttpRequest;
31using OpenSim.Region.ScriptEngine.XEngine.Script;
32
33namespace OpenSim.Region.ScriptEngine.XEngine.AsyncCommandPlugins
34{
35 public class HttpRequest
36 {
37 public AsyncCommandManager m_CmdManager;
38
39 public HttpRequest(AsyncCommandManager CmdManager)
40 {
41 m_CmdManager = CmdManager;
42 }
43
44 public void CheckHttpRequests()
45 {
46 if (m_CmdManager.m_ScriptEngine.World == null)
47 return;
48
49 IHttpRequests iHttpReq =
50 m_CmdManager.m_ScriptEngine.World.RequestModuleInterface<IHttpRequests>();
51
52 HttpRequestClass httpInfo = null;
53
54 if (iHttpReq != null)
55 httpInfo = iHttpReq.GetNextCompletedRequest();
56
57 while (httpInfo != null)
58 {
59 //m_ScriptEngine.Log.Info("[AsyncLSL]:" + httpInfo.response_body + httpInfo.status);
60
61 // Deliver data to prim's remote_data handler
62 //
63 // TODO: Returning null for metadata, since the lsl function
64 // only returns the byte for HTTP_BODY_TRUNCATED, which is not
65 // implemented here yet anyway. Should be fixed if/when maxsize
66 // is supported
67
68 iHttpReq.RemoveCompletedRequest(httpInfo.reqID);
69
70 object[] resobj = new object[]
71 {
72 new LSL_Types.LSLString(httpInfo.reqID.ToString()),
73 new LSL_Types.LSLInteger(httpInfo.status),
74 new LSL_Types.list(),
75 new LSL_Types.LSLString(httpInfo.response_body)
76 };
77
78 foreach (XEngine xe in XEngine.ScriptEngines)
79 {
80 if(xe.PostObjectEvent(httpInfo.localID,
81 new XEventParams("http_response",
82 resobj, new XDetectParams[0])))
83 break;
84 }
85 httpInfo = iHttpReq.GetNextCompletedRequest();
86 }
87 }
88 }
89}
diff --git a/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/Listener.cs b/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/Listener.cs
new file mode 100644
index 0000000..1144c00
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/Listener.cs
@@ -0,0 +1,91 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using libsecondlife;
30using OpenSim.Region.Environment.Interfaces;
31using OpenSim.Region.Environment.Modules.Scripting.WorldComm;
32using OpenSim.Region.ScriptEngine.XEngine.Script;
33
34namespace OpenSim.Region.ScriptEngine.XEngine.AsyncCommandPlugins
35{
36 public class Listener
37 {
38 // private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
39
40 public AsyncCommandManager m_CmdManager;
41
42 public Listener(AsyncCommandManager CmdManager)
43 {
44 m_CmdManager = CmdManager;
45 }
46
47 public void CheckListeners()
48 {
49 if (m_CmdManager.m_ScriptEngine.World == null)
50 return;
51 IWorldComm comms = m_CmdManager.m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
52
53 if (comms != null)
54 {
55 while (comms.HasMessages())
56 {
57 ListenerInfo lInfo = comms.GetNextMessage();
58
59 //Deliver data to prim's listen handler
60 object[] resobj = new object[]
61 {
62 new LSL_Types.LSLInteger(lInfo.GetChannel()),
63 new LSL_Types.LSLString(lInfo.GetName()),
64 new LSL_Types.LSLString(lInfo.GetID().ToString()),
65 new LSL_Types.LSLString(lInfo.GetMessage())
66 };
67
68 m_CmdManager.m_ScriptEngine.PostScriptEvent(
69 lInfo.GetItemID(), new XEventParams(
70 "listen", resobj,
71 new XDetectParams[0]));
72 }
73 }
74 }
75
76 public Object[] GetSerializationData(LLUUID itemID)
77 {
78 IWorldComm comms = m_CmdManager.m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
79
80 return comms.GetSerializationData(itemID);
81 }
82
83 public void CreateFromData(uint localID, LLUUID itemID, LLUUID hostID,
84 Object[] data)
85 {
86 IWorldComm comms = m_CmdManager.m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
87
88 comms.CreateFromData(localID, itemID, hostID, data);
89 }
90 }
91}
diff --git a/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/SensorRepeat.cs
new file mode 100644
index 0000000..5a87bb0
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/SensorRepeat.cs
@@ -0,0 +1,391 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using libsecondlife;
31using OpenSim.Framework;
32using OpenSim.Region.Environment.Scenes;
33using OpenSim.Region.ScriptEngine.XEngine.Script;
34
35namespace OpenSim.Region.ScriptEngine.XEngine.AsyncCommandPlugins
36{
37 public class SensorRepeat
38 {
39 public AsyncCommandManager m_CmdManager;
40
41 public SensorRepeat(AsyncCommandManager CmdManager)
42 {
43 m_CmdManager = CmdManager;
44 }
45
46 public Dictionary<uint, Dictionary<LLUUID, LSL_Types.list>> SenseEvents =
47 new Dictionary<uint, Dictionary<LLUUID, LSL_Types.list>>();
48 private Object SenseLock = new Object();
49
50 //
51 // SenseRepeater and Sensors
52 //
53 private class SenseRepeatClass
54 {
55 public uint localID;
56 public LLUUID itemID;
57 public double interval;
58 public DateTime next;
59
60 public string name;
61 public LLUUID keyID;
62 public int type;
63 public double range;
64 public double arc;
65 public SceneObjectPart host;
66 }
67
68 private List<SenseRepeatClass> SenseRepeaters = new List<SenseRepeatClass>();
69 private object SenseRepeatListLock = new object();
70
71 public void SetSenseRepeatEvent(uint m_localID, LLUUID m_itemID,
72 string name, LLUUID keyID, int type, double range, double arc, double sec, SceneObjectPart host)
73 {
74 Console.WriteLine("SetSensorEvent");
75
76 // Always remove first, in case this is a re-set
77 UnSetSenseRepeaterEvents(m_localID, m_itemID);
78 if (sec == 0) // Disabling timer
79 return;
80
81 // Add to timer
82 SenseRepeatClass ts = new SenseRepeatClass();
83 ts.localID = m_localID;
84 ts.itemID = m_itemID;
85 ts.interval = sec;
86 ts.name = name;
87 ts.keyID = keyID;
88 ts.type = type;
89 ts.range = range;
90 ts.arc = arc;
91 ts.host = host;
92
93 ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
94 lock (SenseRepeatListLock)
95 {
96 SenseRepeaters.Add(ts);
97 }
98 }
99
100 public void UnSetSenseRepeaterEvents(uint m_localID, LLUUID m_itemID)
101 {
102 // Remove from timer
103 lock (SenseRepeatListLock)
104 {
105 List<SenseRepeatClass> NewSensors = new List<SenseRepeatClass>();
106 foreach (SenseRepeatClass ts in SenseRepeaters)
107 {
108 if (ts.localID != m_localID && ts.itemID != m_itemID)
109 {
110 NewSensors.Add(ts);
111 }
112 }
113 SenseRepeaters.Clear();
114 SenseRepeaters = NewSensors;
115 }
116 }
117
118 public void CheckSenseRepeaterEvents()
119 {
120 // Nothing to do here?
121 if (SenseRepeaters.Count == 0)
122 return;
123
124 lock (SenseRepeatListLock)
125 {
126 // Go through all timers
127 foreach (SenseRepeatClass ts in SenseRepeaters)
128 {
129 // Time has passed?
130 if (ts.next.ToUniversalTime() < DateTime.Now.ToUniversalTime())
131 {
132 SensorSweep(ts);
133 // set next interval
134 ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
135 }
136 }
137 } // lock
138 }
139
140 public void SenseOnce(uint m_localID, LLUUID m_itemID,
141 string name, LLUUID keyID, int type,
142 double range, double arc, SceneObjectPart host)
143 {
144 // Add to timer
145 SenseRepeatClass ts = new SenseRepeatClass();
146 ts.localID = m_localID;
147 ts.itemID = m_itemID;
148 ts.interval = 0;
149 ts.name = name;
150 ts.keyID = keyID;
151 ts.type = type;
152 ts.range = range;
153 ts.arc = arc;
154 ts.host = host;
155 SensorSweep(ts);
156 }
157
158 public LSL_Types.list GetSensorList(uint m_localID, LLUUID m_itemID)
159 {
160 lock (SenseLock)
161 {
162 Dictionary<LLUUID, LSL_Types.list> Obj = null;
163 if (!SenseEvents.TryGetValue(m_localID, out Obj))
164 {
165 m_CmdManager.m_ScriptEngine.Log.Info("[AsyncLSL]: GetSensorList missing localID: " + m_localID);
166 return null;
167 }
168 lock (Obj)
169 {
170 // Get script
171 LSL_Types.list SenseList = null;
172 if (!Obj.TryGetValue(m_itemID, out SenseList))
173 {
174 m_CmdManager.m_ScriptEngine.Log.Info("[AsyncLSL]: GetSensorList missing itemID: " + m_itemID);
175 return null;
176 }
177 return SenseList;
178 }
179 }
180 }
181
182 private void SensorSweep(SenseRepeatClass ts)
183 {
184 //m_ScriptEngine.Log.Info("[AsyncLSL]:Enter SensorSweep");
185 SceneObjectPart SensePoint = ts.host;
186
187 if (SensePoint == null)
188 {
189 //m_ScriptEngine.Log.Info("[AsyncLSL]: Enter SensorSweep (SensePoint == null) for "+ts.itemID.ToString());
190 return;
191 }
192 //m_ScriptEngine.Log.Info("[AsyncLSL]: Enter SensorSweep Scan");
193
194 LLVector3 sensorPos = SensePoint.AbsolutePosition;
195 LLVector3 regionPos = new LLVector3(m_CmdManager.m_ScriptEngine.World.RegionInfo.RegionLocX * Constants.RegionSize, m_CmdManager.m_ScriptEngine.World.RegionInfo.RegionLocY * Constants.RegionSize, 0);
196 LLVector3 fromRegionPos = sensorPos + regionPos;
197
198 LLQuaternion q = SensePoint.RotationOffset;
199 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W);
200 LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r);
201 double mag_fwd = LSL_Types.Vector3.Mag(forward_dir);
202
203 // Here we should do some smart culling ...
204 // math seems quicker than strings so try that first
205 LSL_Types.list SensedObjects = new LSL_Types.list();
206 LSL_Types.Vector3 ZeroVector = new LSL_Types.Vector3(0, 0, 0);
207
208 foreach (EntityBase ent in m_CmdManager.m_ScriptEngine.World.Entities.Values)
209 {
210 LLVector3 toRegionPos = ent.AbsolutePosition + regionPos;
211 double dis = Math.Abs((double)Util.GetDistanceTo(toRegionPos, fromRegionPos));
212 if (dis <= ts.range)
213 {
214 // In Range, is it the right Type ?
215 int objtype = 0;
216
217 if (m_CmdManager.m_ScriptEngine.World.GetScenePresence(ent.UUID) != null) objtype |= 0x01; // actor
218 if (ent.Velocity.Equals(ZeroVector))
219 objtype |= 0x04; // passive non-moving
220 else
221 objtype |= 0x02; // active moving
222 if (ent is IScript) objtype |= 0x08; // Scripted. It COULD have one hidden ...
223
224 if (((ts.type & objtype) != 0) || ((ts.type & objtype) == ts.type))
225 {
226 // docs claim AGENT|ACTIVE should find agent objects OR active objects
227 // so the bitwise AND with object type should be non-zero
228
229 // Right type too, what about the other params , key and name ?
230 bool keep = true;
231 if (ts.arc < Math.PI)
232 {
233 // not omni-directional. Can you see it ?
234 // vec forward_dir = llRot2Fwd(llGetRot())
235 // vec obj_dir = toRegionPos-fromRegionPos
236 // dot=dot(forward_dir,obj_dir)
237 // mag_fwd = mag(forward_dir)
238 // mag_obj = mag(obj_dir)
239 // ang = acos(dot /(mag_fwd*mag_obj))
240 double ang_obj = 0;
241 try
242 {
243 LLVector3 diff = toRegionPos - fromRegionPos;
244 LSL_Types.Vector3 obj_dir = new LSL_Types.Vector3(diff.X, diff.Y, diff.Z);
245 double dot = LSL_Types.Vector3.Dot(forward_dir, obj_dir);
246 double mag_obj = LSL_Types.Vector3.Mag(obj_dir);
247 ang_obj = Math.Acos(dot / (mag_fwd * mag_obj));
248 }
249 catch
250 {
251 }
252
253 if (ang_obj > ts.arc) keep = false;
254 }
255
256 if (keep && (ts.keyID != LLUUID.Zero) && (ts.keyID != ent.UUID))
257 {
258 keep = false;
259 }
260
261 if (keep && (ts.name.Length > 0))
262 {
263 string avatarname=null;
264 string objectname=null;
265 string entname =ent.Name;
266
267 // try avatar username surname
268 UserProfileData profile = m_CmdManager.m_ScriptEngine.World.CommsManager.UserService.GetUserProfile(ent.UUID);
269 if (profile != null)
270 {
271 avatarname = profile.FirstName + " " + profile.SurName;
272 }
273 // try an scene object
274 SceneObjectPart SOP = m_CmdManager.m_ScriptEngine.World.GetSceneObjectPart(ent.UUID);
275 if (SOP != null)
276 {
277 objectname = SOP.Name;
278 }
279
280 if ((ts.name != entname) && (ts.name != avatarname) && (ts.name != objectname))
281 {
282 keep = false;
283 }
284 }
285
286 if (keep == true) SensedObjects.Add(ent.UUID);
287 }
288 }
289 }
290 //m_ScriptEngine.Log.Info("[AsyncLSL]: Enter SensorSweep SenseLock");
291
292 lock (SenseLock)
293 {
294 // Create object if it doesn't exist
295 if (SenseEvents.ContainsKey(ts.localID) == false)
296 {
297 SenseEvents.Add(ts.localID, new Dictionary<LLUUID, LSL_Types.list>());
298 }
299 // clear if previous traces exist
300 Dictionary<LLUUID, LSL_Types.list> Obj;
301 SenseEvents.TryGetValue(ts.localID, out Obj);
302 if (Obj.ContainsKey(ts.itemID) == true)
303 Obj.Remove(ts.itemID);
304
305 // note list may be zero length
306 Obj.Add(ts.itemID, SensedObjects);
307
308 if (SensedObjects.Length == 0)
309 {
310 // send a "no_sensor"
311 // Add it to queue
312 m_CmdManager.m_ScriptEngine.PostScriptEvent(ts.itemID,
313 new XEventParams("no_sensor", new Object[0],
314 new XDetectParams[0]));
315 }
316 else
317 {
318 XDetectParams[] detect =
319 new XDetectParams[SensedObjects.Length];
320
321 int idx;
322 for(idx = 0 ; idx < SensedObjects.Length; idx++)
323 {
324 detect[idx].Key=(LLUUID)(SensedObjects.Data[idx]);
325 }
326
327 m_CmdManager.m_ScriptEngine.PostScriptEvent(ts.itemID,
328 new XEventParams("sensor",
329 new Object[] {
330 new LSL_Types.LSLInteger(SensedObjects.Length) },
331 detect));
332 }
333 }
334 }
335
336 public Object[] GetSerializationData(LLUUID itemID)
337 {
338 List<Object> data = new List<Object>();
339
340 foreach (SenseRepeatClass ts in SenseRepeaters)
341 {
342 if(ts.itemID == itemID)
343 {
344 data.Add(ts.interval);
345 data.Add(ts.name);
346 data.Add(ts.keyID);
347 data.Add(ts.type);
348 data.Add(ts.range);
349 data.Add(ts.arc);
350 }
351 }
352 return data.ToArray();
353 }
354
355 public void CreateFromData(uint localID, LLUUID itemID, LLUUID objectID,
356 Object[] data)
357 {
358 SceneObjectPart part =
359 m_CmdManager.m_ScriptEngine.World.GetSceneObjectPart(
360 objectID);
361
362 if(part == null)
363 return;
364
365 int idx=0;
366
367 while(idx < data.Length)
368 {
369 SenseRepeatClass ts = new SenseRepeatClass();
370
371 ts.localID = localID;
372 ts.itemID = itemID;
373
374 ts.interval = (double)data[idx];
375 ts.name = (string)data[idx+1];
376 ts.keyID = (LLUUID)data[idx+2];
377 ts.type = (int)data[idx+3];
378 ts.range = (double)data[idx+4];
379 ts.arc = (double)data[idx+5];
380 ts.host = part;
381
382 ts.next =
383 DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
384
385 SenseRepeaters.Add(ts);
386 idx += 6;
387 }
388 }
389
390 }
391}
diff --git a/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/Timer.cs b/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/Timer.cs
new file mode 100644
index 0000000..09a5818
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/Timer.cs
@@ -0,0 +1,163 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using libsecondlife;
32
33namespace OpenSim.Region.ScriptEngine.XEngine.AsyncCommandPlugins
34{
35 public class Timer
36 {
37 public AsyncCommandManager m_CmdManager;
38
39 public Timer(AsyncCommandManager CmdManager)
40 {
41 m_CmdManager = CmdManager;
42 }
43
44 //
45 // TIMER
46 //
47 private class TimerClass
48 {
49 public uint localID;
50 public LLUUID itemID;
51 //public double interval;
52 public long interval;
53 //public DateTime next;
54 public long next;
55 }
56
57 private List<TimerClass> Timers = new List<TimerClass>();
58 private object TimerListLock = new object();
59
60 public void SetTimerEvent(uint m_localID, LLUUID m_itemID, double sec)
61 {
62 Console.WriteLine("SetTimerEvent");
63
64 // Always remove first, in case this is a re-set
65 UnSetTimerEvents(m_localID, m_itemID);
66 if (sec == 0) // Disabling timer
67 return;
68
69 // Add to timer
70 TimerClass ts = new TimerClass();
71 ts.localID = m_localID;
72 ts.itemID = m_itemID;
73 ts.interval = Convert.ToInt64(sec * 10000000); // How many 100 nanoseconds (ticks) should we wait
74 // 2193386136332921 ticks
75 // 219338613 seconds
76
77 //ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
78 ts.next = DateTime.Now.Ticks + ts.interval;
79 lock (TimerListLock)
80 {
81 Timers.Add(ts);
82 }
83 }
84
85 public void UnSetTimerEvents(uint m_localID, LLUUID m_itemID)
86 {
87 // Remove from timer
88 lock (TimerListLock)
89 {
90 foreach (TimerClass ts in new ArrayList(Timers))
91 {
92 if (ts.localID == m_localID && ts.itemID == m_itemID)
93 Timers.Remove(ts);
94 }
95 }
96 }
97
98 public void CheckTimerEvents()
99 {
100 // Nothing to do here?
101 if (Timers.Count == 0)
102 return;
103
104 lock (TimerListLock)
105 {
106 // Go through all timers
107 foreach (TimerClass ts in Timers)
108 {
109 // Time has passed?
110 if (ts.next < DateTime.Now.Ticks)
111 {
112 // Console.WriteLine("Time has passed: Now: " + DateTime.Now.Ticks + ", Passed: " + ts.next);
113 // Add it to queue
114 m_CmdManager.m_ScriptEngine.PostScriptEvent(ts.itemID,
115 new XEventParams("timer", new Object[0],
116 new XDetectParams[0]));
117 // set next interval
118
119 //ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
120 ts.next = DateTime.Now.Ticks + ts.interval;
121 }
122 }
123 }
124 }
125
126 public Object[] GetSerializationData(LLUUID itemID)
127 {
128 List<Object> data = new List<Object>();
129
130 lock (TimerListLock)
131 {
132 foreach (TimerClass ts in Timers)
133 {
134 if(ts.itemID == itemID)
135 {
136 data.Add(ts.interval);
137 data.Add(ts.next-DateTime.Now.Ticks);
138 }
139 }
140 }
141 return data.ToArray();
142 }
143
144 public void CreateFromData(uint localID, LLUUID itemID, LLUUID objectID,
145 Object[] data)
146 {
147 int idx=0;
148
149 while(idx < data.Length)
150 {
151 TimerClass ts = new TimerClass();
152
153 ts.localID = localID;
154 ts.itemID = itemID;
155 ts.interval = (long)data[idx];
156 ts.next = DateTime.Now.Ticks + (long)data[idx+1];
157 idx += 2;
158
159 Timers.Add(ts);
160 }
161 }
162 }
163}
diff --git a/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/XmlRequest.cs b/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/XmlRequest.cs
new file mode 100644
index 0000000..2714d11
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/XmlRequest.cs
@@ -0,0 +1,115 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using OpenSim.Region.Environment.Interfaces;
30using OpenSim.Region.Environment.Modules.Scripting.XMLRPC;
31using OpenSim.Region.ScriptEngine.XEngine.Script;
32
33namespace OpenSim.Region.ScriptEngine.XEngine.AsyncCommandPlugins
34{
35 public class XmlRequest
36 {
37 public AsyncCommandManager m_CmdManager;
38
39 public XmlRequest(AsyncCommandManager CmdManager)
40 {
41 m_CmdManager = CmdManager;
42 }
43
44 public void CheckXMLRPCRequests()
45 {
46 if (m_CmdManager.m_ScriptEngine.World == null)
47 return;
48
49 IXMLRPC xmlrpc = m_CmdManager.m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
50
51 if (xmlrpc != null)
52 {
53 RPCRequestInfo rInfo = xmlrpc.GetNextCompletedRequest();
54
55 while (rInfo != null)
56 {
57 xmlrpc.RemoveCompletedRequest(rInfo.GetMessageID());
58
59 //Deliver data to prim's remote_data handler
60 object[] resobj = new object[]
61 {
62 new LSL_Types.LSLInteger(2),
63 new LSL_Types.LSLString(
64 rInfo.GetChannelKey().ToString()),
65 new LSL_Types.LSLString(
66 rInfo.GetMessageID().ToString()),
67 new LSL_Types.LSLString(String.Empty),
68 new LSL_Types.LSLInteger(rInfo.GetIntValue()),
69 new LSL_Types.LSLString(rInfo.GetStrVal())
70 };
71
72 foreach (XEngine xe in XEngine.ScriptEngines)
73 {
74 if(xe.PostScriptEvent(
75 rInfo.GetItemID(), new XEventParams(
76 "remote_data", resobj,
77 new XDetectParams[0])))
78 break;
79 }
80
81 rInfo = xmlrpc.GetNextCompletedRequest();
82 }
83
84 SendRemoteDataRequest srdInfo = xmlrpc.GetNextCompletedSRDRequest();
85
86 while (srdInfo != null)
87 {
88 xmlrpc.RemoveCompletedSRDRequest(srdInfo.GetReqID());
89
90 //Deliver data to prim's remote_data handler
91 object[] resobj = new object[]
92 {
93 new LSL_Types.LSLInteger(3),
94 new LSL_Types.LSLString(srdInfo.channel.ToString()),
95 new LSL_Types.LSLString(srdInfo.GetReqID().ToString()),
96 new LSL_Types.LSLString(String.Empty),
97 new LSL_Types.LSLInteger(srdInfo.idata),
98 new LSL_Types.LSLString(srdInfo.sdata)
99 };
100
101 foreach (XEngine xe in XEngine.ScriptEngines)
102 {
103 if(xe.PostScriptEvent(
104 srdInfo.m_itemID, new XEventParams(
105 "remote_data", resobj,
106 new XDetectParams[0])))
107 break;
108 }
109
110 srdInfo = xmlrpc.GetNextCompletedSRDRequest();
111 }
112 }
113 }
114 }
115}
diff --git a/OpenSim/Region/ScriptEngine/XEngine/Compiler.cs b/OpenSim/Region/ScriptEngine/XEngine/Compiler.cs
new file mode 100644
index 0000000..980d9e6
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/XEngine/Compiler.cs
@@ -0,0 +1,515 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.CodeDom.Compiler;
30using System.Collections.Generic;
31using System.Globalization;
32using System.IO;
33using Microsoft.CSharp;
34using Microsoft.JScript;
35using Microsoft.VisualBasic;
36using OpenSim.Region.Environment.Interfaces;
37
38namespace OpenSim.Region.ScriptEngine.XEngine
39{
40 public class Compiler
41 {
42 private static readonly log4net.ILog m_log
43 = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
44
45 // * Uses "LSL2Converter" to convert LSL to C# if necessary.
46 // * Compiles C#-code into an assembly
47 // * Returns assembly name ready for AppDomain load.
48 //
49 // Assembly is compiled using LSL_BaseClass as base. Look at debug C# code file created when LSL script is compiled for full details.
50 //
51
52 internal enum enumCompileType
53 {
54 lsl = 0,
55 cs = 1,
56 vb = 2,
57 js = 3
58 }
59
60 /// <summary>
61 /// This contains number of lines WE use for header when compiling script. User will get error in line x-LinesToRemoveOnError when error occurs.
62 /// </summary>
63 public int LinesToRemoveOnError = 3;
64 private enumCompileType DefaultCompileLanguage;
65 private bool WriteScriptSourceToDebugFile;
66 private bool CompileWithDebugInformation;
67 private Dictionary<string, bool> AllowedCompilers = new Dictionary<string, bool>(StringComparer.CurrentCultureIgnoreCase);
68 private Dictionary<string, enumCompileType> LanguageMapping = new Dictionary<string, enumCompileType>(StringComparer.CurrentCultureIgnoreCase);
69
70 private string FilePrefix;
71 private string ScriptEnginesPath = "ScriptEngines";
72
73 private static LSL2CSConverter LSL_Converter = new LSL2CSConverter();
74 private static CSharpCodeProvider CScodeProvider = new CSharpCodeProvider();
75 private static VBCodeProvider VBcodeProvider = new VBCodeProvider();
76 private static JScriptCodeProvider JScodeProvider = new JScriptCodeProvider();
77
78 private static int instanceID = new Random().Next(0, int.MaxValue); // Unique number to use on our compiled files
79 private static UInt64 scriptCompileCounter = 0; // And a counter
80
81 public XEngine m_scriptEngine;
82 public Compiler(XEngine scriptEngine)
83 {
84 m_scriptEngine = scriptEngine;
85 ReadConfig();
86 }
87 public bool in_startup = true;
88 public void ReadConfig()
89 {
90
91 // Get some config
92 WriteScriptSourceToDebugFile = m_scriptEngine.ScriptConfigSource.GetBoolean("WriteScriptSourceToDebugFile", true);
93 CompileWithDebugInformation = m_scriptEngine.ScriptConfigSource.GetBoolean("CompileWithDebugInformation", true);
94
95 // Get file prefix from scriptengine name and make it file system safe:
96 FilePrefix = m_scriptEngine.ScriptEngineName;
97 foreach (char c in Path.GetInvalidFileNameChars())
98 {
99 FilePrefix = FilePrefix.Replace(c, '_');
100 }
101
102 // First time we start? Delete old files
103 if (in_startup)
104 {
105 in_startup = false;
106 DeleteOldFiles();
107 }
108
109 // Map name and enum type of our supported languages
110 LanguageMapping.Add(enumCompileType.cs.ToString(), enumCompileType.cs);
111 LanguageMapping.Add(enumCompileType.vb.ToString(), enumCompileType.vb);
112 LanguageMapping.Add(enumCompileType.lsl.ToString(), enumCompileType.lsl);
113 LanguageMapping.Add(enumCompileType.js.ToString(), enumCompileType.js);
114
115 // Allowed compilers
116 string allowComp = m_scriptEngine.ScriptConfigSource.GetString("AllowedCompilers", "lsl,cs,vb,js");
117 AllowedCompilers.Clear();
118
119#if DEBUG
120 m_scriptEngine.Log.Debug("[" + m_scriptEngine.ScriptEngineName + "]: Allowed languages: " + allowComp);
121#endif
122
123
124 foreach (string strl in allowComp.Split(','))
125 {
126 string strlan = strl.Trim(" \t".ToCharArray()).ToLower();
127 if (!LanguageMapping.ContainsKey(strlan))
128 {
129 m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: Config error. Compiler is unable to recognize language type \"" + strlan + "\" specified in \"AllowedCompilers\".");
130 }
131 else
132 {
133#if DEBUG
134 //m_scriptEngine.Log.Debug("[" + m_scriptEngine.ScriptEngineName + "]: Config OK. Compiler recognized language type \"" + strlan + "\" specified in \"AllowedCompilers\".");
135#endif
136 }
137 AllowedCompilers.Add(strlan, true);
138 }
139 if (AllowedCompilers.Count == 0)
140 m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: Config error. Compiler could not recognize any language in \"AllowedCompilers\". Scripts will not be executed!");
141
142 // Default language
143 string defaultCompileLanguage = m_scriptEngine.ScriptConfigSource.GetString("DefaultCompileLanguage", "lsl").ToLower();
144
145 // Is this language recognized at all?
146 if (!LanguageMapping.ContainsKey(defaultCompileLanguage))
147 {
148 m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: " +
149 "Config error. Default language \"" + defaultCompileLanguage + "\" specified in \"DefaultCompileLanguage\" is not recognized as a valid language. Changing default to: \"lsl\".");
150 defaultCompileLanguage = "lsl";
151 }
152
153 // Is this language in allow-list?
154 if (!AllowedCompilers.ContainsKey(defaultCompileLanguage))
155 {
156 m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: " +
157 "Config error. Default language \"" + defaultCompileLanguage + "\"specified in \"DefaultCompileLanguage\" is not in list of \"AllowedCompilers\". Scripts may not be executed!");
158 }
159 else
160 {
161#if DEBUG
162// m_scriptEngine.Log.Debug("[" + m_scriptEngine.ScriptEngineName + "]: " +
163// "Config OK. Default language \"" + defaultCompileLanguage + "\" specified in \"DefaultCompileLanguage\" is recognized as a valid language.");
164#endif
165 // LANGUAGE IS IN ALLOW-LIST
166 DefaultCompileLanguage = LanguageMapping[defaultCompileLanguage];
167 }
168
169 // We now have an allow-list, a mapping list, and a default language
170
171 }
172
173 /// <summary>
174 /// Delete old script files
175 /// </summary>
176 private void DeleteOldFiles()
177 {
178
179 // CREATE FOLDER IF IT DOESNT EXIST
180 if (!Directory.Exists(ScriptEnginesPath))
181 {
182 try
183 {
184 Directory.CreateDirectory(ScriptEnginesPath);
185 }
186 catch (Exception ex)
187 {
188 m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: Exception trying to create ScriptEngine directory \"" + ScriptEnginesPath + "\": " + ex.ToString());
189 }
190 }
191
192 if (!Directory.Exists(Path.Combine(ScriptEnginesPath,
193 m_scriptEngine.World.RegionInfo.RegionID.ToString())))
194 {
195 try
196 {
197 Directory.CreateDirectory(Path.Combine(ScriptEnginesPath,
198 m_scriptEngine.World.RegionInfo.RegionID.ToString()));
199 }
200 catch (Exception ex)
201 {
202 m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: Exception trying to create ScriptEngine directory \"" + Path.Combine(ScriptEnginesPath,
203 m_scriptEngine.World.RegionInfo.RegionID.ToString())+ "\": " + ex.ToString());
204 }
205 }
206
207 foreach (string file in Directory.GetFiles(Path.Combine(ScriptEnginesPath,
208 m_scriptEngine.World.RegionInfo.RegionID.ToString())))
209 {
210 //m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: FILE FOUND: " + file);
211
212 if (file.ToLower().StartsWith(FilePrefix + "_compiled_") ||
213 file.ToLower().StartsWith(FilePrefix + "_source_"))
214 {
215 try
216 {
217 File.Delete(file);
218 }
219 catch (Exception ex)
220 {
221 m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: Exception trying delete old script file \"" + file + "\": " + ex.ToString());
222 }
223
224 }
225 }
226
227 }
228
229 ////private ICodeCompiler icc = codeProvider.CreateCompiler();
230 //public string CompileFromFile(string LSOFileName)
231 //{
232 // switch (Path.GetExtension(LSOFileName).ToLower())
233 // {
234 // case ".txt":
235 // case ".lsl":
236 // Common.ScriptEngineBase.Common.SendToDebug("Source code is LSL, converting to CS");
237 // return CompileFromLSLText(File.ReadAllText(LSOFileName));
238 // case ".cs":
239 // Common.ScriptEngineBase.Common.SendToDebug("Source code is CS");
240 // return CompileFromCSText(File.ReadAllText(LSOFileName));
241 // default:
242 // throw new Exception("Unknown script type.");
243 // }
244 //}
245
246 /// <summary>
247 /// Converts script from LSL to CS and calls CompileFromCSText
248 /// </summary>
249 /// <param name="Script">LSL script</param>
250 /// <returns>Filename to .dll assembly</returns>
251 public string PerformScriptCompile(string Script, string asset)
252 {
253 string OutFile = Path.Combine(ScriptEnginesPath, Path.Combine(
254 m_scriptEngine.World.RegionInfo.RegionID.ToString(),
255 FilePrefix + "_compiled_" + asset + ".dll"));
256// string OutFile = Path.Combine(ScriptEnginesPath,
257// FilePrefix + "_compiled_" + asset + ".dll");
258
259 if(File.Exists(OutFile))
260 return OutFile;
261
262 if (!Directory.Exists(ScriptEnginesPath))
263 {
264 try
265 {
266 Directory.CreateDirectory(ScriptEnginesPath);
267 }
268 catch (Exception ex)
269 {
270 }
271 }
272
273 if (!Directory.Exists(Path.Combine(ScriptEnginesPath,
274 m_scriptEngine.World.RegionInfo.RegionID.ToString())))
275 {
276 try
277 {
278 Directory.CreateDirectory(ScriptEnginesPath);
279 }
280 catch (Exception ex)
281 {
282 }
283 }
284
285 enumCompileType l = DefaultCompileLanguage;
286
287
288 if (Script.StartsWith("//c#", true, CultureInfo.InvariantCulture))
289 l = enumCompileType.cs;
290 if (Script.StartsWith("//vb", true, CultureInfo.InvariantCulture))
291 {
292 l = enumCompileType.vb;
293 // We need to remove //vb, it won't compile with that
294
295 Script = Script.Substring(4, Script.Length - 4);
296 }
297 if (Script.StartsWith("//lsl", true, CultureInfo.InvariantCulture))
298 l = enumCompileType.lsl;
299
300 if (Script.StartsWith("//js", true, CultureInfo.InvariantCulture))
301 l = enumCompileType.js;
302
303 if (!AllowedCompilers.ContainsKey(l.ToString()))
304 {
305 // Not allowed to compile to this language!
306 string errtext = String.Empty;
307 errtext += "The compiler for language \"" + l.ToString() + "\" is not in list of allowed compilers. Script will not be executed!";
308 throw new Exception(errtext);
309 }
310
311 string compileScript = Script;
312
313 if (l == enumCompileType.lsl)
314 {
315 // Its LSL, convert it to C#
316 compileScript = LSL_Converter.Convert(Script);
317 l = enumCompileType.cs;
318 }
319
320 // Insert additional assemblies here
321
322 //ADAM: Disabled for the moment until it's working right.
323 bool enableCommanderLSL = false;
324
325 if (enableCommanderLSL == true && l == enumCompileType.cs)
326 {
327 foreach (KeyValuePair<string,
328 ICommander> com
329 in m_scriptEngine.World.GetCommanders())
330 {
331 compileScript = com.Value.GenerateRuntimeAPI() + compileScript;
332 }
333 }
334
335 // End of insert
336
337
338 switch (l)
339 {
340 case enumCompileType.cs:
341 compileScript = CreateCSCompilerScript(compileScript);
342 break;
343 case enumCompileType.vb:
344 compileScript = CreateVBCompilerScript(compileScript);
345 break;
346 case enumCompileType.js:
347 compileScript = CreateJSCompilerScript(compileScript);
348 break;
349 }
350
351// m_log.Debug("[ScriptEngine.DotNetEngine]: Preparing to compile the following LSL to C# translated code");
352// m_log.Debug("");
353// m_log.Debug(compileScript);
354
355 return CompileFromDotNetText(compileScript, l, asset);
356 }
357
358 private static string CreateJSCompilerScript(string compileScript)
359 {
360 compileScript = String.Empty +
361 "import OpenSim.Region.ScriptEngine.XEngine.Script; import System.Collections.Generic;\r\n" +
362 "package SecondLife {\r\n" +
363 "class Script extends OpenSim.Region.ScriptEngine.XEngine.Script.BuiltIn_Commands_BaseClass { \r\n" +
364 compileScript +
365 "} }\r\n";
366 return compileScript;
367 }
368
369 private static string CreateCSCompilerScript(string compileScript)
370 {
371
372
373 compileScript = String.Empty +
374 "using OpenSim.Region.ScriptEngine.XEngine.Script; using System.Collections.Generic;\r\n" +
375 String.Empty + "namespace SecondLife { " +
376 String.Empty + "public class Script : OpenSim.Region.ScriptEngine.XEngine.Script.BuiltIn_Commands_BaseClass { \r\n" +
377 @"public Script() { } " +
378 compileScript +
379 "} }\r\n";
380 return compileScript;
381 }
382
383 private static string CreateVBCompilerScript(string compileScript)
384 {
385 compileScript = String.Empty +
386 "Imports OpenSim.Region.ScriptEngine.XEngine.Script: Imports System.Collections.Generic: " +
387 String.Empty + "NameSpace SecondLife:" +
388 String.Empty + "Public Class Script: Inherits OpenSim.Region.ScriptEngine.XEngine.Script.BuiltIn_Commands_BaseClass: " +
389 "\r\nPublic Sub New()\r\nEnd Sub: " +
390 compileScript +
391 ":End Class :End Namespace\r\n";
392 return compileScript;
393 }
394
395 /// <summary>
396 /// Compile .NET script to .Net assembly (.dll)
397 /// </summary>
398 /// <param name="Script">CS script</param>
399 /// <returns>Filename to .dll assembly</returns>
400 internal string CompileFromDotNetText(string Script, enumCompileType lang, string asset)
401 {
402 string ext = "." + lang.ToString();
403
404 // Output assembly name
405 scriptCompileCounter++;
406 string OutFile = Path.Combine(ScriptEnginesPath, Path.Combine(
407 m_scriptEngine.World.RegionInfo.RegionID.ToString(),
408 FilePrefix + "_compiled_" + asset + ".dll"));
409#if DEBUG
410// m_scriptEngine.Log.Debug("[" + m_scriptEngine.ScriptEngineName + "]: Starting compile of \"" + OutFile + "\".");
411#endif
412 try
413 {
414 File.Delete(OutFile);
415 }
416 catch (Exception e) // NOTLEGIT - Should be just catching FileIOException
417 {
418 //m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: Unable to delete old existring script-file before writing new. Compile aborted: " + e.ToString());
419 throw new Exception("Unable to delete old existring script-file before writing new. Compile aborted: " + e.ToString());
420 }
421 //string OutFile = Path.Combine("ScriptEngines", "SecondLife.Script.dll");
422
423 // DEBUG - write source to disk
424 if (WriteScriptSourceToDebugFile)
425 {
426 string srcFileName = FilePrefix + "_source_" + Path.GetFileNameWithoutExtension(OutFile) + ext;
427 try
428 {
429 File.WriteAllText(
430 Path.Combine("ScriptEngines", srcFileName),
431 Script);
432 }
433 catch (Exception ex) // NOTLEGIT - Should be just catching FileIOException
434 {
435 m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: Exception while trying to write script source to file \"" + srcFileName + "\": " + ex.ToString());
436 }
437 }
438
439 // Do actual compile
440 CompilerParameters parameters = new CompilerParameters();
441
442 parameters.IncludeDebugInformation = true;
443
444 // Add all available assemblies
445// foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies())
446// {
447// Console.WriteLine("Adding assembly: " + asm.Location);
448// parameters.ReferencedAssemblies.Add(asm.Location);
449// }
450
451 string rootPath = Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory);
452 string rootPathSE = Path.GetDirectoryName(GetType().Assembly.Location);
453 //Console.WriteLine("Assembly location: " + rootPath);
454 parameters.ReferencedAssemblies.Add(Path.Combine(rootPath, "OpenSim.Region.ScriptEngine.XEngine.Script.dll"));
455// parameters.ReferencedAssemblies.Add(Path.Combine(rootPathSE, "OpenSim.Region.ScriptEngine.XEngine.dll"));
456
457 //parameters.ReferencedAssemblies.Add("OpenSim.Region.Environment");
458 parameters.GenerateExecutable = false;
459 parameters.OutputAssembly = OutFile;
460 parameters.IncludeDebugInformation = CompileWithDebugInformation;
461 //parameters.WarningLevel = 1; // Should be 4?
462 parameters.TreatWarningsAsErrors = false;
463
464//Console.WriteLine(Script);
465 CompilerResults results;
466 switch (lang)
467 {
468 case enumCompileType.vb:
469 results = VBcodeProvider.CompileAssemblyFromSource(parameters, Script);
470 break;
471 case enumCompileType.cs:
472 results = CScodeProvider.CompileAssemblyFromSource(parameters, Script);
473 break;
474 case enumCompileType.js:
475 results = JScodeProvider.CompileAssemblyFromSource(parameters, Script);
476 break;
477 default:
478 throw new Exception("Compiler is not able to recongnize language type \"" + lang.ToString() + "\"");
479 }
480
481 // Check result
482 // Go through errors
483
484 //
485 // WARNINGS AND ERRORS
486 //
487 if (results.Errors.Count > 0)
488 {
489 string errtext = String.Empty;
490 foreach (CompilerError CompErr in results.Errors)
491 {
492 errtext += "Line number " + (CompErr.Line - LinesToRemoveOnError) +
493 ", Error Number: " + CompErr.ErrorNumber +
494 ", '" + CompErr.ErrorText + "'\r\n";
495 }
496 if (!File.Exists(OutFile))
497 {
498 throw new Exception(errtext);
499 }
500 }
501
502
503 //
504 // NO ERRORS, BUT NO COMPILED FILE
505 //
506 if (!File.Exists(OutFile))
507 {
508 string errtext = String.Empty;
509 errtext += "No compile error. But not able to locate compiled file.";
510 throw new Exception(errtext);
511 }
512 return OutFile;
513 }
514 }
515}
diff --git a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs
new file mode 100644
index 0000000..734c837
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs
@@ -0,0 +1,293 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using libsecondlife;
30using OpenSim.Framework;
31using OpenSim.Region.Environment.Modules.Avatar.Currency.SampleMoney;
32using OpenSim.Region.Environment.Scenes;
33using OpenSim.Region.Environment.Interfaces;
34using OpenSim.Region.ScriptEngine.XEngine.Script;
35using Axiom.Math;
36
37namespace OpenSim.Region.ScriptEngine.XEngine
38{
39 /// <summary>
40 /// Prepares events so they can be directly executed upon a script by EventQueueManager, then queues it.
41 /// </summary>
42 public class EventManager
43 {
44 private XEngine myScriptEngine;
45
46 public EventManager(XEngine _ScriptEngine)
47 {
48 myScriptEngine = _ScriptEngine;
49
50 myScriptEngine.Log.Info("[XEngine] Hooking up to server events");
51 myScriptEngine.World.EventManager.OnObjectGrab += touch_start;
52 myScriptEngine.World.EventManager.OnObjectDeGrab += touch_end;
53 myScriptEngine.World.EventManager.OnScriptChangedEvent += changed;
54 myScriptEngine.World.EventManager.OnScriptAtTargetEvent += at_target;
55 myScriptEngine.World.EventManager.OnScriptNotAtTargetEvent += not_at_target;
56 myScriptEngine.World.EventManager.OnScriptControlEvent += control;
57 IMoneyModule money=myScriptEngine.World.RequestModuleInterface<IMoneyModule>();
58 if (money != null)
59 {
60 money.OnObjectPaid+=HandleObjectPaid;
61 }
62 }
63
64 private void HandleObjectPaid(LLUUID objectID, LLUUID agentID,
65 int amount)
66 {
67 SceneObjectPart part =
68 myScriptEngine.World.GetSceneObjectPart(objectID);
69
70 if (part != null)
71 {
72 money(part.LocalId, agentID, amount);
73 }
74 }
75
76 public void touch_start(uint localID, LLVector3 offsetPos,
77 IClientAPI remoteClient)
78 {
79 // Add to queue for all scripts in ObjectID object
80 XDetectParams[] det = new XDetectParams[1];
81 det[0].Key = remoteClient.AgentId;
82
83 myScriptEngine.PostObjectEvent(localID, new XEventParams(
84 "touch_start", new Object[] { new LSL_Types.LSLInteger(1) },
85 det));
86 }
87
88 public void touch(uint localID, LLVector3 offsetPos,
89 IClientAPI remoteClient)
90 {
91 // Add to queue for all scripts in ObjectID object
92 XDetectParams[] det = new XDetectParams[1];
93 det[0].Key = remoteClient.AgentId;
94 det[0].OffsetPos = new LSL_Types.Vector3(offsetPos.X,
95 offsetPos.Y,
96 offsetPos.Z);
97
98 myScriptEngine.PostObjectEvent(localID, new XEventParams(
99 "touch", new Object[] { new LSL_Types.LSLInteger(1) },
100 det));
101 }
102
103 public void touch_end(uint localID, IClientAPI remoteClient)
104 {
105 // Add to queue for all scripts in ObjectID object
106 XDetectParams[] det = new XDetectParams[1];
107 det[0].Key = remoteClient.AgentId;
108
109 myScriptEngine.PostObjectEvent(localID, new XEventParams(
110 "touch_end", new Object[] { new LSL_Types.LSLInteger(1) },
111 det));
112 }
113
114 public void changed(uint localID, uint change)
115 {
116 // Add to queue for all scripts in localID, Object pass change.
117 myScriptEngine.PostObjectEvent(localID, new XEventParams(
118 "changed",new object[] { new LSL_Types.LSLInteger(change) },
119 new XDetectParams[0]));
120 }
121
122 // state_entry: not processed here
123 // state_exit: not processed here
124
125 public void money(uint localID, LLUUID agentID, int amount)
126 {
127 myScriptEngine.PostObjectEvent(localID, new XEventParams(
128 "money", new object[] {
129 new LSL_Types.LSLString(agentID.ToString()),
130 new LSL_Types.LSLInteger(amount) },
131 new XDetectParams[0]));
132 }
133
134 public void collision_start(uint localID, LLUUID itemID,
135 IClientAPI remoteClient)
136 {
137 // Add to queue for all scripts in ObjectID object
138 XDetectParams[] det = new XDetectParams[1];
139 det[0].Key = remoteClient.AgentId;
140
141 myScriptEngine.PostObjectEvent(localID, new XEventParams(
142 "collision_start",
143 new Object[] { new LSL_Types.LSLInteger(1) },
144 det));
145 }
146
147 public void collision(uint localID, LLUUID itemID,
148 IClientAPI remoteClient)
149 {
150 // Add to queue for all scripts in ObjectID object
151 XDetectParams[] det = new XDetectParams[1];
152 det[0].Key = remoteClient.AgentId;
153
154 myScriptEngine.PostObjectEvent(localID, new XEventParams(
155 "collision", new Object[] { new LSL_Types.LSLInteger(1) },
156 det));
157 }
158
159 public void collision_end(uint localID, LLUUID itemID,
160 IClientAPI remoteClient)
161 {
162 // Add to queue for all scripts in ObjectID object
163 XDetectParams[] det = new XDetectParams[1];
164 det[0].Key = remoteClient.AgentId;
165
166 myScriptEngine.PostObjectEvent(localID, new XEventParams(
167 "collision_end",
168 new Object[] { new LSL_Types.LSLInteger(1) },
169 det));
170 }
171
172 public void land_collision_start(uint localID, LLUUID itemID)
173 {
174 myScriptEngine.PostObjectEvent(localID, new XEventParams(
175 "land_collision_start",
176 new object[0],
177 new XDetectParams[0]));
178 }
179
180 public void land_collision(uint localID, LLUUID itemID)
181 {
182 myScriptEngine.PostObjectEvent(localID, new XEventParams(
183 "land_collision",
184 new object[0],
185 new XDetectParams[0]));
186 }
187
188 public void land_collision_end(uint localID, LLUUID itemID)
189 {
190 myScriptEngine.PostObjectEvent(localID, new XEventParams(
191 "land_collision_end",
192 new object[0],
193 new XDetectParams[0]));
194 }
195
196 // timer: not handled here
197 // listen: not handled here
198
199 public void on_rez(uint localID, LLUUID itemID, int startParam)
200 {
201 myScriptEngine.PostObjectEvent(localID, new XEventParams(
202 "on_rez",new object[] {
203 new LSL_Types.LSLInteger(startParam)},
204 new XDetectParams[0]));
205 }
206
207 public void control(uint localID, LLUUID itemID, LLUUID agentID, uint held, uint change)
208 {
209 myScriptEngine.PostObjectEvent(localID, new XEventParams(
210 "control",new object[] {
211 new LSL_Types.LSLString(agentID.ToString()),
212 new LSL_Types.LSLInteger(held),
213 new LSL_Types.LSLInteger(change)},
214 new XDetectParams[0]));
215 }
216
217 public void email(uint localID, LLUUID itemID, string timeSent,
218 string address, string subject, string message, int numLeft)
219 {
220 myScriptEngine.PostObjectEvent(localID, new XEventParams(
221 "email",new object[] {
222 new LSL_Types.LSLString(timeSent),
223 new LSL_Types.LSLString(address),
224 new LSL_Types.LSLString(subject),
225 new LSL_Types.LSLString(message),
226 new LSL_Types.LSLInteger(numLeft)},
227 new XDetectParams[0]));
228 }
229
230 public void at_target(uint localID, uint handle, LLVector3 targetpos,
231 LLVector3 atpos)
232 {
233 myScriptEngine.PostObjectEvent(localID, new XEventParams(
234 "at_target", new object[] {
235 new LSL_Types.LSLInteger(handle),
236 new LSL_Types.Vector3(targetpos.X,targetpos.Y,targetpos.Z),
237 new LSL_Types.Vector3(atpos.X,atpos.Y,atpos.Z) },
238 new XDetectParams[0]));
239 }
240
241 public void not_at_target(uint localID)
242 {
243 myScriptEngine.PostObjectEvent(localID, new XEventParams(
244 "not_at_target",new object[0],
245 new XDetectParams[0]));
246 }
247
248 public void at_rot_target(uint localID, LLUUID itemID)
249 {
250 myScriptEngine.PostObjectEvent(localID, new XEventParams(
251 "at_rot_target",new object[0],
252 new XDetectParams[0]));
253 }
254
255 public void not_at_rot_target(uint localID, LLUUID itemID)
256 {
257 myScriptEngine.PostObjectEvent(localID, new XEventParams(
258 "not_at_rot_target",new object[0],
259 new XDetectParams[0]));
260 }
261
262 // run_time_permissions: not handled here
263
264 public void attach(uint localID, LLUUID itemID, LLUUID avatar)
265 {
266 myScriptEngine.PostObjectEvent(localID, new XEventParams(
267 "attach",new object[] {
268 new LSL_Types.LSLString(avatar.ToString()) },
269 new XDetectParams[0]));
270 }
271
272 // dataserver: not handled here
273 // link_message: not handled here
274
275 public void moving_start(uint localID, LLUUID itemID)
276 {
277 myScriptEngine.PostObjectEvent(localID, new XEventParams(
278 "moving_start",new object[0],
279 new XDetectParams[0]));
280 }
281
282 public void moving_end(uint localID, LLUUID itemID)
283 {
284 myScriptEngine.PostObjectEvent(localID, new XEventParams(
285 "moving_end",new object[0],
286 new XDetectParams[0]));
287 }
288
289 // object_rez: not handled here
290 // remote_data: not handled here
291 // http_response: not handled here
292 }
293}
diff --git a/OpenSim/Region/ScriptEngine/XEngine/Executor.cs b/OpenSim/Region/ScriptEngine/XEngine/Executor.cs
new file mode 100644
index 0000000..40075ec
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/XEngine/Executor.cs
@@ -0,0 +1,136 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using OpenSim.Region.ScriptEngine.XEngine.Script;
32
33namespace OpenSim.Region.ScriptEngine.XEngine
34{
35 public class Executor : ExecutorBase
36 {
37 // Cache functions by keeping a reference to them in a dictionary
38 private Dictionary<string, MethodInfo> Events = new Dictionary<string, MethodInfo>();
39 private Dictionary<string, scriptEvents> m_stateEvents = new Dictionary<string, scriptEvents>();
40
41 public Executor(IScript script) : base(script)
42 {
43 initEventFlags();
44 }
45
46
47 protected override scriptEvents DoGetStateEventFlags()
48 {
49 //Console.WriteLine("Get event flags for " + m_Script.State);
50
51 // Check to see if we've already computed the flags for this state
52 scriptEvents eventFlags = scriptEvents.None;
53 if (m_stateEvents.ContainsKey(m_Script.State))
54 {
55 m_stateEvents.TryGetValue(m_Script.State, out eventFlags);
56 return eventFlags;
57 }
58
59 Type type=m_Script.GetType();
60
61 // Fill in the events for this state, cache the results in the map
62 foreach (KeyValuePair<string, scriptEvents> kvp in m_eventFlagsMap)
63 {
64 string evname = m_Script.State + "_event_" + kvp.Key;
65 //Console.WriteLine("Trying event "+evname);
66 try
67 {
68 MethodInfo mi = type.GetMethod(evname);
69 if (mi != null)
70 {
71 //Console.WriteLine("Found handler for " + kvp.Key);
72 eventFlags |= kvp.Value;
73 }
74 }
75 catch(Exception e)
76 {
77 //Console.WriteLine("Exeption in GetMethod:\n"+e.ToString());
78 }
79 }
80
81 // Save the flags we just computed and return the result
82 if(eventFlags != 0)
83 m_stateEvents.Add(m_Script.State, eventFlags);
84
85 //Console.WriteLine("Returning {0:x}", eventFlags);
86 return (eventFlags);
87 }
88
89 protected override void DoExecuteEvent(string FunctionName, object[] args)
90 {
91 // IMPORTANT: Types and MemberInfo-derived objects require a LOT of memory.
92 // Instead use RuntimeTypeHandle, RuntimeFieldHandle and RunTimeHandle (IntPtr) instead!
93
94 string EventName = m_Script.State + "_event_" + FunctionName;
95
96//#if DEBUG
97// Console.WriteLine("ScriptEngine: Script event function name: " + EventName);
98//#endif
99
100 if (Events.ContainsKey(EventName) == false)
101 {
102 // Not found, create
103 Type type = m_Script.GetType();
104 try
105 {
106 MethodInfo mi = type.GetMethod(EventName);
107 Events.Add(EventName, mi);
108 }
109 catch
110 {
111 Console.WriteLine("Event {0}not found", EventName);
112 // Event name not found, cache it as not found
113 Events.Add(EventName, null);
114 }
115 }
116
117 // Get event
118 MethodInfo ev = null;
119 Events.TryGetValue(EventName, out ev);
120
121 if (ev == null) // No event by that name!
122 {
123 //Console.WriteLine("ScriptEngine Can not find any event named: \String.Empty + EventName + "\String.Empty);
124 return;
125 }
126
127//cfk 2-7-08 dont need this right now and the default Linux build has DEBUG defined
128#if DEBUG
129 //Console.WriteLine("ScriptEngine: Executing function name: " + EventName);
130#endif
131 // Found
132 ev.Invoke(m_Script, args);
133
134 }
135 }
136}
diff --git a/OpenSim/Region/ScriptEngine/XEngine/ExecutorBase.cs b/OpenSim/Region/ScriptEngine/XEngine/ExecutorBase.cs
new file mode 100644
index 0000000..3775372
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/XEngine/ExecutorBase.cs
@@ -0,0 +1,181 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Runtime.Remoting.Lifetime;
31using OpenSim.Region.ScriptEngine.XEngine.Script;
32
33namespace OpenSim.Region.ScriptEngine.XEngine
34{
35 public abstract class ExecutorBase : MarshalByRefObject
36 {
37 /// <summary>
38 /// Contains the script to execute functions in.
39 /// </summary>
40 protected IScript m_Script;
41
42 protected Dictionary<string, scriptEvents> m_eventFlagsMap = new Dictionary<string, scriptEvents>();
43
44 [Flags]
45 public enum scriptEvents : int
46 {
47 None = 0,
48 attach = 1,
49 collision = 15,
50 collision_end = 32,
51 collision_start = 64,
52 control = 128,
53 dataserver = 256,
54 email = 512,
55 http_response = 1024,
56 land_collision = 2048,
57 land_collision_end = 4096,
58 land_collision_start = 8192,
59 at_target = 16384,
60 listen = 32768,
61 money = 65536,
62 moving_end = 131072,
63 moving_start = 262144,
64 not_at_rot_target = 524288,
65 not_at_target = 1048576,
66 remote_data = 8388608,
67 run_time_permissions = 268435456,
68 state_entry = 1073741824,
69 state_exit = 2,
70 timer = 4,
71 touch = 8,
72 touch_end = 536870912,
73 touch_start = 2097152,
74 object_rez = 4194304
75 }
76
77 /// <summary>
78 /// Create a new instance of ExecutorBase
79 /// </summary>
80 /// <param name="Script"></param>
81 public ExecutorBase(IScript Script)
82 {
83 m_Script = Script;
84 initEventFlags();
85 }
86
87 /// <summary>
88 /// Make sure our object does not timeout when in AppDomain. (Called by ILease base class)
89 /// </summary>
90 /// <returns></returns>
91 public override Object InitializeLifetimeService()
92 {
93 //Console.WriteLine("Executor: InitializeLifetimeService()");
94 // return null;
95 ILease lease = (ILease)base.InitializeLifetimeService();
96
97 if (lease.CurrentState == LeaseState.Initial)
98 {
99 lease.InitialLeaseTime = TimeSpan.Zero; // TimeSpan.FromMinutes(1);
100 // lease.SponsorshipTimeout = TimeSpan.FromMinutes(2);
101 // lease.RenewOnCallTime = TimeSpan.FromSeconds(2);
102 }
103 return lease;
104 }
105
106 /// <summary>
107 /// Get current AppDomain
108 /// </summary>
109 /// <returns>Current AppDomain</returns>
110 public AppDomain GetAppDomain()
111 {
112 return AppDomain.CurrentDomain;
113 }
114
115 /// <summary>
116 /// Execute a specific function/event in script.
117 /// </summary>
118 /// <param name="FunctionName">Name of function to execute</param>
119 /// <param name="args">Arguments to pass to function</param>
120 public void ExecuteEvent(string FunctionName, object[] args)
121 {
122 DoExecuteEvent(FunctionName, args);
123 }
124
125 protected abstract void DoExecuteEvent(string FunctionName, object[] args);
126
127 /// <summary>
128 /// Compute the events handled by the current state of the script
129 /// </summary>
130 /// <returns>state mask</returns>
131 public scriptEvents GetStateEventFlags()
132 {
133 return DoGetStateEventFlags();
134 }
135
136 protected abstract scriptEvents DoGetStateEventFlags();
137
138 protected void initEventFlags()
139 {
140 // Initialize the table if it hasn't already been done
141 if (m_eventFlagsMap.Count > 0)
142 {
143 return;
144 }
145
146 m_eventFlagsMap.Add("attach", scriptEvents.attach);
147 // m_eventFlagsMap.Add("at_rot_target",(long)scriptEvents.at_rot_target);
148 m_eventFlagsMap.Add("at_target", scriptEvents.at_target);
149 // m_eventFlagsMap.Add("changed",(long)scriptEvents.changed);
150 m_eventFlagsMap.Add("collision", scriptEvents.collision);
151 m_eventFlagsMap.Add("collision_end", scriptEvents.collision_end);
152 m_eventFlagsMap.Add("collision_start", scriptEvents.collision_start);
153 m_eventFlagsMap.Add("control", scriptEvents.control);
154 m_eventFlagsMap.Add("dataserver", scriptEvents.dataserver);
155 m_eventFlagsMap.Add("email", scriptEvents.email);
156 m_eventFlagsMap.Add("http_response", scriptEvents.http_response);
157 m_eventFlagsMap.Add("land_collision", scriptEvents.land_collision);
158 m_eventFlagsMap.Add("land_collision_end", scriptEvents.land_collision_end);
159 m_eventFlagsMap.Add("land_collision_start", scriptEvents.land_collision_start);
160 // m_eventFlagsMap.Add("link_message",scriptEvents.link_message);
161 m_eventFlagsMap.Add("listen", scriptEvents.listen);
162 m_eventFlagsMap.Add("money", scriptEvents.money);
163 m_eventFlagsMap.Add("moving_end", scriptEvents.moving_end);
164 m_eventFlagsMap.Add("moving_start", scriptEvents.moving_start);
165 m_eventFlagsMap.Add("not_at_rot_target", scriptEvents.not_at_rot_target);
166 m_eventFlagsMap.Add("not_at_target", scriptEvents.not_at_target);
167 // m_eventFlagsMap.Add("no_sensor",(long)scriptEvents.no_sensor);
168 // m_eventFlagsMap.Add("on_rez",(long)scriptEvents.on_rez);
169 m_eventFlagsMap.Add("remote_data", scriptEvents.remote_data);
170 m_eventFlagsMap.Add("run_time_permissions", scriptEvents.run_time_permissions);
171 // m_eventFlagsMap.Add("sensor",(long)scriptEvents.sensor);
172 m_eventFlagsMap.Add("state_entry", scriptEvents.state_entry);
173 m_eventFlagsMap.Add("state_exit", scriptEvents.state_exit);
174 m_eventFlagsMap.Add("timer", scriptEvents.timer);
175 m_eventFlagsMap.Add("touch", scriptEvents.touch);
176 m_eventFlagsMap.Add("touch_end", scriptEvents.touch_end);
177 m_eventFlagsMap.Add("touch_start", scriptEvents.touch_start);
178 m_eventFlagsMap.Add("object_rez", scriptEvents.object_rez);
179 }
180 }
181}
diff --git a/OpenSim/Region/ScriptEngine/XEngine/LSL2CSConverter.cs b/OpenSim/Region/ScriptEngine/XEngine/LSL2CSConverter.cs
new file mode 100644
index 0000000..9c59108
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/XEngine/LSL2CSConverter.cs
@@ -0,0 +1,363 @@
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
29using System;
30using System.Collections.Generic;
31using System.Text.RegularExpressions;
32
33namespace OpenSim.Region.ScriptEngine.XEngine
34{
35 public class LSL2CSConverter
36 {
37 // Uses regex to convert LSL code to C# code.
38
39 //private Regex rnw = new Regex(@"[a-zA-Z0-9_\-]", RegexOptions.Compiled);
40 private Dictionary<string, string> dataTypes = new Dictionary<string, string>();
41 private Dictionary<string, string> quotes = new Dictionary<string, string>();
42 // c Style
43 private Regex cstylecomments = new Regex(@"/\*(.|[\r\n])*?\*/", RegexOptions.Compiled | RegexOptions.Multiline);
44 // c# one liners
45 private Regex nonCommentFwsl = new Regex("\"[a-zA-Z0-9.,:/\\n ]+//[^\"+]+([\\\\\\\"+]+)?(\\s+)?[\"+](\\s+)?(;)?", RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline);
46 private Regex conelinecomments = new Regex(@"[^:].?([\/]{2}[^\n]*)|([\n]{1,}[\/]{2}[^\n]*)", RegexOptions.Compiled | RegexOptions.Multiline);
47 // ([^\"])((?:[a-zA-Z])\.[a-zA-Z].?)([^\"])
48
49 // value we're looking for: (?:[a-zA-Z])\.[a-zA-Z]
50 public LSL2CSConverter()
51 {
52 // Only the types we need to convert
53 dataTypes.Add("void", "void");
54 dataTypes.Add("integer", "LSL_Types.LSLInteger");
55 dataTypes.Add("float", "double");
56 dataTypes.Add("string", "LSL_Types.LSLString");
57 dataTypes.Add("key", "LSL_Types.LSLString");
58 dataTypes.Add("vector", "LSL_Types.Vector3");
59 dataTypes.Add("rotation", "LSL_Types.Quaternion");
60 dataTypes.Add("list", "LSL_Types.list");
61 dataTypes.Add("null", "null");
62 }
63
64 public string Convert(string Script)
65 {
66 quotes.Clear();
67 string Return = String.Empty;
68 Script = " \r\n" + Script;
69
70 //
71 // Prepare script for processing
72 //
73
74 // Clean up linebreaks
75 Script = Regex.Replace(Script, @"\r\n", "\n");
76 Script = Regex.Replace(Script, @"\n", "\r\n");
77
78 // QUOTE REPLACEMENT
79 // temporarily replace quotes so we can work our magic on the script without
80 // always considering if we are inside our outside quotes's
81 // TODO: Does this work on half-quotes in strings? ;)
82 string _Script = String.Empty;
83 string C;
84 bool in_quote = false;
85 bool quote_replaced = false;
86 string quote_replacement_string = "Q_U_O_T_E_REPLACEMENT_";
87 string quote = String.Empty;
88 bool last_was_escape = false;
89 int quote_replaced_count = 0;
90
91 string removefwnoncomments = nonCommentFwsl.Replace(Script, "\"\";");
92
93 string removecomments = conelinecomments.Replace(removefwnoncomments, "");
94 removecomments = cstylecomments.Replace(removecomments, "");
95 string[] localscript = removecomments.Split('"');
96 string checkscript = String.Empty;
97 bool flip = true;
98
99 for (int p = 0; p < localscript.Length; p++)
100 {
101 //if (localscript[p].Length >= 1)
102 //{
103 if (!localscript[p].EndsWith(@"\"))
104 {
105 flip = !flip;
106 //System.Console.WriteLine("Flip:" + flip.ToString() + " - " + localscript[p] + " ! " + localscript[p].EndsWith(@"\").ToString());
107 }
108 //}
109 //else
110 //{
111 // flip = !flip;
112 // System.Console.WriteLine("Flip:" + flip.ToString() + " - " + localscript[p]);
113 //}
114 if (!flip)
115 checkscript += localscript[p];
116 }
117
118 //System.Console.WriteLine("SCRIPT:" + checkscript);
119
120 // checks for alpha.alpha way of referring to objects in C#
121 // ignores alpha.x alpha.y, alpha.z for refering to vector components
122 Match SecurityM;
123
124 // BROKEN: this check is very wrong. It block's any url in strings.
125 SecurityM = Regex.Match(checkscript, @"(?:[a-zA-Z])\.(?:[a-wA-Z]|[a-zA-Z][a-zA-Z])", RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline);
126
127 if (SecurityM.Success)
128 throw new Exception("CS0103: 'The . symbol cannot be used in LSL except in float values or vector components'. Detected around: " + SecurityM.Captures[0].Value);
129
130 SecurityM = Regex.Match(checkscript, @"typeof\s", RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline);
131 if (SecurityM.Success)
132 throw new Exception("CS0103: 'The object.typeof method isn't allowed in LSL'");
133
134 SecurityM = Regex.Match(checkscript, @"GetType\(", RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline);
135 if (SecurityM.Success)
136 throw new Exception("CS0103: 'The object.GetType method isn't allowed in LSL'");
137
138 for (int p = 0; p < Script.Length; p++)
139 {
140 C = Script.Substring(p, 1);
141 while (true)
142 {
143 // found " and last was not \ so this is not an escaped \"
144 if (C == "\"" && last_was_escape == false)
145 {
146 // Toggle inside/outside quote
147 in_quote = !in_quote;
148 if (in_quote)
149 {
150 quote_replaced_count++;
151 }
152 else
153 {
154 if (quote == String.Empty)
155 {
156 // We didn't replace quote, probably because of empty string?
157 _Script += quote_replacement_string +
158 quote_replaced_count.ToString().PadLeft(5, "0".ToCharArray()[0]);
159 }
160 // We just left a quote
161 quotes.Add(
162 quote_replacement_string +
163 quote_replaced_count.ToString().PadLeft(5, "0".ToCharArray()[0]), quote);
164 quote = String.Empty;
165 }
166 break;
167 }
168
169 if (!in_quote)
170 {
171 // We are not inside a quote
172 quote_replaced = false;
173 }
174 else
175 {
176 // We are inside a quote
177 if (!quote_replaced)
178 {
179 // Replace quote
180 _Script += quote_replacement_string +
181 quote_replaced_count.ToString().PadLeft(5, "0".ToCharArray()[0]);
182 quote_replaced = true;
183 }
184 quote += C;
185 break;
186 }
187 _Script += C;
188 break;
189 }
190 last_was_escape = false;
191 if (C == @"\")
192 {
193 last_was_escape = true;
194 }
195 }
196 Script = _Script;
197 //
198 // END OF QUOTE REPLACEMENT
199 //
200
201 //
202 // PROCESS STATES
203 // Remove state definitions and add state names to start of each event within state
204 //
205 int ilevel = 0;
206 int lastlevel = 0;
207 string ret = String.Empty;
208 string cache = String.Empty;
209 bool in_state = false;
210 string current_statename = String.Empty;
211 for (int p = 0; p < Script.Length; p++)
212 {
213 C = Script.Substring(p, 1);
214 while (true)
215 {
216 // inc / dec level
217 if (C == @"{")
218 ilevel++;
219 if (C == @"}")
220 ilevel--;
221 if (ilevel < 0)
222 ilevel = 0;
223 cache += C;
224
225 // if level == 0, add to return
226 if (ilevel == 1 && lastlevel == 0)
227 {
228 // 0 => 1: Get last
229 Match m =
230 //Regex.Match(cache, @"(?![a-zA-Z_]+)\s*([a-zA-Z_]+)[^a-zA-Z_\(\)]*{",
231 Regex.Match(cache, @"(?![a-zA-Z_]+)\s*(state\s+)?(?<statename>[a-zA-Z_][a-zA-Z_0-9]*)[^a-zA-Z_0-9\(\)]*{",
232
233 RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline);
234
235 in_state = false;
236 if (m.Success)
237 {
238 // Go back to level 0, this is not a state
239 in_state = true;
240 current_statename = m.Groups["statename"].Captures[0].Value;
241 //Console.WriteLine("Current statename: " + current_statename);
242 cache =
243 //@"(?<s1>(?![a-zA-Z_]+)\s*)" + @"([a-zA-Z_]+)(?<s2>[^a-zA-Z_\(\)]*){",
244 Regex.Replace(cache,
245 @"(?<s1>(?![a-zA-Z_]+)\s*)" + @"(state\s+)?([a-zA-Z_][a-zA-Z_0-9]*)(?<s2>[^a-zA-Z_0-9\(\)]*){",
246 "${s1}${s2}",
247 RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.IgnoreCase);
248 }
249 ret += cache;
250 cache = String.Empty;
251 }
252 if (ilevel == 0 && lastlevel == 1)
253 {
254 // 1 => 0: Remove last }
255 if (in_state == true)
256 {
257 cache = cache.Remove(cache.Length - 1, 1);
258 //cache = Regex.Replace(cache, "}$", String.Empty, RegexOptions.Multiline | RegexOptions.Singleline);
259
260 //Replace function names
261 // void dataserver(key query_id, string data) {
262 //cache = Regex.Replace(cache, @"([^a-zA-Z_]\s*)((?!if|switch|for)[a-zA-Z_]+\s*\([^\)]*\)[^{]*{)", "$1" + "<STATE>" + "$2", RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline);
263 //Console.WriteLine("Replacing using statename: " + current_statename);
264 cache =
265 Regex.Replace(cache,
266 @"^(\s*)((?!(if|switch|for|while)[^a-zA-Z0-9_])[a-zA-Z0-9_]*\s*\([^\)]*\)[^;]*\{)",
267 @"$1public " + current_statename + "_event_$2",
268 RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.IgnoreCase);
269 }
270
271 ret += cache;
272 cache = String.Empty;
273 in_state = true;
274 current_statename = String.Empty;
275 }
276
277 break;
278 }
279 lastlevel = ilevel;
280 }
281 ret += cache;
282 cache = String.Empty;
283
284 Script = ret;
285 ret = String.Empty;
286
287 foreach (string key in dataTypes.Keys)
288 {
289 string val;
290 dataTypes.TryGetValue(key, out val);
291
292 // Replace CAST - (integer) with (int)
293 Script =
294 Regex.Replace(Script, @"\(" + key + @"\)", @"(" + val + ")",
295 RegexOptions.Compiled | RegexOptions.Multiline);
296 // Replace return types and function variables - integer a() and f(integer a, integer a)
297 Script =
298 Regex.Replace(Script, @"(^|;|}|[\(,])(\s*)" + key + @"(\s+)", @"$1$2" + val + "$3",
299 RegexOptions.Compiled | RegexOptions.Multiline);
300 Script =
301 Regex.Replace(Script, @"(^|;|}|[\(,])(\s*)" + key + @"(\s*)[,]", @"$1$2" + val + "$3,",
302 RegexOptions.Compiled | RegexOptions.Multiline);
303 }
304
305 // Add "void" in front of functions that needs it
306 Script =
307 Regex.Replace(Script,
308 @"^(\s*public\s+)?((?!(if|switch|for)[^a-zA-Z0-9_])[a-zA-Z0-9_]*\s*\([^\)]*\)[^;]*\{)",
309 @"$1void $2", RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline);
310
311 // Replace <x,y,z> and <x,y,z,r>
312 Script =
313 Regex.Replace(Script, @"<([^,>;]*,[^,>;]*,[^,>;]*,[^,>;]*)>", @"new LSL_Types.Quaternion($1)",
314 RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline);
315 Script =
316 Regex.Replace(Script, @"<([^,>;)]*,[^,>;]*,[^,>;]*)>", @"new LSL_Types.Vector3($1)",
317 RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline);
318
319 // Replace List []'s
320 Script =
321 Regex.Replace(Script, @"\[([^\]]*)\]", @"new LSL_Types.list($1)",
322 RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline);
323
324 // Replace (string) to .ToString() //
325 Script =
326 Regex.Replace(Script, @"\(string\)\s*([a-zA-Z0-9_.]+(\s*\([^\)]*\))?)", @"$1.ToString()",
327 RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline);
328 Script =
329 Regex.Replace(Script, @"\((float|int)\)\s*([a-zA-Z0-9_.]+(\s*\([^\)]*\))?)", @"$1.Parse($2)",
330 RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline);
331
332 // Replace "state STATENAME" with "state("statename")"
333 Script =
334 Regex.Replace(Script, @"(state)\s+([^;\n\r]+)(;[\r\n\s])", "$1(\"$2\")$3",
335 RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.IgnoreCase);
336
337 // REPLACE BACK QUOTES
338 foreach (string key in quotes.Keys)
339 {
340 string val;
341 quotes.TryGetValue(key, out val);
342 Script = Script.Replace(key, "\"" + val + "\"");
343 }
344
345 //System.Console.WriteLine(Script);
346 Return = String.Empty;// +
347 //"using OpenSim.Region.ScriptEngine.Common; using System.Collections.Generic;";
348
349 //Return += String.Empty +
350 // "namespace SecondLife { ";
351 //Return += String.Empty +
352 // //"[Serializable] " +
353 // "public class Script : OpenSim.Region.ScriptEngine.Common.LSL_BaseClass { ";
354 //Return += @"public Script() { } ";
355 Return += Script;
356 //Return += "} }\r\n";
357
358 quotes.Clear();
359
360 return Return;
361 }
362 }
363}
diff --git a/OpenSim/Region/ScriptEngine/XEngine/LSL_ScriptCommands.cs b/OpenSim/Region/ScriptEngine/XEngine/LSL_ScriptCommands.cs
new file mode 100644
index 0000000..ca209b6
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/XEngine/LSL_ScriptCommands.cs
@@ -0,0 +1,6474 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Runtime.Remoting.Lifetime;
32using System.Text;
33using System.Threading;
34using Axiom.Math;
35using libsecondlife;
36using OpenSim.Framework;
37using OpenSim.Region.Environment;
38using OpenSim.Region.Environment.Interfaces;
39using OpenSim.Region.Environment.Modules.Avatar.Currency.SampleMoney;
40using OpenSim.Region.Environment.Modules.World.Land;
41using OpenSim.Region.Environment.Scenes;
42using OpenSim.Region.ScriptEngine.XEngine;
43using OpenSim.Region.ScriptEngine.XEngine.Script;
44
45
46namespace OpenSim.Region.ScriptEngine.XEngine
47{
48 /// <summary>
49 /// Contains all LSL ll-functions. This class will be in Default AppDomain.
50 /// </summary>
51 public class LSL_ScriptCommands : MarshalByRefObject, ILSL_ScriptCommands
52 {
53 // private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
54
55 internal XEngine m_ScriptEngine;
56 internal XScriptInstance m_Instance;
57 internal SceneObjectPart m_host;
58 internal uint m_localID;
59 internal LLUUID m_itemID;
60 internal bool throwErrorOnNotImplemented = true;
61
62 public LSL_ScriptCommands(XEngine ScriptEngine, XScriptInstance instance, SceneObjectPart host, uint localID, LLUUID itemID)
63 {
64 m_ScriptEngine = ScriptEngine;
65 m_Instance = instance;
66 m_host = host;
67 m_localID = localID;
68 m_itemID = itemID;
69
70 //m_log.Info(ScriptEngineName, "LSL_BaseClass.Start() called. Hosted by [" + m_host.Name + ":" + m_host.UUID + "@" + m_host.AbsolutePosition + "]");
71 }
72
73 private DateTime m_timer = DateTime.Now;
74 private string m_state = "default";
75 private bool m_waitingForScriptAnswer=false;
76
77
78 public string State
79 {
80 get { return m_Instance.State; }
81 set { m_Instance.State = value; }
82 }
83
84 public void state(string newState)
85 {
86 m_Instance.SetState(newState);
87 }
88
89 // Object never expires
90 public override Object InitializeLifetimeService()
91 {
92 //Console.WriteLine("LSL_BuiltIn_Commands: InitializeLifetimeService()");
93 // return null;
94 ILease lease = (ILease)base.InitializeLifetimeService();
95
96 if (lease.CurrentState == LeaseState.Initial)
97 {
98 lease.InitialLeaseTime = TimeSpan.Zero; // TimeSpan.FromMinutes(1);
99 // lease.SponsorshipTimeout = TimeSpan.FromMinutes(2);
100 // lease.RenewOnCallTime = TimeSpan.FromSeconds(2);
101 }
102 return lease;
103 }
104
105 public Scene World
106 {
107 get { return m_ScriptEngine.World; }
108 }
109
110 public void llSay(int channelID, string text)
111 {
112 m_host.AddScriptLPS(1);
113
114 if(text.Length > 1023)
115 text=text.Substring(0, 1023);
116
117 World.SimChat(Helpers.StringToField(text),
118 ChatTypeEnum.Say, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID, false);
119
120 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
121 wComm.DeliverMessage(ChatTypeEnum.Say, channelID, m_host.Name, m_host.UUID, text);
122 }
123
124 // Extension commands use this:
125 public ICommander GetCommander(string name)
126 {
127 return World.GetCommander(name);
128 }
129
130 private LLUUID InventorySelf()
131 {
132 LLUUID invItemID=new LLUUID();
133
134 foreach (KeyValuePair<LLUUID, TaskInventoryItem> inv in m_host.TaskInventory)
135 {
136 if (inv.Value.Type == 10 && inv.Value.ItemID == m_itemID)
137 {
138 invItemID=inv.Key;
139 break;
140 }
141 }
142
143 return invItemID;
144 }
145
146 private LLUUID InventoryKey(string name, int type)
147 {
148 m_host.AddScriptLPS(1);
149 foreach (KeyValuePair<LLUUID, TaskInventoryItem> inv in m_host.TaskInventory)
150 {
151 if (inv.Value.Name == name)
152 {
153 if (inv.Value.Type != type)
154 return LLUUID.Zero;
155
156 return inv.Value.AssetID.ToString();
157 }
158 }
159 return LLUUID.Zero;
160 }
161
162 private LLUUID InventoryKey(string name)
163 {
164 m_host.AddScriptLPS(1);
165 foreach (KeyValuePair<LLUUID, TaskInventoryItem> inv in m_host.TaskInventory)
166 {
167 if (inv.Value.Name == name)
168 {
169 return inv.Value.AssetID.ToString();
170 }
171 }
172 return LLUUID.Zero;
173 }
174
175 public void osSetRegionWaterHeight(double height)
176 {
177 m_host.AddScriptLPS(1);
178 //Check to make sure that the script's owner is the estate manager/master
179 //World.Permissions.GenericEstatePermission(
180 if (World.ExternalChecks.ExternalChecksCanBeGodLike(m_host.OwnerID))
181 {
182 World.EventManager.TriggerRequestChangeWaterHeight((float)height);
183 }
184 }
185
186 //These are the implementations of the various ll-functions used by the LSL scripts.
187 //starting out, we use the System.Math library for trig functions. - ckrinke 8-14-07
188 public double llSin(double f)
189 {
190 m_host.AddScriptLPS(1);
191 return (double)Math.Sin(f);
192 }
193
194 public double llCos(double f)
195 {
196 m_host.AddScriptLPS(1);
197 return (double)Math.Cos(f);
198 }
199
200 public double llTan(double f)
201 {
202 m_host.AddScriptLPS(1);
203 return (double)Math.Tan(f);
204 }
205
206 public double llAtan2(double x, double y)
207 {
208 m_host.AddScriptLPS(1);
209 return (double)Math.Atan2(y, x);
210 }
211
212 public double llSqrt(double f)
213 {
214 m_host.AddScriptLPS(1);
215 return (double)Math.Sqrt(f);
216 }
217
218 public double llPow(double fbase, double fexponent)
219 {
220 m_host.AddScriptLPS(1);
221 return (double)Math.Pow(fbase, fexponent);
222 }
223
224 public LSL_Types.LSLInteger llAbs(int i)
225 {
226 m_host.AddScriptLPS(1);
227 return (int)Math.Abs(i);
228 }
229
230 public double llFabs(double f)
231 {
232 m_host.AddScriptLPS(1);
233 return (double)Math.Abs(f);
234 }
235
236 public double llFrand(double mag)
237 {
238 m_host.AddScriptLPS(1);
239 lock (Util.RandomClass)
240 {
241 return Util.RandomClass.NextDouble() * mag;
242 }
243 }
244
245 public LSL_Types.LSLInteger llFloor(double f)
246 {
247 m_host.AddScriptLPS(1);
248 return (int)Math.Floor(f);
249 }
250
251 public LSL_Types.LSLInteger llCeil(double f)
252 {
253 m_host.AddScriptLPS(1);
254 return (int)Math.Ceiling(f);
255 }
256
257 // Xantor 01/May/2008 fixed midpointrounding (2.5 becomes 3.0 instead of 2.0, default = ToEven)
258 public LSL_Types.LSLInteger llRound(double f)
259 {
260 m_host.AddScriptLPS(1);
261 return (int)Math.Round(f, MidpointRounding.AwayFromZero);
262 }
263
264 //This next group are vector operations involving squaring and square root. ckrinke
265 public double llVecMag(LSL_Types.Vector3 v)
266 {
267 m_host.AddScriptLPS(1);
268 return LSL_Types.Vector3.Mag(v);
269 }
270
271 public LSL_Types.Vector3 llVecNorm(LSL_Types.Vector3 v)
272 {
273 m_host.AddScriptLPS(1);
274 double mag = LSL_Types.Vector3.Mag(v);
275 LSL_Types.Vector3 nor = new LSL_Types.Vector3();
276 nor.x = v.x / mag;
277 nor.y = v.y / mag;
278 nor.z = v.z / mag;
279 return nor;
280 }
281
282 public double llVecDist(LSL_Types.Vector3 a, LSL_Types.Vector3 b)
283 {
284 m_host.AddScriptLPS(1);
285 double dx = a.x - b.x;
286 double dy = a.y - b.y;
287 double dz = a.z - b.z;
288 return Math.Sqrt(dx * dx + dy * dy + dz * dz);
289 }
290
291 //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke
292
293 // Utility function for llRot2Euler
294
295 // normalize an angle between 0 - 2*PI (0 and 360 degrees)
296 private double NormalizeAngle(double angle)
297 {
298 angle = angle % (Math.PI * 2);
299 if (angle < 0) angle = angle + Math.PI * 2;
300 return angle;
301 }
302
303
304 // Old implementation of llRot2Euler, now normalized
305
306 public LSL_Types.Vector3 llRot2Euler(LSL_Types.Quaternion r)
307 {
308 m_host.AddScriptLPS(1);
309 //This implementation is from http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions. ckrinke
310 LSL_Types.Quaternion t = new LSL_Types.Quaternion(r.x * r.x, r.y * r.y, r.z * r.z, r.s * r.s);
311 double m = (t.x + t.y + t.z + t.s);
312 if (m == 0) return new LSL_Types.Vector3();
313 double n = 2 * (r.y * r.s + r.x * r.z);
314 double p = m * m - n * n;
315 if (p > 0)
316 return new LSL_Types.Vector3(NormalizeAngle(Math.Atan2(2.0 * (r.x * r.s - r.y * r.z), (-t.x - t.y + t.z + t.s))),
317 NormalizeAngle(Math.Atan2(n, Math.Sqrt(p))),
318 NormalizeAngle(Math.Atan2(2.0 * (r.z * r.s - r.x * r.y), (t.x - t.y - t.z + t.s))));
319 else if (n > 0)
320 return new LSL_Types.Vector3(0.0, Math.PI / 2, NormalizeAngle(Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z)));
321 else
322 return new LSL_Types.Vector3(0.0, -Math.PI / 2, NormalizeAngle(Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z)));
323 }
324
325
326 // Xantor's newer llEuler2Rot() *try the second* inverted quaternions (-x,-y,-z,w) as LL seems to like
327 // New and improved, now actually works as described. Prim rotates as expected as does llRot2Euler.
328
329 /* From wiki:
330 The Euler angle vector (in radians) is converted to a rotation by doing the rotations around the 3 axes
331 in Z, Y, X order. So llEuler2Rot(<1.0, 2.0, 3.0> * DEG_TO_RAD) generates a rotation by taking the zero rotation,
332 a vector pointing along the X axis, first rotating it 3 degrees around the global Z axis, then rotating the resulting
333 vector 2 degrees around the global Y axis, and finally rotating that 1 degree around the global X axis.
334 */
335
336 public LSL_Types.Quaternion llEuler2Rot(LSL_Types.Vector3 v)
337 {
338 m_host.AddScriptLPS(1);
339
340 double x,y,z,s,s_i;
341
342 double cosX = Math.Cos(v.x);
343 double cosY = Math.Cos(v.y);
344 double cosZ = Math.Cos(v.z);
345 double sinX = Math.Sin(v.x);
346 double sinY = Math.Sin(v.y);
347 double sinZ = Math.Sin(v.z);
348
349 s = Math.Sqrt(cosY * cosZ - sinX * sinY * sinZ + cosX * cosZ + cosX * cosY + 1.0f) * 0.5f;
350 if (Math.Abs(s) < 0.00001) // null rotation
351 {
352 x = 0.0f;
353 y = 1.0f;
354 z = 0.0f;
355 }
356 else
357 {
358 s_i = 1.0f / (4.0f * s);
359 x = - (-sinX * cosY - cosX * sinY * sinZ - sinX * cosZ) * s_i;
360 y = - (-cosX * sinY * cosZ + sinX * sinZ - sinY) * s_i;
361 z = - (-cosY * sinZ - sinX * sinY * cosZ - cosX * sinZ) * s_i;
362 }
363 return new LSL_Types.Quaternion(x, y, z, s);
364 }
365
366
367 public LSL_Types.Quaternion llAxes2Rot(LSL_Types.Vector3 fwd, LSL_Types.Vector3 left, LSL_Types.Vector3 up)
368 {
369 m_host.AddScriptLPS(1);
370 NotImplemented("llAxes2Rot");
371 return new LSL_Types.Quaternion();
372 }
373
374 public LSL_Types.Vector3 llRot2Fwd(LSL_Types.Quaternion r)
375 {
376 m_host.AddScriptLPS(1);
377 return (new LSL_Types.Vector3(1,0,0) * r);
378 }
379
380 public LSL_Types.Vector3 llRot2Left(LSL_Types.Quaternion r)
381 {
382 m_host.AddScriptLPS(1);
383 return (new LSL_Types.Vector3(0, 1, 0) * r);
384 }
385
386 public LSL_Types.Vector3 llRot2Up(LSL_Types.Quaternion r)
387 {
388 m_host.AddScriptLPS(1);
389 return (new LSL_Types.Vector3(0, 0, 1) * r);
390 }
391 public LSL_Types.Quaternion llRotBetween(LSL_Types.Vector3 a, LSL_Types.Vector3 b)
392 {
393 //A and B should both be normalized
394 m_host.AddScriptLPS(1);
395 double dotProduct = LSL_Types.Vector3.Dot(a, b);
396 LSL_Types.Vector3 crossProduct = LSL_Types.Vector3.Cross(a, b);
397 double magProduct = LSL_Types.Vector3.Mag(a) * LSL_Types.Vector3.Mag(b);
398 double angle = Math.Acos(dotProduct / magProduct);
399 LSL_Types.Vector3 axis = LSL_Types.Vector3.Norm(crossProduct);
400 double s = Math.Sin(angle / 2);
401
402 return new LSL_Types.Quaternion(axis.x * s, axis.y * s, axis.z * s, (float)Math.Cos(angle / 2));
403 }
404 public void llWhisper(int channelID, string text)
405 {
406 m_host.AddScriptLPS(1);
407
408 if(text.Length > 1023)
409 text=text.Substring(0, 1023);
410
411 World.SimChat(Helpers.StringToField(text),
412 ChatTypeEnum.Whisper, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID, false);
413
414 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
415 wComm.DeliverMessage(ChatTypeEnum.Whisper, channelID, m_host.Name, m_host.UUID, text);
416 }
417
418 public void llShout(int channelID, string text)
419 {
420 m_host.AddScriptLPS(1);
421
422 if(text.Length > 1023)
423 text=text.Substring(0, 1023);
424
425 World.SimChat(Helpers.StringToField(text),
426 ChatTypeEnum.Shout, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID, true);
427
428 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
429 wComm.DeliverMessage(ChatTypeEnum.Shout, channelID, m_host.Name, m_host.UUID, text);
430 }
431
432 public void llRegionSay(int channelID, string text)
433 {
434 if (channelID == 0)
435 {
436 LSLError("Cannot use llRegionSay() on channel 0");
437 return;
438 }
439
440
441 if(text.Length > 1023)
442 text=text.Substring(0, 1023);
443
444 m_host.AddScriptLPS(1);
445
446 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
447 wComm.DeliverMessage(ChatTypeEnum.Region, channelID, m_host.Name, m_host.UUID, text);
448 }
449
450 public LSL_Types.LSLInteger llListen(int channelID, string name, string ID, string msg)
451 {
452 m_host.AddScriptLPS(1);
453 LLUUID keyID;
454 LLUUID.TryParse(ID, out keyID);
455 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
456 return wComm.Listen(m_localID, m_itemID, m_host.UUID, channelID, name, keyID, msg);
457 }
458
459 public void llListenControl(int number, int active)
460 {
461 m_host.AddScriptLPS(1);
462 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
463 wComm.ListenControl(m_itemID, number, active);
464 }
465
466 public void llListenRemove(int number)
467 {
468 m_host.AddScriptLPS(1);
469 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
470 wComm.ListenRemove(m_itemID, number);
471 }
472
473 public void llSensor(string name, string id, int type, double range, double arc)
474 {
475 m_host.AddScriptLPS(1);
476 LLUUID keyID = LLUUID.Zero;
477 LLUUID.TryParse(id, out keyID);
478
479 m_ScriptEngine.m_ASYNCLSLCommandManager.m_SensorRepeat.SenseOnce(m_localID, m_itemID, name, keyID, type, range, arc, m_host);
480 }
481
482 public void llSensorRepeat(string name, string id, int type, double range, double arc, double rate)
483 {
484 m_host.AddScriptLPS(1);
485 LLUUID keyID = LLUUID.Zero;
486 LLUUID.TryParse(id, out keyID);
487
488 m_ScriptEngine.m_ASYNCLSLCommandManager.m_SensorRepeat.SetSenseRepeatEvent(m_localID, m_itemID, name, keyID, type, range, arc, rate, m_host);
489 }
490
491 public void llSensorRemove()
492 {
493 m_host.AddScriptLPS(1);
494 m_ScriptEngine.m_ASYNCLSLCommandManager.m_SensorRepeat.UnSetSenseRepeaterEvents(m_localID, m_itemID);
495 }
496
497 public string resolveName(LLUUID objecUUID)
498 {
499 // try avatar username surname
500 UserProfileData profile = World.CommsManager.UserService.GetUserProfile(objecUUID);
501 if (profile != null)
502 {
503 string avatarname = profile.FirstName + " " + profile.SurName;
504 return avatarname;
505 }
506 // try an scene object
507 SceneObjectPart SOP = World.GetSceneObjectPart(objecUUID);
508 if (SOP != null)
509 {
510 string objectname = SOP.Name;
511 return objectname;
512 }
513
514 EntityBase SensedObject;
515 lock (World.Entities)
516 {
517 World.Entities.TryGetValue(objecUUID, out SensedObject);
518 }
519
520 if (SensedObject == null)
521 return String.Empty;
522 return SensedObject.Name;
523
524 }
525
526 public string llDetectedName(int number)
527 {
528 m_host.AddScriptLPS(1);
529 LLUUID sensedUUID = m_ScriptEngine.GetDetectID(m_itemID, number);
530 if(sensedUUID != null)
531 return resolveName(sensedUUID);
532 return String.Empty;
533 }
534
535 public LLUUID uuidDetectedKey(int number)
536 {
537 return m_ScriptEngine.GetDetectID(m_itemID, number);
538 }
539
540 public EntityBase entityDetectedKey(int number)
541 {
542 LLUUID sensedUUID = m_ScriptEngine.GetDetectID(m_itemID, number);
543 if(sensedUUID != null)
544 {
545 EntityBase SensedObject = null;
546 lock (World.Entities)
547 {
548 World.Entities.TryGetValue(sensedUUID, out SensedObject);
549 }
550 return SensedObject;
551 }
552 return null;
553 }
554
555 public string llDetectedKey(int number)
556 {
557 m_host.AddScriptLPS(1);
558 LLUUID SensedUUID = uuidDetectedKey(number);
559 if (SensedUUID == LLUUID.Zero)
560 return String.Empty;
561
562 return SensedUUID.ToString();
563 }
564
565 public string llDetectedOwner(int number)
566 {
567 // returns UUID of owner of object detected
568 m_host.AddScriptLPS(1);
569 EntityBase SensedObject = entityDetectedKey(number);
570 if (SensedObject ==null)
571 return String.Empty;
572 LLUUID SensedUUID = uuidDetectedKey(number);
573 if (World.GetScenePresence(SensedUUID) == null)
574 {
575 // sensed object is not an avatar
576 // so get the owner of the sensed object
577 SceneObjectPart SOP = World.GetSceneObjectPart(SensedUUID);
578 if (SOP != null) { return SOP.ObjectOwner.ToString(); }
579 }
580 else
581 {
582 // sensed object is an avatar, and so must be its own owner
583 return SensedUUID.ToString();
584 }
585
586
587 return String.Empty;
588
589 }
590
591 public LSL_Types.LSLInteger llDetectedType(int number)
592 {
593 m_host.AddScriptLPS(1);
594 EntityBase SensedObject = entityDetectedKey(number);
595 if (SensedObject == null)
596 return 0;
597 int mask = 0;
598
599 LLUUID SensedUUID = uuidDetectedKey(number);
600 LSL_Types.Vector3 ZeroVector = new LSL_Types.Vector3(0, 0, 0);
601
602 if (World.GetScenePresence(SensedUUID) != null) mask |= 0x01; // actor
603 if (SensedObject.Velocity.Equals(ZeroVector))
604 mask |= 0x04; // passive non-moving
605 else
606 mask |= 0x02; // active moving
607 if (SensedObject is IScript) mask |= 0x08; // Scripted. It COULD have one hidden ...
608 return mask;
609
610 }
611
612 public LSL_Types.Vector3 llDetectedPos(int number)
613 {
614 m_host.AddScriptLPS(1);
615 EntityBase SensedObject = entityDetectedKey(number);
616 if (SensedObject == null)
617 return new LSL_Types.Vector3(0, 0, 0);
618
619 return new LSL_Types.Vector3(SensedObject.AbsolutePosition.X,SensedObject.AbsolutePosition.Y,SensedObject.AbsolutePosition.Z);
620 }
621
622 public LSL_Types.Vector3 llDetectedVel(int number)
623 {
624 m_host.AddScriptLPS(1);
625 EntityBase SensedObject = entityDetectedKey(number);
626 if (SensedObject == null)
627 return new LSL_Types.Vector3(0, 0, 0);
628
629 return new LSL_Types.Vector3(SensedObject.Velocity.X, SensedObject.Velocity.Y, SensedObject.Velocity.Z);
630 // return new LSL_Types.Vector3();
631 }
632
633 public LSL_Types.Vector3 llDetectedGrab(int number)
634 {
635 m_host.AddScriptLPS(1);
636 XDetectParams parms = m_ScriptEngine.GetDetectParams(m_itemID, number);
637
638 return parms.OffsetPos;
639 }
640
641 public LSL_Types.Quaternion llDetectedRot(int number)
642 {
643 m_host.AddScriptLPS(1);
644 EntityBase SensedObject = entityDetectedKey(number);
645 if (SensedObject == null)
646 return new LSL_Types.Quaternion();
647
648 return new LSL_Types.Quaternion(SensedObject.Rotation.x, SensedObject.Rotation.y, SensedObject.Rotation.z, SensedObject.Rotation.w);
649 }
650
651 public LSL_Types.LSLInteger llDetectedGroup(int number)
652 {
653 m_host.AddScriptLPS(1);
654 NotImplemented("llDetectedGroup");
655 return 0;
656 }
657
658 public LSL_Types.LSLInteger llDetectedLinkNumber(int number)
659 {
660 m_host.AddScriptLPS(1);
661 NotImplemented("llDetectedLinkNumber");
662 return 0;
663 }
664
665 public void llDie()
666 {
667 m_host.AddScriptLPS(1);
668 World.DeleteSceneObject(m_host.ParentGroup);
669 }
670
671 public double llGround(LSL_Types.Vector3 offset)
672 {
673 m_host.AddScriptLPS(1);
674 int x = (int)(m_host.AbsolutePosition.X + offset.x);
675 int y = (int)(m_host.AbsolutePosition.Y + offset.y);
676 return World.GetLandHeight(x, y);
677 }
678
679 public double llCloud(LSL_Types.Vector3 offset)
680 {
681 m_host.AddScriptLPS(1);
682 NotImplemented("llCloud");
683 return 0;
684 }
685
686 public LSL_Types.Vector3 llWind(LSL_Types.Vector3 offset)
687 {
688 m_host.AddScriptLPS(1);
689 NotImplemented("llWind");
690 return new LSL_Types.Vector3();
691 }
692
693 public void llSetStatus(int status, int value)
694 {
695 m_host.AddScriptLPS(1);
696
697 int statusrotationaxis = 0;
698
699 if ((status & BuiltIn_Commands_BaseClass.STATUS_PHYSICS) == BuiltIn_Commands_BaseClass.STATUS_PHYSICS)
700 {
701 if (value == 1)
702 m_host.ScriptSetPhysicsStatus(true);
703 else
704 m_host.ScriptSetPhysicsStatus(false);
705
706 }
707 if ((status & BuiltIn_Commands_BaseClass.STATUS_PHANTOM) == BuiltIn_Commands_BaseClass.STATUS_PHANTOM)
708 {
709 if (value == 1)
710 m_host.ScriptSetPhantomStatus(true);
711 else
712 m_host.ScriptSetPhantomStatus(false);
713 }
714 if ((status & BuiltIn_Commands_BaseClass.STATUS_CAST_SHADOWS) == BuiltIn_Commands_BaseClass.STATUS_CAST_SHADOWS)
715 {
716 m_host.AddFlag(LLObject.ObjectFlags.CastShadows);
717 }
718 if ((status & BuiltIn_Commands_BaseClass.STATUS_ROTATE_X) == BuiltIn_Commands_BaseClass.STATUS_ROTATE_X)
719 {
720 statusrotationaxis |= BuiltIn_Commands_BaseClass.STATUS_ROTATE_X;
721
722 }
723 if ((status & BuiltIn_Commands_BaseClass.STATUS_ROTATE_Y) == BuiltIn_Commands_BaseClass.STATUS_ROTATE_Y)
724 {
725 statusrotationaxis |= BuiltIn_Commands_BaseClass.STATUS_ROTATE_Y;
726 }
727 if ((status & BuiltIn_Commands_BaseClass.STATUS_ROTATE_Z) == BuiltIn_Commands_BaseClass.STATUS_ROTATE_Z)
728 {
729 statusrotationaxis |= BuiltIn_Commands_BaseClass.STATUS_ROTATE_Z;
730 }
731 if ((status & BuiltIn_Commands_BaseClass.STATUS_BLOCK_GRAB) == BuiltIn_Commands_BaseClass.STATUS_BLOCK_GRAB)
732 {
733 NotImplemented("llSetStatus - STATUS_BLOCK_GRAB");
734 }
735 if ((status & BuiltIn_Commands_BaseClass.STATUS_DIE_AT_EDGE) == BuiltIn_Commands_BaseClass.STATUS_DIE_AT_EDGE)
736 {
737 if (value == 1)
738 m_host.SetDieAtEdge(true);
739 else
740 m_host.SetDieAtEdge(false);
741 }
742 if ((status & BuiltIn_Commands_BaseClass.STATUS_RETURN_AT_EDGE) == BuiltIn_Commands_BaseClass.STATUS_RETURN_AT_EDGE)
743 {
744 NotImplemented("llSetStatus - STATUS_RETURN_AT_EDGE");
745 }
746 if ((status & BuiltIn_Commands_BaseClass.STATUS_SANDBOX) == BuiltIn_Commands_BaseClass.STATUS_SANDBOX)
747 {
748 NotImplemented("llSetStatus - STATUS_SANDBOX");
749 }
750 if (statusrotationaxis != 0)
751 {
752 m_host.SetAxisRotation(statusrotationaxis, value);
753
754 }
755 }
756
757 public LSL_Types.LSLInteger llGetStatus(int status)
758 {
759 m_host.AddScriptLPS(1);
760 // Console.WriteLine(m_host.UUID.ToString() + " status is " + m_host.GetEffectiveObjectFlags().ToString());
761 switch (status)
762 {
763 case BuiltIn_Commands_BaseClass.STATUS_PHYSICS:
764 if ((m_host.GetEffectiveObjectFlags() & (uint)LLObject.ObjectFlags.Physics) == (uint)LLObject.ObjectFlags.Physics)
765 {
766 return 1;
767 }
768 return 0;
769 case BuiltIn_Commands_BaseClass.STATUS_PHANTOM:
770 if ((m_host.GetEffectiveObjectFlags() & (uint)LLObject.ObjectFlags.Phantom) == (uint)LLObject.ObjectFlags.Phantom)
771 {
772 return 1;
773 }
774 return 0;
775 case BuiltIn_Commands_BaseClass.STATUS_CAST_SHADOWS:
776 if ((m_host.GetEffectiveObjectFlags() & (uint)LLObject.ObjectFlags.CastShadows) == (uint)LLObject.ObjectFlags.CastShadows)
777 {
778 return 1;
779 }
780 return 0;
781 case BuiltIn_Commands_BaseClass.STATUS_BLOCK_GRAB:
782 NotImplemented("llGetStatus - STATUS_BLOCK_GRAB");
783 return 0;
784 case BuiltIn_Commands_BaseClass.STATUS_DIE_AT_EDGE:
785
786 if (m_host.GetDieAtEdge())
787 return 1;
788 else
789 return 0;
790
791 case BuiltIn_Commands_BaseClass.STATUS_RETURN_AT_EDGE:
792 NotImplemented("llGetStatus - STATUS_RETURN_AT_EDGE");
793 return 0;
794 case BuiltIn_Commands_BaseClass.STATUS_ROTATE_X:
795 NotImplemented("llGetStatus - STATUS_ROTATE_X");
796 return 0;
797 case BuiltIn_Commands_BaseClass.STATUS_ROTATE_Y:
798 NotImplemented("llGetStatus - STATUS_ROTATE_Y");
799 return 0;
800 case BuiltIn_Commands_BaseClass.STATUS_ROTATE_Z:
801 NotImplemented("llGetStatus - STATUS_ROTATE_Z");
802 return 0;
803 case BuiltIn_Commands_BaseClass.STATUS_SANDBOX:
804 NotImplemented("llGetStatus - STATUS_SANDBOX");
805 return 0;
806 }
807 return 0;
808 }
809
810 public void llSetScale(LSL_Types.Vector3 scale)
811 {
812 m_host.AddScriptLPS(1);
813 SetScale(m_host, scale);
814 }
815
816 private void SetScale(SceneObjectPart part, LSL_Types.Vector3 scale)
817 {
818 // TODO: this needs to trigger a persistance save as well
819 LLVector3 tmp = part.Scale;
820 tmp.X = (float)scale.x;
821 tmp.Y = (float)scale.y;
822 tmp.Z = (float)scale.z;
823 part.Scale = tmp;
824 part.SendFullUpdateToAllClients();
825 }
826
827 public LSL_Types.Vector3 llGetScale()
828 {
829 m_host.AddScriptLPS(1);
830 return new LSL_Types.Vector3(m_host.Scale.X, m_host.Scale.Y, m_host.Scale.Z);
831 }
832
833 public void llSetColor(LSL_Types.Vector3 color, int face)
834 {
835 m_host.AddScriptLPS(1);
836
837 SetColor(m_host, color, face);
838 }
839
840 private void SetColor(SceneObjectPart part, LSL_Types.Vector3 color, int face)
841 {
842 LLObject.TextureEntry tex = part.Shape.Textures;
843 LLColor texcolor;
844 if (face > -1)
845 {
846 texcolor = tex.CreateFace((uint)face).RGBA;
847 texcolor.R = (float)Math.Abs(color.x - 1);
848 texcolor.G = (float)Math.Abs(color.y - 1);
849 texcolor.B = (float)Math.Abs(color.z - 1);
850 tex.FaceTextures[face].RGBA = texcolor;
851 part.UpdateTexture(tex);
852 return;
853 }
854 else if (face == -1)
855 {
856 for (uint i = 0; i < 32; i++)
857 {
858 if (tex.FaceTextures[i] != null)
859 {
860 texcolor = tex.FaceTextures[i].RGBA;
861 texcolor.R = (float)Math.Abs(color.x - 1);
862 texcolor.G = (float)Math.Abs(color.y - 1);
863 texcolor.B = (float)Math.Abs(color.z - 1);
864 tex.FaceTextures[i].RGBA = texcolor;
865 }
866 texcolor = tex.DefaultTexture.RGBA;
867 texcolor.R = (float)Math.Abs(color.x - 1);
868 texcolor.G = (float)Math.Abs(color.y - 1);
869 texcolor.B = (float)Math.Abs(color.z - 1);
870 tex.DefaultTexture.RGBA = texcolor;
871 }
872 part.UpdateTexture(tex);
873 return;
874 }
875 }
876
877 public double llGetAlpha(int face)
878 {
879 m_host.AddScriptLPS(1);
880 LLObject.TextureEntry tex = m_host.Shape.Textures;
881 if (face == -1) // TMP: Until we can determine number of sides, ALL_SIDES (-1) will return default color
882 {
883 return (double)((tex.DefaultTexture.RGBA.A * 255) / 255);
884 }
885 if (face > -1)
886 {
887 return (double)((tex.GetFace((uint)face).RGBA.A * 255) / 255);
888 }
889 return 0;
890 }
891
892 public void llSetAlpha(double alpha, int face)
893 {
894 m_host.AddScriptLPS(1);
895
896 SetAlpha(m_host, alpha, face);
897 }
898
899 private void SetAlpha(SceneObjectPart part, double alpha, int face)
900 {
901 LLObject.TextureEntry tex = part.Shape.Textures;
902 LLColor texcolor;
903 if (face > -1)
904 {
905 texcolor = tex.CreateFace((uint)face).RGBA;
906 texcolor.A = (float)Math.Abs(alpha - 1);
907 tex.FaceTextures[face].RGBA = texcolor;
908 part.UpdateTexture(tex);
909 return;
910 }
911 else if (face == -1)
912 {
913 for (int i = 0; i < 32; i++)
914 {
915 if (tex.FaceTextures[i] != null)
916 {
917 texcolor = tex.FaceTextures[i].RGBA;
918 texcolor.A = (float)Math.Abs(alpha - 1);
919 tex.FaceTextures[i].RGBA = texcolor;
920 }
921 }
922 texcolor = tex.DefaultTexture.RGBA;
923 texcolor.A = (float)Math.Abs(alpha - 1);
924 tex.DefaultTexture.RGBA = texcolor;
925 part.UpdateTexture(tex);
926 return;
927 }
928 }
929
930 public LSL_Types.Vector3 llGetColor(int face)
931 {
932 m_host.AddScriptLPS(1);
933 LLObject.TextureEntry tex = m_host.Shape.Textures;
934 LLColor texcolor;
935 LSL_Types.Vector3 rgb;
936 if (face == -1) // TMP: Until we can determine number of sides, ALL_SIDES (-1) will return default color
937 {
938 texcolor = tex.DefaultTexture.RGBA;
939 rgb.x = (255 - (texcolor.R * 255)) / 255;
940 rgb.y = (255 - (texcolor.G * 255)) / 255;
941 rgb.z = (255 - (texcolor.B * 255)) / 255;
942 return rgb;
943 }
944 if (face > -1)
945 {
946 texcolor = tex.GetFace((uint)face).RGBA;
947 rgb.x = (255 - (texcolor.R * 255)) / 255;
948 rgb.y = (255 - (texcolor.G * 255)) / 255;
949 rgb.z = (255 - (texcolor.B * 255)) / 255;
950 return rgb;
951 }
952 else
953 {
954 return new LSL_Types.Vector3();
955 }
956 }
957
958 public void llSetTexture(string texture, int face)
959 {
960 m_host.AddScriptLPS(1);
961 SetTexture(m_host, texture, face);
962 }
963
964 private void SetTexture(SceneObjectPart part, string texture, int face)
965 {
966 LLUUID textureID=new LLUUID();
967
968 if (!LLUUID.TryParse(texture, out textureID))
969 {
970 textureID=InventoryKey(texture, (int)AssetType.Texture);
971 }
972
973 if (textureID == LLUUID.Zero)
974 return;
975
976 LLObject.TextureEntry tex = part.Shape.Textures;
977
978 if (face > -1)
979 {
980 LLObject.TextureEntryFace texface = tex.CreateFace((uint)face);
981 texface.TextureID = textureID;
982 tex.FaceTextures[face] = texface;
983 part.UpdateTexture(tex);
984 return;
985 }
986 else if (face == -1)
987 {
988 for (uint i = 0; i < 32; i++)
989 {
990 if (tex.FaceTextures[i] != null)
991 {
992 tex.FaceTextures[i].TextureID = textureID;
993 }
994 }
995 tex.DefaultTexture.TextureID = textureID;
996 part.UpdateTexture(tex);
997 return;
998 }
999 }
1000
1001 public void llScaleTexture(double u, double v, int face)
1002 {
1003 m_host.AddScriptLPS(1);
1004
1005 ScaleTexture(m_host, u, v, face);
1006 }
1007
1008 private void ScaleTexture(SceneObjectPart part, double u, double v, int face)
1009 {
1010 LLObject.TextureEntry tex = part.Shape.Textures;
1011 if (face > -1)
1012 {
1013 LLObject.TextureEntryFace texface = tex.CreateFace((uint)face);
1014 texface.RepeatU = (float)u;
1015 texface.RepeatV = (float)v;
1016 tex.FaceTextures[face] = texface;
1017 part.UpdateTexture(tex);
1018 return;
1019 }
1020 if (face == -1)
1021 {
1022 for (int i = 0; i < 32; i++)
1023 {
1024 if (tex.FaceTextures[i] != null)
1025 {
1026 tex.FaceTextures[i].RepeatU = (float)u;
1027 tex.FaceTextures[i].RepeatV = (float)v;
1028 }
1029 }
1030 tex.DefaultTexture.RepeatU = (float)u;
1031 tex.DefaultTexture.RepeatV = (float)v;
1032 part.UpdateTexture(tex);
1033 return;
1034 }
1035 }
1036
1037 public void llOffsetTexture(double u, double v, int face)
1038 {
1039 m_host.AddScriptLPS(1);
1040 OffsetTexture(m_host, u, v, face);
1041 }
1042
1043 private void OffsetTexture(SceneObjectPart part, double u, double v, int face)
1044 {
1045 LLObject.TextureEntry tex = part.Shape.Textures;
1046 if (face > -1)
1047 {
1048 LLObject.TextureEntryFace texface = tex.CreateFace((uint)face);
1049 texface.OffsetU = (float)u;
1050 texface.OffsetV = (float)v;
1051 tex.FaceTextures[face] = texface;
1052 part.UpdateTexture(tex);
1053 return;
1054 }
1055 if (face == -1)
1056 {
1057 for (int i = 0; i < 32; i++)
1058 {
1059 if (tex.FaceTextures[i] != null)
1060 {
1061 tex.FaceTextures[i].OffsetU = (float)u;
1062 tex.FaceTextures[i].OffsetV = (float)v;
1063 }
1064 }
1065 tex.DefaultTexture.OffsetU = (float)u;
1066 tex.DefaultTexture.OffsetV = (float)v;
1067 part.UpdateTexture(tex);
1068 return;
1069 }
1070 }
1071
1072 public void llRotateTexture(double rotation, int face)
1073 {
1074 m_host.AddScriptLPS(1);
1075 RotateTexture(m_host, rotation, face);
1076 }
1077
1078 private void RotateTexture(SceneObjectPart part, double rotation, int face)
1079 {
1080 LLObject.TextureEntry tex = part.Shape.Textures;
1081 if (face > -1)
1082 {
1083 LLObject.TextureEntryFace texface = tex.CreateFace((uint)face);
1084 texface.Rotation = (float)rotation;
1085 tex.FaceTextures[face] = texface;
1086 part.UpdateTexture(tex);
1087 return;
1088 }
1089 if (face == -1)
1090 {
1091 for (int i = 0; i < 32; i++)
1092 {
1093 if (tex.FaceTextures[i] != null)
1094 {
1095 tex.FaceTextures[i].Rotation = (float)rotation;
1096 }
1097 }
1098 tex.DefaultTexture.Rotation = (float)rotation;
1099 part.UpdateTexture(tex);
1100 return;
1101 }
1102 }
1103
1104 public string llGetTexture(int face)
1105 {
1106 m_host.AddScriptLPS(1);
1107 LLObject.TextureEntry tex = m_host.Shape.Textures;
1108 if (face == -1)
1109 {
1110 face = 0;
1111 }
1112 if (face > -1)
1113 {
1114 LLObject.TextureEntryFace texface;
1115 texface = tex.GetFace((uint)face);
1116 return texface.TextureID.ToString();
1117 }
1118 else
1119 {
1120 return String.Empty;
1121 }
1122 }
1123
1124 public void llSetPos(LSL_Types.Vector3 pos)
1125 {
1126 m_host.AddScriptLPS(1);
1127
1128 SetPos(m_host, pos);
1129 }
1130
1131 private void SetPos(SceneObjectPart part, LSL_Types.Vector3 pos)
1132 {
1133 if (part.ParentID != 0)
1134 {
1135 part.UpdateOffSet(new LLVector3((float)pos.x, (float)pos.y, (float)pos.z));
1136 }
1137 else
1138 {
1139 part.UpdateGroupPosition(new LLVector3((float)pos.x, (float)pos.y, (float)pos.z));
1140 }
1141 }
1142
1143 public LSL_Types.Vector3 llGetPos()
1144 {
1145 m_host.AddScriptLPS(1);
1146 return new LSL_Types.Vector3(m_host.AbsolutePosition.X,
1147 m_host.AbsolutePosition.Y,
1148 m_host.AbsolutePosition.Z);
1149 }
1150
1151 public LSL_Types.Vector3 llGetLocalPos()
1152 {
1153 m_host.AddScriptLPS(1);
1154 if (m_host.ParentID != 0)
1155 {
1156 return new LSL_Types.Vector3(m_host.OffsetPosition.X,
1157 m_host.OffsetPosition.Y,
1158 m_host.OffsetPosition.Z);
1159 }
1160 else
1161 {
1162 return new LSL_Types.Vector3(m_host.AbsolutePosition.X,
1163 m_host.AbsolutePosition.Y,
1164 m_host.AbsolutePosition.Z);
1165 }
1166 }
1167
1168 public void llSetRot(LSL_Types.Quaternion rot)
1169 {
1170 m_host.AddScriptLPS(1);
1171
1172 SetRot(m_host, rot);
1173 }
1174
1175 private void SetRot(SceneObjectPart part, LSL_Types.Quaternion rot)
1176 {
1177 part.UpdateRotation(new LLQuaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s));
1178 // Update rotation does not move the object in the physics scene if it's a linkset.
1179 part.ParentGroup.AbsolutePosition = part.ParentGroup.AbsolutePosition;
1180 }
1181
1182 public LSL_Types.Quaternion llGetRot()
1183 {
1184 m_host.AddScriptLPS(1);
1185 LLQuaternion q = m_host.RotationOffset;
1186 return new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W);
1187 }
1188
1189 public LSL_Types.Quaternion llGetLocalRot()
1190 {
1191 m_host.AddScriptLPS(1);
1192 return new LSL_Types.Quaternion(m_host.RotationOffset.X, m_host.RotationOffset.Y, m_host.RotationOffset.Z, m_host.RotationOffset.W);
1193 }
1194
1195 public void llSetForce(LSL_Types.Vector3 force, int local)
1196 {
1197 m_host.AddScriptLPS(1);
1198 NotImplemented("llSetForce");
1199 }
1200
1201 public LSL_Types.Vector3 llGetForce()
1202 {
1203 m_host.AddScriptLPS(1);
1204 NotImplemented("llGetForce");
1205 return new LSL_Types.Vector3();
1206 }
1207
1208 public LSL_Types.LSLInteger llTarget(LSL_Types.Vector3 position, double range)
1209 {
1210 m_host.AddScriptLPS(1);
1211 return m_host.registerTargetWaypoint(new LLVector3((float)position.x, (float)position.y, (float)position.z), (float)range);
1212
1213 }
1214
1215 public void llTargetRemove(int number)
1216 {
1217 m_host.AddScriptLPS(1);
1218 m_host.unregisterTargetWaypoint(number);
1219 }
1220
1221 public LSL_Types.LSLInteger llRotTarget(LSL_Types.Quaternion rot, double error)
1222 {
1223 m_host.AddScriptLPS(1);
1224 NotImplemented("llRotTarget");
1225 return 0;
1226 }
1227
1228 public void llRotTargetRemove(int number)
1229 {
1230 m_host.AddScriptLPS(1);
1231 NotImplemented("llRotTargetRemove");
1232 }
1233
1234 public void llMoveToTarget(LSL_Types.Vector3 target, double tau)
1235 {
1236 m_host.AddScriptLPS(1);
1237 m_host.MoveToTarget(new LLVector3((float)target.x, (float)target.y, (float)target.z), (float)tau);
1238 }
1239
1240 public void llStopMoveToTarget()
1241 {
1242 m_host.AddScriptLPS(1);
1243 m_host.StopMoveToTarget();
1244 }
1245
1246 public void llApplyImpulse(LSL_Types.Vector3 force, int local)
1247 {
1248 m_host.AddScriptLPS(1);
1249 //No energy force yet
1250
1251 if (force.x > 20000)
1252 force.x = 20000;
1253 if (force.y > 20000)
1254 force.y = 20000;
1255 if (force.z > 20000)
1256 force.z = 20000;
1257
1258 if (local == 1)
1259 {
1260 m_host.ApplyImpulse(new LLVector3((float)force.x, (float)force.y, (float)force.z), true);
1261 }
1262 else
1263 {
1264
1265 m_host.ApplyImpulse(new LLVector3((float)force.x,(float)force.y,(float)force.z), false);
1266 }
1267 }
1268
1269 public void llApplyRotationalImpulse(LSL_Types.Vector3 force, int local)
1270 {
1271 m_host.AddScriptLPS(1);
1272 NotImplemented("llApplyRotationalImpulse");
1273 }
1274
1275 public void llSetTorque(LSL_Types.Vector3 torque, int local)
1276 {
1277 m_host.AddScriptLPS(1);
1278 NotImplemented("llSetTorque");
1279 }
1280
1281 public LSL_Types.Vector3 llGetTorque()
1282 {
1283 m_host.AddScriptLPS(1);
1284 NotImplemented("llGetTorque");
1285 return new LSL_Types.Vector3();
1286 }
1287
1288 public void llSetForceAndTorque(LSL_Types.Vector3 force, LSL_Types.Vector3 torque, int local)
1289 {
1290 m_host.AddScriptLPS(1);
1291 NotImplemented("llSetForceAndTorque");
1292 }
1293
1294 public LSL_Types.Vector3 llGetVel()
1295 {
1296 m_host.AddScriptLPS(1);
1297 return new LSL_Types.Vector3(m_host.Velocity.X, m_host.Velocity.Y, m_host.Velocity.Z);
1298 }
1299
1300 public LSL_Types.Vector3 llGetAccel()
1301 {
1302 m_host.AddScriptLPS(1);
1303 return new LSL_Types.Vector3(m_host.Acceleration.X, m_host.Acceleration.Y, m_host.Acceleration.Z);
1304 }
1305
1306 public LSL_Types.Vector3 llGetOmega()
1307 {
1308 m_host.AddScriptLPS(1);
1309 return new LSL_Types.Vector3(m_host.RotationalVelocity.X, m_host.RotationalVelocity.Y, m_host.RotationalVelocity.Z);
1310 }
1311
1312 public double llGetTimeOfDay()
1313 {
1314 m_host.AddScriptLPS(1);
1315 NotImplemented("llGetTimeOfDay");
1316 return 0;
1317 }
1318
1319 public double llGetWallclock()
1320 {
1321 m_host.AddScriptLPS(1);
1322 return DateTime.Now.TimeOfDay.TotalSeconds;
1323 }
1324
1325 public double llGetTime()
1326 {
1327 m_host.AddScriptLPS(1);
1328 TimeSpan ScriptTime = DateTime.Now - m_timer;
1329 return (double)((ScriptTime.TotalMilliseconds / 1000)*World.TimeDilation);
1330 }
1331
1332 public void llResetTime()
1333 {
1334 m_host.AddScriptLPS(1);
1335 m_timer = DateTime.Now;
1336 }
1337
1338 public double llGetAndResetTime()
1339 {
1340 m_host.AddScriptLPS(1);
1341 TimeSpan ScriptTime = DateTime.Now - m_timer;
1342 m_timer = DateTime.Now;
1343 return (double)((ScriptTime.TotalMilliseconds / 1000)*World.TimeDilation);
1344 }
1345
1346 public void llSound()
1347 {
1348 m_host.AddScriptLPS(1);
1349 // This function has been deprecated
1350 // see http://www.lslwiki.net/lslwiki/wakka.php?wakka=llSound
1351 Deprecated("llSound");
1352 }
1353
1354 public void llPlaySound(string sound, double volume)
1355 {
1356 m_host.AddScriptLPS(1);
1357 m_host.SendSound(sound, volume, false, 0);
1358 }
1359
1360 public void llLoopSound(string sound, double volume)
1361 {
1362 m_host.AddScriptLPS(1);
1363 m_host.SendSound(sound, volume, false, 1);
1364 }
1365
1366 public void llLoopSoundMaster(string sound, double volume)
1367 {
1368 m_host.AddScriptLPS(1);
1369 NotImplemented("llLoopSoundMaster");
1370 }
1371
1372 public void llLoopSoundSlave(string sound, double volume)
1373 {
1374 m_host.AddScriptLPS(1);
1375 NotImplemented("llLoopSoundSlave");
1376 }
1377
1378 public void llPlaySoundSlave(string sound, double volume)
1379 {
1380 m_host.AddScriptLPS(1);
1381 NotImplemented("llPlaySoundSlave");
1382 }
1383
1384 public void llTriggerSound(string sound, double volume)
1385 {
1386 m_host.AddScriptLPS(1);
1387 m_host.SendSound(sound, volume, true, 0);
1388 }
1389
1390 public void llStopSound()
1391 {
1392 m_host.AddScriptLPS(1);
1393 m_host.SendSound(LLUUID.Zero.ToString(), 1.0, false, 2);
1394 }
1395
1396 public void llPreloadSound(string sound)
1397 {
1398 m_host.AddScriptLPS(1);
1399 m_host.PreloadSound(sound);
1400 }
1401
1402 /// <summary>
1403 /// Return a portion of the designated string bounded by
1404 /// inclusive indices (start and end). As usual, the negative
1405 /// indices, and the tolerance for out-of-bound values, makes
1406 /// this more complicated than it might otherwise seem.
1407 /// </summary>
1408
1409 public string llGetSubString(string src, int start, int end)
1410 {
1411
1412 m_host.AddScriptLPS(1);
1413
1414 // Normalize indices (if negative).
1415 // After normlaization they may still be
1416 // negative, but that is now relative to
1417 // the start, rather than the end, of the
1418 // sequence.
1419
1420 if (start < 0)
1421 {
1422 start = src.Length+start;
1423 }
1424 if (end < 0)
1425 {
1426 end = src.Length+end;
1427 }
1428
1429 // Conventional substring
1430 if (start <= end)
1431 {
1432 // Implies both bounds are out-of-range.
1433 if (end < 0 || start >= src.Length)
1434 {
1435 return String.Empty;
1436 }
1437 // If end is positive, then it directly
1438 // corresponds to the lengt of the substring
1439 // needed (plus one of course). BUT, it
1440 // must be within bounds.
1441 if (end >= src.Length)
1442 {
1443 end = src.Length-1;
1444 }
1445
1446 if (start < 0)
1447 {
1448 return src.Substring(0,end+1);
1449 }
1450 // Both indices are positive
1451 return src.Substring(start, (end+1) - start);
1452 }
1453
1454 // Inverted substring (end < start)
1455 else
1456 {
1457 // Implies both indices are below the
1458 // lower bound. In the inverted case, that
1459 // means the entire string will be returned
1460 // unchanged.
1461 if (start < 0)
1462 {
1463 return src;
1464 }
1465 // If both indices are greater than the upper
1466 // bound the result may seem initially counter
1467 // intuitive.
1468 if (end >= src.Length)
1469 {
1470 return src;
1471 }
1472
1473 if (end < 0)
1474 {
1475 if (start < src.Length)
1476 {
1477 return src.Substring(start);
1478 }
1479 else
1480 {
1481 return String.Empty;
1482 }
1483 }
1484 else
1485 {
1486 if (start < src.Length)
1487 {
1488 return src.Substring(0,end+1) + src.Substring(start);
1489 }
1490 else
1491 {
1492 return src.Substring(0,end+1);
1493 }
1494 }
1495 }
1496 }
1497
1498 /// <summary>
1499 /// Delete substring removes the specified substring bounded
1500 /// by the inclusive indices start and end. Indices may be
1501 /// negative (indicating end-relative) and may be inverted,
1502 /// i.e. end < start.
1503 /// </summary>
1504
1505 public string llDeleteSubString(string src, int start, int end)
1506 {
1507
1508 m_host.AddScriptLPS(1);
1509
1510 // Normalize indices (if negative).
1511 // After normlaization they may still be
1512 // negative, but that is now relative to
1513 // the start, rather than the end, of the
1514 // sequence.
1515 if (start < 0)
1516 {
1517 start = src.Length+start;
1518 }
1519 if (end < 0)
1520 {
1521 end = src.Length+end;
1522 }
1523 // Conventionally delimited substring
1524 if (start <= end)
1525 {
1526 // If both bounds are outside of the existing
1527 // string, then return unchanges.
1528 if (end < 0 || start >= src.Length)
1529 {
1530 return src;
1531 }
1532 // At least one bound is in-range, so we
1533 // need to clip the out-of-bound argument.
1534 if (start < 0)
1535 {
1536 start = 0;
1537 }
1538
1539 if (end >= src.Length)
1540 {
1541 end = src.Length-1;
1542 }
1543
1544 return src.Remove(start,end-start+1);
1545 }
1546 // Inverted substring
1547 else
1548 {
1549 // In this case, out of bounds means that
1550 // the existing string is part of the cut.
1551 if (start < 0 || end >= src.Length)
1552 {
1553 return String.Empty;
1554 }
1555
1556 if (end > 0)
1557 {
1558 if (start < src.Length)
1559 {
1560 return src.Remove(start).Remove(0,end+1);
1561 }
1562 else
1563 {
1564 return src.Remove(0,end+1);
1565 }
1566 }
1567 else
1568 {
1569 if (start < src.Length)
1570 {
1571 return src.Remove(start);
1572 }
1573 else
1574 {
1575 return src;
1576 }
1577 }
1578 }
1579 }
1580
1581 /// <summary>
1582 /// Insert string inserts the specified string identified by src
1583 /// at the index indicated by index. Index may be negative, in
1584 /// which case it is end-relative. The index may exceed either
1585 /// string bound, with the result being a concatenation.
1586 /// </summary>
1587
1588 public string llInsertString(string dest, int index, string src)
1589 {
1590
1591 m_host.AddScriptLPS(1);
1592
1593 // Normalize indices (if negative).
1594 // After normlaization they may still be
1595 // negative, but that is now relative to
1596 // the start, rather than the end, of the
1597 // sequence.
1598 if (index < 0)
1599 {
1600 index = dest.Length+index;
1601
1602 // Negative now means it is less than the lower
1603 // bound of the string.
1604
1605 if (index < 0)
1606 {
1607 return src+dest;
1608 }
1609
1610 }
1611
1612 if (index >= dest.Length)
1613 {
1614 return dest+src;
1615 }
1616
1617 // The index is in bounds.
1618 // In this case the index refers to the index that will
1619 // be assigned to the first character of the inserted string.
1620 // So unlike the other string operations, we do not add one
1621 // to get the correct string length.
1622 return dest.Substring(0,index)+src+dest.Substring(index);
1623
1624 }
1625
1626 public string llToUpper(string src)
1627 {
1628 m_host.AddScriptLPS(1);
1629 return src.ToUpper();
1630 }
1631
1632 public string llToLower(string src)
1633 {
1634 m_host.AddScriptLPS(1);
1635 return src.ToLower();
1636 }
1637
1638 public LSL_Types.LSLInteger llGiveMoney(string destination, int amount)
1639 {
1640 LLUUID invItemID=InventorySelf();
1641 if (invItemID == LLUUID.Zero)
1642 return 0;
1643
1644 m_host.AddScriptLPS(1);
1645
1646 if (m_host.TaskInventory[invItemID].PermsGranter == LLUUID.Zero)
1647 return 0;
1648
1649 if ((m_host.TaskInventory[invItemID].PermsMask & BuiltIn_Commands_BaseClass.PERMISSION_DEBIT) == 0)
1650 {
1651 LSLError("No permissions to give money");
1652 return 0;
1653 }
1654
1655 LLUUID toID=new LLUUID();
1656
1657 if (!LLUUID.TryParse(destination, out toID))
1658 {
1659 LSLError("Bad key in llGiveMoney");
1660 return 0;
1661 }
1662
1663 IMoneyModule money=World.RequestModuleInterface<IMoneyModule>();
1664
1665 if (money == null)
1666 {
1667 NotImplemented("llGiveMoney");
1668 return 0;
1669 }
1670
1671 bool result=money.ObjectGiveMoney(m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount);
1672
1673 if (result)
1674 return 1;
1675
1676 return 0;
1677 }
1678
1679 public void llMakeExplosion()
1680 {
1681 m_host.AddScriptLPS(1);
1682 NotImplemented("llMakeExplosion");
1683 }
1684
1685 public void llMakeFountain()
1686 {
1687 m_host.AddScriptLPS(1);
1688 NotImplemented("llMakeFountain");
1689 }
1690
1691 public void llMakeSmoke()
1692 {
1693 m_host.AddScriptLPS(1);
1694 NotImplemented("llMakeSmoke");
1695 }
1696
1697 public void llMakeFire()
1698 {
1699 m_host.AddScriptLPS(1);
1700 NotImplemented("llMakeFire");
1701 }
1702
1703 public void llRezObject(string inventory, LSL_Types.Vector3 pos, LSL_Types.Vector3 vel, LSL_Types.Quaternion rot, int param)
1704 {
1705 m_host.AddScriptLPS(1);
1706 //NotImplemented("llRezObject");
1707 bool found = false;
1708
1709 // Instead of using return;, I'm using continue; because in our TaskInventory implementation
1710 // it's possible to have two items with the same task inventory name.
1711 // this is an easter egg of sorts.
1712
1713 foreach (KeyValuePair<LLUUID, TaskInventoryItem> inv in m_host.TaskInventory)
1714 {
1715 if (inv.Value.Name == inventory)
1716 {
1717 // make sure we're an object.
1718 if (inv.Value.InvType != (int)InventoryType.Object)
1719 {
1720 llSay(0, "Unable to create requested object. Object is missing from database.");
1721 continue;
1722 }
1723
1724 LLVector3 llpos = new LLVector3((float)pos.x, (float)pos.y, (float)pos.z);
1725
1726 // test if we're further away then 10m
1727 if (Util.GetDistanceTo(llpos, m_host.AbsolutePosition) > 10)
1728 return; // wiki says, if it's further away then 10m, silently fail.
1729
1730 LLVector3 llvel = new LLVector3((float)vel.x, (float)vel.y, (float)vel.z);
1731
1732 // need the magnitude later
1733 float velmag = (float)Util.GetMagnitude(llvel);
1734
1735 SceneObjectGroup new_group = World.RezObject(inv.Value, llpos, new LLQuaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s), llvel, param);
1736
1737 // If either of these are null, then there was an unknown error.
1738 if (new_group == null)
1739 continue;
1740 if (new_group.RootPart == null)
1741 continue;
1742
1743 // objects rezzed with this method are die_at_edge by default.
1744 new_group.RootPart.SetDieAtEdge(true);
1745
1746 m_ScriptEngine.PostScriptEvent(m_itemID, new XEventParams(
1747 "object_rez", new Object[] {
1748 new LSL_Types.LSLString(
1749 new_group.RootPart.UUID.ToString()) },
1750 new XDetectParams[0]));
1751
1752 float groupmass = new_group.GetMass();
1753
1754 //Recoil.
1755 llApplyImpulse(new LSL_Types.Vector3(llvel.X * groupmass, llvel.Y * groupmass, llvel.Z * groupmass), 0);
1756 found = true;
1757 //script delay
1758 System.Threading.Thread.Sleep((int)((groupmass * velmag) / 10));
1759 break;
1760 }
1761 }
1762 if (!found)
1763 llSay(0, "Could not find object " + inventory);
1764 }
1765
1766 public void llLookAt(LSL_Types.Vector3 target, double strength, double damping)
1767 {
1768 m_host.AddScriptLPS(1);
1769 NotImplemented("llLookAt");
1770 }
1771
1772 public void llStopLookAt()
1773 {
1774 m_host.AddScriptLPS(1);
1775 NotImplemented("llStopLookAt");
1776 }
1777
1778 public void llSetTimerEvent(double sec)
1779 {
1780 m_host.AddScriptLPS(1);
1781 // Setting timer repeat
1782 m_ScriptEngine.m_ASYNCLSLCommandManager.m_Timer.SetTimerEvent(m_localID, m_itemID, sec);
1783 }
1784
1785 public void llSleep(double sec)
1786 {
1787 m_host.AddScriptLPS(1);
1788 Thread.Sleep((int)(sec * 1000));
1789 }
1790
1791 public double llGetMass()
1792 {
1793 m_host.AddScriptLPS(1);
1794 return m_host.GetMass();
1795 }
1796
1797 public void llCollisionFilter(string name, string id, int accept)
1798 {
1799 m_host.AddScriptLPS(1);
1800 NotImplemented("llCollisionFilter");
1801 }
1802
1803 public void llTakeControls(int controls, int accept, int pass_on)
1804 {
1805 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
1806 {
1807 return;
1808 }
1809
1810 if (m_host.TaskInventory[InventorySelf()].PermsGranter != LLUUID.Zero)
1811 {
1812 ScenePresence presence = World.GetScenePresence(m_host.TaskInventory[InventorySelf()].PermsGranter);
1813
1814 if (presence != null)
1815 {
1816 if ((m_host.TaskInventory[InventorySelf()].PermsMask & BuiltIn_Commands_BaseClass.PERMISSION_TAKE_CONTROLS) != 0)
1817 {
1818 presence.RegisterControlEventsToScript(controls, accept, pass_on, m_localID, m_itemID);
1819
1820 }
1821 }
1822 }
1823
1824 m_host.AddScriptLPS(1);
1825 //NotImplemented("llTakeControls");
1826 }
1827
1828 public void llReleaseControls()
1829 {
1830 m_host.AddScriptLPS(1);
1831
1832 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
1833 {
1834 return;
1835 }
1836
1837 if (m_host.TaskInventory[InventorySelf()].PermsGranter != LLUUID.Zero)
1838 {
1839 ScenePresence presence = World.GetScenePresence(m_host.TaskInventory[InventorySelf()].PermsGranter);
1840
1841 if (presence != null)
1842 {
1843 if ((m_host.TaskInventory[InventorySelf()].PermsMask & BuiltIn_Commands_BaseClass.PERMISSION_TAKE_CONTROLS) != 0)
1844 {
1845 // Unregister controls from Presence
1846 presence.UnRegisterControlEventsToScript(m_localID, m_itemID);
1847 // Remove Take Control permission.
1848 m_host.TaskInventory[InventorySelf()].PermsMask &= ~BuiltIn_Commands_BaseClass.PERMISSION_TAKE_CONTROLS;
1849 }
1850 }
1851 }
1852 }
1853
1854 public void llAttachToAvatar(int attachment)
1855 {
1856 m_host.AddScriptLPS(1);
1857 NotImplemented("llAttachToAvatar");
1858 }
1859
1860 public void llDetachFromAvatar()
1861 {
1862 m_host.AddScriptLPS(1);
1863 NotImplemented("llDetachFromAvatar");
1864 }
1865
1866 public void llTakeCamera()
1867 {
1868 m_host.AddScriptLPS(1);
1869 NotImplemented("llTakeCamera");
1870 }
1871
1872 public void llReleaseCamera()
1873 {
1874 m_host.AddScriptLPS(1);
1875 NotImplemented("llReleaseCamera");
1876 }
1877
1878 public string llGetOwner()
1879 {
1880 m_host.AddScriptLPS(1);
1881
1882 return m_host.ObjectOwner.ToString();
1883 }
1884
1885 public void llInstantMessage(string user, string message)
1886 {
1887 m_host.AddScriptLPS(1);
1888
1889 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance.
1890 // InstantMessageModule.OnInstantMessage searches through a list of scenes for a client matching the toAgent,
1891 // but I don't think we have a list of scenes available from here.
1892 // (We also don't want to duplicate the code in OnInstantMessage if we can avoid it.)
1893
1894 // user is a UUID
1895
1896 // TODO: figure out values for client, fromSession, and imSessionID
1897 // client.SendInstantMessage(m_host.UUID, fromSession, message, user, imSessionID, m_host.Name, AgentManager.InstantMessageDialog.MessageFromAgent, (uint)Util.UnixTimeSinceEpoch());
1898 LLUUID friendTransactionID = LLUUID.Random();
1899
1900 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID);
1901
1902 GridInstantMessage msg = new GridInstantMessage();
1903 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.UUID;
1904 msg.fromAgentSession = new Guid(friendTransactionID.ToString());// fromAgentSession.UUID;
1905 msg.toAgentID = new Guid(user); // toAgentID.UUID;
1906 msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here
1907 Console.WriteLine("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message);
1908 Console.WriteLine("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString());
1909 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();// timestamp;
1910 //if (client != null)
1911 //{
1912 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName;
1913 //}
1914 //else
1915 //{
1916 // msg.fromAgentName = "(hippos)";// Added for posterity. This means that we can't figure out who sent it
1917 //}
1918 msg.message = message;
1919 msg.dialog = (byte)19; // messgage from script ??? // dialog;
1920 msg.fromGroup = false;// fromGroup;
1921 msg.offline = (byte)0; //offline;
1922 msg.ParentEstateID = 0; //ParentEstateID;
1923 msg.Position = new sLLVector3();// new sLLVector3(m_host.AbsolutePosition);
1924 msg.RegionID = World.RegionInfo.RegionID.UUID;//RegionID.UUID;
1925 msg.binaryBucket = new byte[0];// binaryBucket;
1926 World.TriggerGridInstantMessage(msg, InstantMessageReceiver.IMModule);
1927 // NotImplemented("llInstantMessage");
1928 }
1929
1930 public void llEmail(string address, string subject, string message)
1931 {
1932 m_host.AddScriptLPS(1);
1933 NotImplemented("llEmail");
1934 }
1935
1936 public void llGetNextEmail(string address, string subject)
1937 {
1938 m_host.AddScriptLPS(1);
1939 NotImplemented("llGetNextEmail");
1940 }
1941
1942 public string llGetKey()
1943 {
1944 m_host.AddScriptLPS(1);
1945 return m_host.UUID.ToString();
1946 }
1947
1948 public void llSetBuoyancy(double buoyancy)
1949 {
1950 m_host.AddScriptLPS(1);
1951 if (m_host.ParentGroup != null)
1952 {
1953 if (m_host.ParentGroup.RootPart != null)
1954 {
1955 m_host.ParentGroup.RootPart.SetBuoyancy((float)buoyancy);
1956 }
1957 }
1958 }
1959
1960
1961
1962 public void llSetHoverHeight(double height, int water, double tau)
1963 {
1964 m_host.AddScriptLPS(1);
1965 NotImplemented("llSetHoverHeight");
1966 }
1967
1968 public void llStopHover()
1969 {
1970 m_host.AddScriptLPS(1);
1971 NotImplemented("llStopHover");
1972 }
1973
1974 public void llMinEventDelay(double delay)
1975 {
1976 m_host.AddScriptLPS(1);
1977 NotImplemented("llMinEventDelay");
1978 }
1979
1980 public void llSoundPreload()
1981 {
1982 m_host.AddScriptLPS(1);
1983 NotImplemented("llSoundPreload");
1984 }
1985
1986 public void llRotLookAt(LSL_Types.Quaternion target, double strength, double damping)
1987 {
1988 m_host.AddScriptLPS(1);
1989 NotImplemented("llRotLookAt");
1990 }
1991
1992 public LSL_Types.LSLInteger llStringLength(string str)
1993 {
1994 m_host.AddScriptLPS(1);
1995 if (str.Length > 0)
1996 {
1997 return str.Length;
1998 }
1999 else
2000 {
2001 return 0;
2002 }
2003 }
2004
2005 public void llStartAnimation(string anim)
2006 {
2007 m_host.AddScriptLPS(1);
2008
2009 LLUUID invItemID=InventorySelf();
2010 if (invItemID == LLUUID.Zero)
2011 return;
2012
2013 if (m_host.TaskInventory[invItemID].PermsGranter == LLUUID.Zero)
2014 return;
2015
2016 if ((m_host.TaskInventory[invItemID].PermsMask & BuiltIn_Commands_BaseClass.PERMISSION_TRIGGER_ANIMATION) != 0)
2017 {
2018 ScenePresence presence = World.GetScenePresence(m_host.TaskInventory[invItemID].PermsGranter);
2019
2020 if (presence != null)
2021 {
2022 // Do NOT try to parse LLUUID, animations cannot be triggered by ID
2023 LLUUID animID=InventoryKey(anim, (int)AssetType.Animation);
2024 if (animID == LLUUID.Zero)
2025 presence.AddAnimation(anim);
2026 else
2027 presence.AddAnimation(animID);
2028 }
2029 }
2030 }
2031
2032 public void llStopAnimation(string anim)
2033 {
2034 m_host.AddScriptLPS(1);
2035
2036 LLUUID invItemID=InventorySelf();
2037 if (invItemID == LLUUID.Zero)
2038 return;
2039
2040 if (m_host.TaskInventory[invItemID].PermsGranter == LLUUID.Zero)
2041 return;
2042
2043 if ((m_host.TaskInventory[invItemID].PermsMask & BuiltIn_Commands_BaseClass.PERMISSION_TRIGGER_ANIMATION) != 0)
2044 {
2045 LLUUID animID = new LLUUID();
2046
2047 if (!LLUUID.TryParse(anim, out animID))
2048 {
2049 animID=InventoryKey(anim);
2050 }
2051
2052 if (animID == LLUUID.Zero)
2053 return;
2054
2055 ScenePresence presence = World.GetScenePresence(m_host.TaskInventory[invItemID].PermsGranter);
2056
2057 if (presence != null)
2058 {
2059 if (animID == LLUUID.Zero)
2060 presence.RemoveAnimation(anim);
2061 else
2062 presence.RemoveAnimation(animID);
2063 }
2064 }
2065 }
2066
2067 public void llPointAt()
2068 {
2069 m_host.AddScriptLPS(1);
2070 NotImplemented("llPointAt");
2071 }
2072
2073 public void llStopPointAt()
2074 {
2075 m_host.AddScriptLPS(1);
2076 NotImplemented("llStopPointAt");
2077 }
2078
2079 public void llTargetOmega(LSL_Types.Vector3 axis, double spinrate, double gain)
2080 {
2081 m_host.AddScriptLPS(1);
2082 m_host.RotationalVelocity = new LLVector3((float)(axis.x * spinrate), (float)(axis.y * spinrate), (float)(axis.z * spinrate));
2083 m_host.AngularVelocity = new LLVector3((float)(axis.x * spinrate), (float)(axis.y * spinrate), (float)(axis.z * spinrate));
2084 m_host.ScheduleTerseUpdate();
2085 m_host.SendTerseUpdateToAllClients();
2086 }
2087
2088 public LSL_Types.LSLInteger llGetStartParameter()
2089 {
2090 m_host.AddScriptLPS(1);
2091 // NotImplemented("llGetStartParameter");
2092 return m_host.ParentGroup.StartParameter;
2093 }
2094
2095 public void llGodLikeRezObject(string inventory, LSL_Types.Vector3 pos)
2096 {
2097 m_host.AddScriptLPS(1);
2098 NotImplemented("llGodLikeRezObject");
2099 }
2100
2101 public void llRequestPermissions(string agent, int perm)
2102 {
2103 LLUUID agentID=new LLUUID();
2104
2105 if (!LLUUID.TryParse(agent, out agentID))
2106 return;
2107
2108 LLUUID invItemID=InventorySelf();
2109
2110 if (invItemID == LLUUID.Zero)
2111 return; // Not in a prim? How??
2112
2113 if (agentID == LLUUID.Zero || perm == 0) // Releasing permissions
2114 {
2115 m_host.TaskInventory[invItemID].PermsGranter=LLUUID.Zero;
2116 m_host.TaskInventory[invItemID].PermsMask=0;
2117
2118 m_ScriptEngine.PostScriptEvent(m_itemID, new XEventParams(
2119 "run_time_permissions", new Object[] {
2120 new LSL_Types.LSLInteger(0) },
2121 new XDetectParams[0]));
2122
2123 return;
2124 }
2125
2126 m_host.AddScriptLPS(1);
2127
2128 if (m_host.ParentGroup.RootPart.m_IsAttachment && agent == m_host.ParentGroup.RootPart.m_attachedAvatar)
2129 {
2130 // When attached, certain permissions are implicit if requested from owner
2131 int implicitPerms = BuiltIn_Commands_BaseClass.PERMISSION_TAKE_CONTROLS |
2132 BuiltIn_Commands_BaseClass.PERMISSION_TRIGGER_ANIMATION |
2133 BuiltIn_Commands_BaseClass.PERMISSION_ATTACH;
2134
2135 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
2136 {
2137 m_host.TaskInventory[invItemID].PermsGranter=agentID;
2138 m_host.TaskInventory[invItemID].PermsMask=perm;
2139
2140 m_ScriptEngine.PostScriptEvent(m_itemID, new XEventParams(
2141 "run_time_permissions", new Object[] {
2142 new LSL_Types.LSLInteger(perm) },
2143 new XDetectParams[0]));
2144
2145 return;
2146 }
2147 }
2148 else if (m_host.m_sitTargetAvatar == agentID) // Sitting avatar
2149 {
2150 // When agent is sitting, certain permissions are implicit if requested from sitting agent
2151 int implicitPerms = BuiltIn_Commands_BaseClass.PERMISSION_TRIGGER_ANIMATION |
2152 BuiltIn_Commands_BaseClass.PERMISSION_TRACK_CAMERA;
2153
2154 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
2155 {
2156 m_host.TaskInventory[invItemID].PermsGranter=agentID;
2157 m_host.TaskInventory[invItemID].PermsMask=perm;
2158
2159 m_ScriptEngine.PostScriptEvent(m_itemID, new XEventParams(
2160 "run_time_permissions", new Object[] {
2161 new LSL_Types.LSLInteger(perm) },
2162 new XDetectParams[0]));
2163
2164 return;
2165 }
2166 }
2167
2168 ScenePresence presence = World.GetScenePresence(agentID);
2169
2170 if (presence != null)
2171 {
2172 string ownerName=resolveName(m_host.ParentGroup.RootPart.OwnerID);
2173 if (ownerName == String.Empty)
2174 ownerName="(hippos)";
2175
2176 if (!m_waitingForScriptAnswer)
2177 {
2178 m_host.TaskInventory[invItemID].PermsGranter=agentID;
2179 m_host.TaskInventory[invItemID].PermsMask=0;
2180 presence.ControllingClient.OnScriptAnswer+=handleScriptAnswer;
2181 m_waitingForScriptAnswer=true;
2182 }
2183
2184 presence.ControllingClient.SendScriptQuestion(m_host.UUID, m_host.ParentGroup.RootPart.Name, ownerName, invItemID, perm);
2185 return;
2186 }
2187
2188 // Requested agent is not in range, refuse perms
2189 m_ScriptEngine.PostScriptEvent(m_itemID, new XEventParams(
2190 "run_time_permissions", new Object[] {
2191 new LSL_Types.LSLInteger(0) },
2192 new XDetectParams[0]));
2193 }
2194
2195 void handleScriptAnswer(IClientAPI client, LLUUID taskID, LLUUID itemID, int answer)
2196 {
2197 if (taskID != m_host.UUID)
2198 return;
2199
2200 LLUUID invItemID=InventorySelf();
2201
2202 if (invItemID == LLUUID.Zero)
2203 return;
2204
2205 client.OnScriptAnswer-=handleScriptAnswer;
2206 m_waitingForScriptAnswer=false;
2207
2208 m_host.TaskInventory[invItemID].PermsMask=answer;
2209 m_ScriptEngine.PostScriptEvent(m_itemID, new XEventParams(
2210 "run_time_permissions", new Object[] {
2211 new LSL_Types.LSLInteger(answer) },
2212 new XDetectParams[0]));
2213 }
2214
2215 public string llGetPermissionsKey()
2216 {
2217 m_host.AddScriptLPS(1);
2218
2219 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
2220 {
2221 if (item.Type == 10 && item.ItemID == m_itemID)
2222 {
2223 return item.PermsGranter.ToString();
2224 }
2225 }
2226
2227 return LLUUID.Zero.ToString();
2228 }
2229
2230 public LSL_Types.LSLInteger llGetPermissions()
2231 {
2232 m_host.AddScriptLPS(1);
2233
2234 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
2235 {
2236 if (item.Type == 10 && item.ItemID == m_itemID)
2237 {
2238 return item.PermsMask;
2239 }
2240 }
2241
2242 return 0;
2243 }
2244
2245 public LSL_Types.LSLInteger llGetLinkNumber()
2246 {
2247 m_host.AddScriptLPS(1);
2248
2249 if (m_host.ParentGroup.Children.Count > 0)
2250 {
2251 return m_host.LinkNum + 1;
2252 }
2253 else
2254 {
2255 return 0;
2256 }
2257 }
2258
2259 public void llSetLinkColor(int linknumber, LSL_Types.Vector3 color, int face)
2260 {
2261 m_host.AddScriptLPS(1);
2262 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknumber);
2263 if (linknumber > -1)
2264 {
2265 LLObject.TextureEntry tex = part.Shape.Textures;
2266 LLColor texcolor;
2267 if (face > -1)
2268 {
2269 texcolor = tex.CreateFace((uint)face).RGBA;
2270 texcolor.R = (float)Math.Abs(color.x - 1);
2271 texcolor.G = (float)Math.Abs(color.y - 1);
2272 texcolor.B = (float)Math.Abs(color.z - 1);
2273 tex.FaceTextures[face].RGBA = texcolor;
2274 part.UpdateTexture(tex);
2275 return;
2276 }
2277 else if (face == -1)
2278 {
2279 texcolor = tex.DefaultTexture.RGBA;
2280 texcolor.R = (float)Math.Abs(color.x - 1);
2281 texcolor.G = (float)Math.Abs(color.y - 1);
2282 texcolor.B = (float)Math.Abs(color.z - 1);
2283 tex.DefaultTexture.RGBA = texcolor;
2284 for (uint i = 0; i < 32; i++)
2285 {
2286 if (tex.FaceTextures[i] != null)
2287 {
2288 texcolor = tex.FaceTextures[i].RGBA;
2289 texcolor.R = (float)Math.Abs(color.x - 1);
2290 texcolor.G = (float)Math.Abs(color.y - 1);
2291 texcolor.B = (float)Math.Abs(color.z - 1);
2292 tex.FaceTextures[i].RGBA = texcolor;
2293 }
2294 }
2295 texcolor = tex.DefaultTexture.RGBA;
2296 texcolor.R = (float)Math.Abs(color.x - 1);
2297 texcolor.G = (float)Math.Abs(color.y - 1);
2298 texcolor.B = (float)Math.Abs(color.z - 1);
2299 tex.DefaultTexture.RGBA = texcolor;
2300 part.UpdateTexture(tex);
2301 return;
2302 }
2303 return;
2304 }
2305 else if (linknumber == -1)
2306 {
2307 int num = m_host.ParentGroup.PrimCount;
2308 for (int w = 0; w < num; w++)
2309 {
2310 linknumber = w;
2311 part = m_host.ParentGroup.GetLinkNumPart(linknumber);
2312 LLObject.TextureEntry tex = part.Shape.Textures;
2313 LLColor texcolor;
2314 if (face > -1)
2315 {
2316 texcolor = tex.CreateFace((uint)face).RGBA;
2317 texcolor.R = (float)Math.Abs(color.x - 1);
2318 texcolor.G = (float)Math.Abs(color.y - 1);
2319 texcolor.B = (float)Math.Abs(color.z - 1);
2320 tex.FaceTextures[face].RGBA = texcolor;
2321 part.UpdateTexture(tex);
2322 }
2323 else if (face == -1)
2324 {
2325 texcolor = tex.DefaultTexture.RGBA;
2326 texcolor.R = (float)Math.Abs(color.x - 1);
2327 texcolor.G = (float)Math.Abs(color.y - 1);
2328 texcolor.B = (float)Math.Abs(color.z - 1);
2329 tex.DefaultTexture.RGBA = texcolor;
2330 for (uint i = 0; i < 32; i++)
2331 {
2332 if (tex.FaceTextures[i] != null)
2333 {
2334 texcolor = tex.FaceTextures[i].RGBA;
2335 texcolor.R = (float)Math.Abs(color.x - 1);
2336 texcolor.G = (float)Math.Abs(color.y - 1);
2337 texcolor.B = (float)Math.Abs(color.z - 1);
2338 tex.FaceTextures[i].RGBA = texcolor;
2339 }
2340 }
2341 texcolor = tex.DefaultTexture.RGBA;
2342 texcolor.R = (float)Math.Abs(color.x - 1);
2343 texcolor.G = (float)Math.Abs(color.y - 1);
2344 texcolor.B = (float)Math.Abs(color.z - 1);
2345 tex.DefaultTexture.RGBA = texcolor;
2346 part.UpdateTexture(tex);
2347 }
2348 }
2349 return;
2350 }
2351 }
2352
2353 public void llCreateLink(string target, int parent)
2354 {
2355 m_host.AddScriptLPS(1);
2356 NotImplemented("llCreateLink");
2357 }
2358
2359 public void llBreakLink(int linknum)
2360 {
2361 m_host.AddScriptLPS(1);
2362 NotImplemented("llBreakLink");
2363 }
2364
2365 public void llBreakAllLinks()
2366 {
2367 m_host.AddScriptLPS(1);
2368 NotImplemented("llBreakAllLinks");
2369 }
2370
2371 public string llGetLinkKey(int linknum)
2372 {
2373 m_host.AddScriptLPS(1);
2374 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum);
2375 if (part != null)
2376 {
2377 return part.UUID.ToString();
2378 }
2379 else
2380 {
2381 return LLUUID.Zero.ToString();
2382 }
2383 }
2384
2385 public string llGetLinkName(int linknum)
2386 {
2387 m_host.AddScriptLPS(1);
2388 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum);
2389 if (part != null)
2390 {
2391 return part.Name;
2392 }
2393 else
2394 {
2395 return LLUUID.Zero.ToString();
2396 }
2397 }
2398
2399 public LSL_Types.LSLInteger llGetInventoryNumber(int type)
2400 {
2401 m_host.AddScriptLPS(1);
2402 int count = 0;
2403 foreach (KeyValuePair<LLUUID, TaskInventoryItem> inv in m_host.TaskInventory)
2404 {
2405 if (inv.Value.Type == type || type == -1)
2406 {
2407 count = count + 1;
2408 }
2409 }
2410 return count;
2411 }
2412
2413 public string llGetInventoryName(int type, int number)
2414 {
2415 m_host.AddScriptLPS(1);
2416 ArrayList keys = new ArrayList();
2417 foreach (KeyValuePair<LLUUID, TaskInventoryItem> inv in m_host.TaskInventory)
2418 {
2419 if (inv.Value.Type == type || type == -1)
2420 {
2421 keys.Add(inv.Value.Name);
2422 }
2423 }
2424 if (keys.Count == 0)
2425 {
2426 return String.Empty;
2427 }
2428 keys.Sort();
2429 if (keys.Count > number)
2430 {
2431 return (string)keys[number];
2432 }
2433 return String.Empty;
2434 }
2435
2436 public void llSetScriptState(string name, int run)
2437 {
2438 LLUUID item;
2439
2440 m_host.AddScriptLPS(1);
2441
2442 // These functions are supposed to be robust,
2443 // so get the state one step at a time.
2444
2445 if ((item = ScriptByName(name)) != LLUUID.Zero)
2446 {
2447 m_ScriptEngine.SetScriptState(item, run == 0 ? false : true);
2448 }
2449 else
2450 {
2451 ShoutError("llSetScriptState: script "+name+" not found");
2452 }
2453 }
2454
2455 public double llGetEnergy()
2456 {
2457 m_host.AddScriptLPS(1);
2458 // TODO: figure out real energy value
2459 return 1.0f;
2460 }
2461
2462 public void llGiveInventory(string destination, string inventory)
2463 {
2464 m_host.AddScriptLPS(1);
2465 NotImplemented("llGiveInventory");
2466 }
2467
2468 public void llRemoveInventory(string item)
2469 {
2470 m_host.AddScriptLPS(1);
2471 NotImplemented("llRemoveInventory");
2472 }
2473
2474 public void llSetText(string text, LSL_Types.Vector3 color, double alpha)
2475 {
2476 m_host.AddScriptLPS(1);
2477 Vector3 av3 = new Vector3((float)color.x, (float)color.y, (float)color.z);
2478 m_host.SetText(text, av3, alpha);
2479 }
2480
2481 public double llWater(LSL_Types.Vector3 offset)
2482 {
2483 m_host.AddScriptLPS(1);
2484 return World.RegionInfo.EstateSettings.waterHeight;
2485 }
2486
2487 public void llPassTouches(int pass)
2488 {
2489 m_host.AddScriptLPS(1);
2490 NotImplemented("llPassTouches");
2491 }
2492
2493 public string llRequestAgentData(string id, int data)
2494 {
2495 m_host.AddScriptLPS(1);
2496
2497 UserProfileData userProfile =
2498 World.CommsManager.UserService.GetUserProfile(id);
2499
2500 string reply = String.Empty;
2501
2502 switch(data)
2503 {
2504 case 1: // DATA_ONLINE (0|1)
2505 // TODO: implement fetching of this information
2506// if(userProfile.CurrentAgent.AgentOnline)
2507// reply = "1";
2508// else
2509 reply = "0";
2510 break;
2511 case 2: // DATA_NAME (First Last)
2512 reply = userProfile.FirstName+" "+userProfile.SurName;
2513 break;
2514 case 3: // DATA_BORN (YYYY-MM-DD)
2515 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0);
2516 born = born.AddSeconds(userProfile.Created);
2517 reply = born.ToString("yyyy-MM-dd");
2518 break;
2519 case 4: // DATA_RATING (0,0,0,0,0,0)
2520 reply = "0,0,0,0,0,0";
2521 break;
2522 case 8: // DATA_PAYINFO (0|1|2|3)
2523 reply = "0";
2524 break;
2525 default:
2526 return LLUUID.Zero.ToString(); // Raise no event
2527 }
2528
2529 LLUUID rq = LLUUID.Random();
2530
2531 LLUUID tid = m_ScriptEngine.m_ASYNCLSLCommandManager.
2532 m_Dataserver.RegisterRequest(m_localID,
2533 m_itemID, rq.ToString());
2534
2535 m_ScriptEngine.m_ASYNCLSLCommandManager.
2536 m_Dataserver.DataserverReply(rq.ToString(), reply);
2537
2538 return tid.ToString();
2539 }
2540
2541 public string llRequestInventoryData(string name)
2542 {
2543 m_host.AddScriptLPS(1);
2544
2545 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
2546 {
2547 if (item.Type == 3 && item.Name == name)
2548 {
2549 LLUUID tid = m_ScriptEngine.m_ASYNCLSLCommandManager.
2550 m_Dataserver.RegisterRequest(m_localID,
2551 m_itemID, item.AssetID.ToString());
2552
2553 LLVector3 region = new LLVector3(
2554 World.RegionInfo.RegionLocX * Constants.RegionSize,
2555 World.RegionInfo.RegionLocY * Constants.RegionSize,
2556 0);
2557
2558 World.AssetCache.GetAsset(item.AssetID,
2559 delegate(LLUUID i, AssetBase a)
2560 {
2561 AssetLandmark lm = new AssetLandmark(a);
2562
2563 region += lm.Position;
2564
2565 string reply = region.ToString();
2566
2567 m_ScriptEngine.m_ASYNCLSLCommandManager.
2568 m_Dataserver.DataserverReply(i.ToString(),
2569 reply);
2570 }, false);
2571
2572 return tid.ToString();
2573 }
2574 }
2575
2576 return String.Empty;
2577 }
2578
2579 public void llSetDamage(double damage)
2580 {
2581 m_host.AddScriptLPS(1);
2582 NotImplemented("llSetDamage");
2583 }
2584
2585 public void llTeleportAgentHome(string agent)
2586 {
2587 m_host.AddScriptLPS(1);
2588 NotImplemented("llTeleportAgentHome");
2589 }
2590
2591 public void llModifyLand(int action, int brush)
2592 {
2593 m_host.AddScriptLPS(1);
2594 World.ExternalChecks.ExternalChecksCanTerraformLand(m_host.OwnerID, new LLVector3(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y, 0));
2595 }
2596
2597 public void llCollisionSound(string impact_sound, double impact_volume)
2598 {
2599 m_host.AddScriptLPS(1);
2600 NotImplemented("llCollisionSound");
2601 }
2602
2603 public void llCollisionSprite(string impact_sprite)
2604 {
2605 m_host.AddScriptLPS(1);
2606 NotImplemented("llCollisionSprite");
2607 }
2608
2609 public string llGetAnimation(string id)
2610 {
2611 m_host.AddScriptLPS(1);
2612 NotImplemented("llGetAnimation");
2613 return String.Empty;
2614 }
2615
2616 public void llResetScript()
2617 {
2618 m_host.AddScriptLPS(1);
2619 m_ScriptEngine.ResetScript(m_itemID);
2620 }
2621
2622 public void llMessageLinked(int linknum, int num, string msg, string id)
2623 {
2624
2625 m_host.AddScriptLPS(1);
2626
2627 uint partLocalID;
2628 LLUUID partItemID;
2629
2630 switch ((int)linknum)
2631 {
2632
2633 case (int)BuiltIn_Commands_BaseClass.LINK_ROOT:
2634
2635 SceneObjectPart part = m_host.ParentGroup.RootPart;
2636
2637 foreach (TaskInventoryItem item in part.TaskInventory.Values)
2638 {
2639 if (item.Type == 10)
2640 {
2641 partLocalID = part.LocalId;
2642 partItemID = item.ItemID;
2643
2644 object[] resobj = new object[]
2645 {
2646 new LSL_Types.LSLInteger(m_host.LinkNum + 1), new LSL_Types.LSLInteger(num), new LSL_Types.LSLString(msg), new LSL_Types.LSLString(id)
2647 };
2648
2649 m_ScriptEngine.PostScriptEvent(partItemID,
2650 new XEventParams("link_message",
2651 resobj, new XDetectParams[0]));
2652 }
2653 }
2654
2655 break;
2656
2657 case (int)BuiltIn_Commands_BaseClass.LINK_SET:
2658
2659 Console.WriteLine("LINK_SET");
2660
2661 foreach (SceneObjectPart partInst in m_host.ParentGroup.GetParts())
2662 {
2663
2664 foreach (TaskInventoryItem item in partInst.TaskInventory.Values)
2665 {
2666 if (item.Type == 10)
2667 {
2668 partLocalID = partInst.LocalId;
2669 partItemID = item.ItemID;
2670 Object[] resobj = new object[]
2671 {
2672 new LSL_Types.LSLInteger(m_host.LinkNum + 1), new LSL_Types.LSLInteger(num), new LSL_Types.LSLString(msg), new LSL_Types.LSLString(id)
2673 };
2674
2675 m_ScriptEngine.PostScriptEvent(partItemID,
2676 new XEventParams("link_message",
2677 resobj, new XDetectParams[0]));
2678 }
2679 }
2680 }
2681
2682 break;
2683
2684 case (int)BuiltIn_Commands_BaseClass.LINK_ALL_OTHERS:
2685
2686 foreach (SceneObjectPart partInst in m_host.ParentGroup.GetParts())
2687 {
2688
2689 if (partInst.LocalId != m_host.LocalId)
2690 {
2691
2692 foreach (TaskInventoryItem item in partInst.TaskInventory.Values)
2693 {
2694 if (item.Type == 10)
2695 {
2696 partLocalID = partInst.LocalId;
2697 partItemID = item.ItemID;
2698 Object[] resobj = new object[]
2699 {
2700 new LSL_Types.LSLInteger(m_host.LinkNum + 1), new LSL_Types.LSLInteger(num), new LSL_Types.LSLString(msg), new LSL_Types.LSLString(id)
2701 };
2702
2703 m_ScriptEngine.PostScriptEvent(partItemID,
2704 new XEventParams("link_message",
2705 resobj, new XDetectParams[0]));
2706 }
2707 }
2708
2709 }
2710 }
2711
2712 break;
2713
2714 case (int)BuiltIn_Commands_BaseClass.LINK_ALL_CHILDREN:
2715
2716 foreach (SceneObjectPart partInst in m_host.ParentGroup.GetParts())
2717 {
2718
2719 if (partInst.LocalId != m_host.ParentGroup.RootPart.LocalId)
2720 {
2721
2722 foreach (TaskInventoryItem item in partInst.TaskInventory.Values)
2723 {
2724 if (item.Type == 10)
2725 {
2726 partLocalID = partInst.LocalId;
2727 partItemID = item.ItemID;
2728 Object[] resobj = new object[]
2729 {
2730 new LSL_Types.LSLInteger(m_host.LinkNum + 1), new LSL_Types.LSLInteger(num), new LSL_Types.LSLString(msg), new LSL_Types.LSLString(id)
2731 };
2732
2733 m_ScriptEngine.PostScriptEvent(partItemID,
2734 new XEventParams("link_message",
2735 resobj, new XDetectParams[0]));
2736 }
2737 }
2738
2739 }
2740 }
2741
2742 break;
2743
2744 case (int)BuiltIn_Commands_BaseClass.LINK_THIS:
2745
2746 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
2747 {
2748 if (item.Type == 10)
2749 {
2750 partItemID = item.ItemID;
2751
2752 object[] resobj = new object[]
2753 {
2754 new LSL_Types.LSLInteger(m_host.LinkNum + 1), new LSL_Types.LSLInteger(num), new LSL_Types.LSLString(msg), new LSL_Types.LSLString(id)
2755 };
2756
2757 m_ScriptEngine.PostScriptEvent(partItemID,
2758 new XEventParams("link_message",
2759 resobj, new XDetectParams[0]));
2760 }
2761 }
2762
2763 break;
2764
2765 default:
2766
2767 foreach (SceneObjectPart partInst in m_host.ParentGroup.GetParts())
2768 {
2769
2770 if ((partInst.LinkNum + 1) == linknum)
2771 {
2772
2773 foreach (TaskInventoryItem item in partInst.TaskInventory.Values)
2774 {
2775 if (item.Type == 10)
2776 {
2777 partLocalID = partInst.LocalId;
2778 partItemID = item.ItemID;
2779 Object[] resObjDef = new object[]
2780 {
2781 new LSL_Types.LSLInteger(m_host.LinkNum + 1), new LSL_Types.LSLInteger(num), new LSL_Types.LSLString(msg), new LSL_Types.LSLString(id)
2782 };
2783
2784 m_ScriptEngine.PostScriptEvent(partItemID,
2785 new XEventParams("link_message",
2786 resObjDef, new XDetectParams[0]));
2787 }
2788 }
2789
2790 }
2791 }
2792
2793 break;
2794
2795 }
2796
2797 }
2798
2799 public void llPushObject(string target, LSL_Types.Vector3 impulse, LSL_Types.Vector3 ang_impulse, int local)
2800 {
2801 m_host.AddScriptLPS(1);
2802 NotImplemented("llPushObject");
2803 }
2804
2805 public void llPassCollisions(int pass)
2806 {
2807 m_host.AddScriptLPS(1);
2808 NotImplemented("llPassCollisions");
2809 }
2810
2811 public string llGetScriptName()
2812 {
2813
2814 string result = String.Empty;
2815
2816 m_host.AddScriptLPS(1);
2817
2818 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
2819 {
2820 if (item.Type == 10 && item.ItemID == m_itemID)
2821 {
2822 result = item.Name!=null?item.Name:String.Empty;
2823 break;
2824 }
2825 }
2826
2827 return result;
2828
2829 }
2830
2831 public LSL_Types.LSLInteger llGetNumberOfSides()
2832 {
2833 m_host.AddScriptLPS(1);
2834 NotImplemented("llGetNumberOfSides");
2835 return 0;
2836 }
2837
2838
2839 /* The new / changed functions were tested with the following LSL script:
2840
2841 default
2842 {
2843 state_entry()
2844 {
2845 rotation rot = llEuler2Rot(<0,70,0> * DEG_TO_RAD);
2846
2847 llOwnerSay("to get here, we rotate over: "+ (string) llRot2Axis(rot));
2848 llOwnerSay("and we rotate for: "+ (llRot2Angle(rot) * RAD_TO_DEG));
2849
2850 // convert back and forth between quaternion <-> vector and angle
2851
2852 rotation newrot = llAxisAngle2Rot(llRot2Axis(rot),llRot2Angle(rot));
2853
2854 llOwnerSay("Old rotation was: "+(string) rot);
2855 llOwnerSay("re-converted rotation is: "+(string) newrot);
2856
2857 llSetRot(rot); // to check the parameters in the prim
2858 }
2859 }
2860 */
2861
2862
2863
2864 // Xantor 29/apr/2008
2865 // Returns rotation described by rotating angle radians about axis.
2866 // q = cos(a/2) + i (x * sin(a/2)) + j (y * sin(a/2)) + k (z * sin(a/2))
2867 public LSL_Types.Quaternion llAxisAngle2Rot(LSL_Types.Vector3 axis, double angle)
2868 {
2869 m_host.AddScriptLPS(1);
2870
2871 double x, y, z, s, t;
2872
2873 s = Math.Cos(angle / 2);
2874 t = Math.Sin(angle / 2); // temp value to avoid 2 more sin() calcs
2875 x = axis.x * t;
2876 y = axis.y * t;
2877 z = axis.z * t;
2878
2879 return new LSL_Types.Quaternion(x,y,z,s);
2880 // NotImplemented("llAxisAngle2Rot");
2881 }
2882
2883
2884 // Xantor 29/apr/2008
2885 // converts a Quaternion to X,Y,Z axis rotations
2886 public LSL_Types.Vector3 llRot2Axis(LSL_Types.Quaternion rot)
2887 {
2888 m_host.AddScriptLPS(1);
2889 double x,y,z;
2890
2891 if (rot.s > 1) // normalization needed
2892 {
2893 double length = Math.Sqrt(rot.x * rot.x + rot.y * rot.y +
2894 rot.z * rot.z + rot.s * rot.s);
2895
2896 rot.x /= length;
2897 rot.y /= length;
2898 rot.z /= length;
2899 rot.s /= length;
2900
2901 }
2902
2903 double angle = 2 * Math.Acos(rot.s);
2904 double s = Math.Sqrt(1 - rot.s * rot.s);
2905 if (s < 0.001)
2906 {
2907 x = 1;
2908 y = z = 0;
2909 }
2910 else
2911 {
2912 x = rot.x / s; // normalise axis
2913 y = rot.y / s;
2914 z = rot.z / s;
2915 }
2916
2917
2918 return new LSL_Types.Vector3(x,y,z);
2919
2920
2921// NotImplemented("llRot2Axis");
2922 }
2923
2924
2925 // Returns the angle of a quaternion (see llRot2Axis for the axis)
2926 public double llRot2Angle(LSL_Types.Quaternion rot)
2927 {
2928 m_host.AddScriptLPS(1);
2929
2930 if (rot.s > 1) // normalization needed
2931 {
2932 double length = Math.Sqrt(rot.x * rot.x + rot.y * rot.y +
2933 rot.z * rot.z + rot.s * rot.s);
2934
2935 rot.x /= length;
2936 rot.y /= length;
2937 rot.z /= length;
2938 rot.s /= length;
2939
2940 }
2941
2942 double angle = 2 * Math.Acos(rot.s);
2943
2944 return angle;
2945
2946// NotImplemented("llRot2Angle");
2947 }
2948
2949 public double llAcos(double val)
2950 {
2951 m_host.AddScriptLPS(1);
2952 return (double)Math.Acos(val);
2953 }
2954
2955 public double llAsin(double val)
2956 {
2957 m_host.AddScriptLPS(1);
2958 return (double)Math.Asin(val);
2959 }
2960
2961 // Xantor 30/apr/2008
2962 public double llAngleBetween(LSL_Types.Quaternion a, LSL_Types.Quaternion b)
2963 {
2964 m_host.AddScriptLPS(1);
2965
2966 return (double) Math.Acos(a.x * b.x + a.y * b.y + a.z * b.z + a.s * b.s) * 2;
2967// NotImplemented("llAngleBetween");
2968 }
2969
2970 public string llGetInventoryKey(string name)
2971 {
2972 m_host.AddScriptLPS(1);
2973 foreach (KeyValuePair<LLUUID, TaskInventoryItem> inv in m_host.TaskInventory)
2974 {
2975 if (inv.Value.Name == name)
2976 {
2977 if ((inv.Value.OwnerMask & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify))
2978 {
2979 return inv.Value.AssetID.ToString();
2980 }
2981 else
2982 {
2983 return LLUUID.Zero.ToString();
2984 }
2985 }
2986 }
2987 return LLUUID.Zero.ToString();
2988 }
2989
2990 public void llAllowInventoryDrop(int add)
2991 {
2992 m_host.AddScriptLPS(1);
2993 NotImplemented("llAllowInventoryDrop");
2994 }
2995
2996 public LSL_Types.Vector3 llGetSunDirection()
2997 {
2998 m_host.AddScriptLPS(1);
2999
3000 LSL_Types.Vector3 SunDoubleVector3;
3001 LLVector3 SunFloatVector3;
3002
3003 // sunPosition estate setting is set in OpenSim.Region.Environment.Modules.SunModule
3004 // have to convert from LLVector3 (float) to LSL_Types.Vector3 (double)
3005 SunFloatVector3 = World.RegionInfo.EstateSettings.sunPosition;
3006 SunDoubleVector3.x = (double)SunFloatVector3.X;
3007 SunDoubleVector3.y = (double)SunFloatVector3.Y;
3008 SunDoubleVector3.z = (double)SunFloatVector3.Z;
3009
3010 return SunDoubleVector3;
3011 }
3012
3013 public LSL_Types.Vector3 llGetTextureOffset(int face)
3014 {
3015 m_host.AddScriptLPS(1);
3016 LLObject.TextureEntry tex = m_host.Shape.Textures;
3017 LSL_Types.Vector3 offset;
3018 if (face == -1)
3019 {
3020 face = 0;
3021 }
3022 offset.x = tex.GetFace((uint)face).OffsetU;
3023 offset.y = tex.GetFace((uint)face).OffsetV;
3024 offset.z = 0.0;
3025 return offset;
3026 }
3027
3028 public LSL_Types.Vector3 llGetTextureScale(int side)
3029 {
3030 m_host.AddScriptLPS(1);
3031 LLObject.TextureEntry tex = m_host.Shape.Textures;
3032 LSL_Types.Vector3 scale;
3033 if (side == -1)
3034 {
3035 side = 0;
3036 }
3037 scale.x = tex.GetFace((uint)side).RepeatU;
3038 scale.y = tex.GetFace((uint)side).RepeatV;
3039 scale.z = 0.0;
3040 return scale;
3041 }
3042
3043 public double llGetTextureRot(int face)
3044 {
3045 m_host.AddScriptLPS(1);
3046 LLObject.TextureEntry tex = m_host.Shape.Textures;
3047 if (face == -1)
3048 {
3049 face = 0;
3050 }
3051 return tex.GetFace((uint)face).Rotation;
3052 }
3053
3054 public LSL_Types.LSLInteger llSubStringIndex(string source, string pattern)
3055 {
3056 m_host.AddScriptLPS(1);
3057 return source.IndexOf(pattern);
3058 }
3059
3060 public string llGetOwnerKey(string id)
3061 {
3062 m_host.AddScriptLPS(1);
3063 LLUUID key = new LLUUID();
3064 if (LLUUID.TryParse(id, out key))
3065 {
3066 return World.GetSceneObjectPart(World.Entities[key].LocalId).OwnerID.ToString();
3067 }
3068 else
3069 {
3070 return LLUUID.Zero.ToString();
3071 }
3072 }
3073
3074 public LSL_Types.Vector3 llGetCenterOfMass()
3075 {
3076 m_host.AddScriptLPS(1);
3077 NotImplemented("llGetCenterOfMass");
3078 return new LSL_Types.Vector3();
3079 }
3080
3081 public LSL_Types.list llListSort(LSL_Types.list src, int stride, int ascending)
3082 {
3083 m_host.AddScriptLPS(1);
3084 return src.Sort(stride, ascending);
3085 }
3086
3087 public LSL_Types.LSLInteger llGetListLength(LSL_Types.list src)
3088 {
3089 m_host.AddScriptLPS(1);
3090 return src.Length;
3091 }
3092
3093 public LSL_Types.LSLInteger llList2Integer(LSL_Types.list src, int index)
3094 {
3095 m_host.AddScriptLPS(1);
3096 if (index < 0)
3097 {
3098 index = src.Length + index;
3099 }
3100 if (index >= src.Length)
3101 {
3102 return 0;
3103 }
3104 try
3105 {
3106 return Convert.ToInt32(src.Data[index]);
3107 }
3108 catch (FormatException)
3109 {
3110 return 0;
3111 }
3112 }
3113
3114 public double osList2Double(LSL_Types.list src, int index)
3115 {
3116 m_host.AddScriptLPS(1);
3117 if (index < 0)
3118 {
3119 index = src.Length + index;
3120 }
3121 if (index >= src.Length)
3122 {
3123 return 0.0;
3124 }
3125 return Convert.ToDouble(src.Data[index]);
3126 }
3127
3128 public double llList2Float(LSL_Types.list src, int index)
3129 {
3130 m_host.AddScriptLPS(1);
3131 if (index < 0)
3132 {
3133 index = src.Length + index;
3134 }
3135 if (index >= src.Length)
3136 {
3137 return 0.0;
3138 }
3139 try
3140 {
3141 return Convert.ToDouble(src.Data[index]);
3142 }
3143 catch (FormatException)
3144 {
3145 return 0.0;
3146 }
3147 }
3148
3149 public string llList2String(LSL_Types.list src, int index)
3150 {
3151 m_host.AddScriptLPS(1);
3152 if (index < 0)
3153 {
3154 index = src.Length + index;
3155 }
3156 if (index >= src.Length)
3157 {
3158 return String.Empty;
3159 }
3160 return src.Data[index].ToString();
3161 }
3162
3163 public string llList2Key(LSL_Types.list src, int index)
3164 {
3165 m_host.AddScriptLPS(1);
3166 if (index < 0)
3167 {
3168 index = src.Length + index;
3169 }
3170 if (index >= src.Length)
3171 {
3172 return "";
3173 }
3174 return src.Data[index].ToString();
3175 }
3176
3177 public LSL_Types.Vector3 llList2Vector(LSL_Types.list src, int index)
3178 {
3179 m_host.AddScriptLPS(1);
3180 if (index < 0)
3181 {
3182 index = src.Length + index;
3183 }
3184 if (index >= src.Length)
3185 {
3186 return new LSL_Types.Vector3(0, 0, 0);
3187 }
3188 if (src.Data[index].GetType() == typeof(LSL_Types.Vector3))
3189 {
3190 return (LSL_Types.Vector3)src.Data[index];
3191 }
3192 else
3193 {
3194 return new LSL_Types.Vector3(src.Data[index].ToString());
3195 }
3196 }
3197
3198 public LSL_Types.Quaternion llList2Rot(LSL_Types.list src, int index)
3199 {
3200 m_host.AddScriptLPS(1);
3201 if (index < 0)
3202 {
3203 index = src.Length + index;
3204 }
3205 if (index >= src.Length)
3206 {
3207 return new LSL_Types.Quaternion(0, 0, 0, 1);
3208 }
3209 if (src.Data[index].GetType() == typeof(LSL_Types.Quaternion))
3210 {
3211 return (LSL_Types.Quaternion)src.Data[index];
3212 }
3213 else
3214 {
3215 return new LSL_Types.Quaternion(src.Data[index].ToString());
3216 }
3217 }
3218
3219 public LSL_Types.list llList2List(LSL_Types.list src, int start, int end)
3220 {
3221 m_host.AddScriptLPS(1);
3222 return src.GetSublist(start, end);
3223 }
3224
3225 public LSL_Types.list llDeleteSubList(LSL_Types.list src, int start, int end)
3226 {
3227 return src.DeleteSublist(end, start);
3228 }
3229
3230 public LSL_Types.LSLInteger llGetListEntryType(LSL_Types.list src, int index)
3231 {
3232 m_host.AddScriptLPS(1);
3233 if (index < 0)
3234 {
3235 index = src.Length + index;
3236 }
3237 if (index >= src.Length)
3238 {
3239 return 0;
3240 }
3241
3242 if (src.Data[index] is Int32)
3243 return 1;
3244 if (src.Data[index] is Double)
3245 return 2;
3246 if (src.Data[index] is String)
3247 {
3248 LLUUID tuuid;
3249 if (LLUUID.TryParse(src.Data[index].ToString(), out tuuid))
3250 {
3251 return 3;
3252 }
3253 else
3254 {
3255 return 4;
3256 }
3257 }
3258 if (src.Data[index] is LSL_Types.Vector3)
3259 return 5;
3260 if (src.Data[index] is LSL_Types.Quaternion)
3261 return 6;
3262 if (src.Data[index] is LSL_Types.list)
3263 return 7;
3264 return 0;
3265
3266 }
3267
3268 /// <summary>
3269 /// Process the supplied list and return the
3270 /// content of the list formatted as a comma
3271 /// separated list. There is a space after
3272 /// each comma.
3273 /// </summary>
3274
3275 public string llList2CSV(LSL_Types.list src)
3276 {
3277
3278 string ret = String.Empty;
3279 int x = 0;
3280
3281 m_host.AddScriptLPS(1);
3282
3283 if (src.Data.Length > 0)
3284 {
3285 ret = src.Data[x++].ToString();
3286 for (; x < src.Data.Length; x++)
3287 {
3288 ret += ", "+src.Data[x].ToString();
3289 }
3290 }
3291
3292 return ret;
3293 }
3294
3295 /// <summary>
3296 /// The supplied string is scanned for commas
3297 /// and converted into a list. Commas are only
3298 /// effective if they are encountered outside
3299 /// of '<' '>' delimiters. Any whitespace
3300 /// before or after an element is trimmed.
3301 /// </summary>
3302
3303 public LSL_Types.list llCSV2List(string src)
3304 {
3305
3306 LSL_Types.list result = new LSL_Types.list();
3307 int parens = 0;
3308 int start = 0;
3309 int length = 0;
3310
3311 m_host.AddScriptLPS(1);
3312
3313 for (int i = 0; i < src.Length; i++)
3314 {
3315 switch (src[i])
3316 {
3317 case '<' :
3318 parens++;
3319 length++;
3320 break;
3321 case '>' :
3322 if (parens > 0)
3323 parens--;
3324 length++;
3325 break;
3326 case ',' :
3327 if (parens == 0)
3328 {
3329 result.Add(src.Substring(start,length).Trim());
3330 start += length+1;
3331 length = 0;
3332 } else
3333 length++;
3334 break;
3335 default :
3336 length++;
3337 break;
3338 }
3339 }
3340
3341 result.Add(src.Substring(start,length).Trim());
3342
3343 return result;
3344
3345 }
3346
3347 /// <summary>
3348 /// Randomizes the list, be arbitrarily reordering
3349 /// sublists of stride elements. As the stride approaches
3350 /// the size of the list, the options become very
3351 /// limited.
3352 /// </summary>
3353 /// <remarks>
3354 /// This could take a while for very large list
3355 /// sizes.
3356 /// </remarks>
3357
3358 public LSL_Types.list llListRandomize(LSL_Types.list src, int stride)
3359 {
3360
3361 LSL_Types.list result;
3362 Random rand = new Random();
3363
3364 int chunkk;
3365 int[] chunks;
3366 int index1;
3367 int index2;
3368 int tmp;
3369
3370 m_host.AddScriptLPS(1);
3371
3372 if (stride == 0)
3373 stride = 1;
3374
3375 // Stride MUST be a factor of the list length
3376 // If not, then return the src list. This also
3377 // traps those cases where stride > length.
3378
3379 if (src.Length != stride && src.Length%stride == 0)
3380 {
3381 chunkk = src.Length/stride;
3382
3383 chunks = new int[chunkk];
3384
3385 for (int i = 0; i < chunkk; i++)
3386 chunks[i] = i;
3387
3388 for (int i = 0; i < chunkk - 1; i++)
3389 {
3390 // randomly select 2 chunks
3391 index1 = rand.Next(rand.Next(65536));
3392 index1 = index1%chunkk;
3393 index2 = rand.Next(rand.Next(65536));
3394 index2 = index2%chunkk;
3395
3396 // and swap their relative positions
3397 tmp = chunks[index1];
3398 chunks[index1] = chunks[index2];
3399 chunks[index2] = tmp;
3400 }
3401
3402 // Construct the randomized list
3403
3404 result = new LSL_Types.list();
3405
3406 for (int i = 0; i < chunkk; i++)
3407 {
3408 for (int j = 0; j < stride; j++)
3409 {
3410 result.Add(src.Data[chunks[i]*stride+j]);
3411 }
3412 }
3413 }
3414 else {
3415 object[] array = new object[src.Length];
3416 Array.Copy(src.Data, 0, array, 0, src.Length);
3417 result = new LSL_Types.list(array);
3418 }
3419
3420 return result;
3421
3422 }
3423
3424 /// <summary>
3425 /// Elements in the source list starting with 0 and then
3426 /// every i+stride. If the stride is negative then the scan
3427 /// is backwards producing an inverted result.
3428 /// Only those elements that are also in the specified
3429 /// range are included in the result.
3430 /// </summary>
3431
3432 public LSL_Types.list llList2ListStrided(LSL_Types.list src, int start, int end, int stride)
3433 {
3434
3435 LSL_Types.list result = new LSL_Types.list();
3436 int[] si = new int[2];
3437 int[] ei = new int[2];
3438 bool twopass = false;
3439
3440 m_host.AddScriptLPS(1);
3441
3442 // First step is always to deal with negative indices
3443
3444 if (start < 0)
3445 start = src.Length+start;
3446 if (end < 0)
3447 end = src.Length+end;
3448
3449 // Out of bounds indices are OK, just trim them
3450 // accordingly
3451
3452 if (start > src.Length)
3453 start = src.Length;
3454
3455 if (end > src.Length)
3456 end = src.Length;
3457
3458 // There may be one or two ranges to be considered
3459
3460 if (start != end)
3461 {
3462
3463 if (start <= end)
3464 {
3465 si[0] = start;
3466 ei[0] = end;
3467 }
3468 else
3469 {
3470 si[1] = start;
3471 ei[1] = src.Length;
3472 si[0] = 0;
3473 ei[0] = end;
3474 twopass = true;
3475 }
3476
3477 // The scan always starts from the beginning of the
3478 // source list, but members are only selected if they
3479 // fall within the specified sub-range. The specified
3480 // range values are inclusive.
3481 // A negative stride reverses the direction of the
3482 // scan producing an inverted list as a result.
3483
3484 if (stride == 0)
3485 stride = 1;
3486
3487 if (stride > 0)
3488 {
3489 for (int i = 0; i < src.Length; i += stride)
3490 {
3491 if (i<=ei[0] && i>=si[0])
3492 result.Add(src.Data[i]);
3493 if (twopass && i>=si[1] && i<=ei[1])
3494 result.Add(src.Data[i]);
3495 }
3496 }
3497 else if (stride < 0)
3498 {
3499 for (int i = src.Length - 1; i >= 0; i += stride)
3500 {
3501 if (i <= ei[0] && i >= si[0])
3502 result.Add(src.Data[i]);
3503 if (twopass && i >= si[1] && i <= ei[1])
3504 result.Add(src.Data[i]);
3505 }
3506 }
3507 }
3508
3509 return result;
3510 }
3511
3512 public LSL_Types.Vector3 llGetRegionCorner()
3513 {
3514 m_host.AddScriptLPS(1);
3515 return new LSL_Types.Vector3(World.RegionInfo.RegionLocX * Constants.RegionSize, World.RegionInfo.RegionLocY * Constants.RegionSize, 0);
3516 }
3517
3518 /// <summary>
3519 /// Insert the list identified by <src> into the
3520 /// list designated by <dest> such that the first
3521 /// new element has the index specified by <index>
3522 /// </summary>
3523
3524 public LSL_Types.list llListInsertList(LSL_Types.list dest, LSL_Types.list src, int index)
3525 {
3526
3527 LSL_Types.list pref = null;
3528 LSL_Types.list suff = null;
3529
3530 m_host.AddScriptLPS(1);
3531
3532 if (index < 0)
3533 {
3534 index = index+dest.Length;
3535 if (index < 0)
3536 {
3537 index = 0;
3538 }
3539 }
3540
3541 if (index != 0)
3542 {
3543 pref = dest.GetSublist(0,index-1);
3544 if (index < dest.Length)
3545 {
3546 suff = dest.GetSublist(index,-1);
3547 return pref + src + suff;
3548 }
3549 else
3550 {
3551 return pref + src;
3552 }
3553 }
3554 else
3555 {
3556 if (index < dest.Length)
3557 {
3558 suff = dest.GetSublist(index,-1);
3559 return src + suff;
3560 }
3561 else
3562 {
3563 return src;
3564 }
3565 }
3566
3567 }
3568
3569 /// <summary>
3570 /// Returns the index of the first occurrence of test
3571 /// in src.
3572 /// </summary>
3573
3574 public LSL_Types.LSLInteger llListFindList(LSL_Types.list src, LSL_Types.list test)
3575 {
3576
3577 int index = -1;
3578 int length = src.Length - test.Length + 1;
3579
3580 m_host.AddScriptLPS(1);
3581
3582 // If either list is empty, do not match
3583
3584 if (src.Length != 0 && test.Length != 0)
3585 {
3586 for (int i = 0; i < length; i++)
3587 {
3588 if (src.Data[i].Equals(test.Data[0]))
3589 {
3590 int j;
3591 for (j = 1; j < test.Length; j++)
3592 if (!src.Data[i+j].Equals(test.Data[j]))
3593 break;
3594 if (j == test.Length)
3595 {
3596 index = i;
3597 break;
3598 }
3599 }
3600 }
3601 }
3602
3603 return index;
3604
3605 }
3606
3607 public string llGetObjectName()
3608 {
3609 m_host.AddScriptLPS(1);
3610 return m_host.Name!=null?m_host.Name:String.Empty;
3611 }
3612
3613 public void llSetObjectName(string name)
3614 {
3615 m_host.AddScriptLPS(1);
3616 m_host.Name = name!=null?name:String.Empty;
3617 }
3618
3619 public string llGetDate()
3620 {
3621 m_host.AddScriptLPS(1);
3622 DateTime date = DateTime.Now.ToUniversalTime();
3623 string result = date.ToString("yyyy-MM-dd");
3624 return result;
3625 }
3626
3627 public LSL_Types.LSLInteger llEdgeOfWorld(LSL_Types.Vector3 pos, LSL_Types.Vector3 dir)
3628 {
3629 m_host.AddScriptLPS(1);
3630 NotImplemented("llEdgeOfWorld");
3631 return 0;
3632 }
3633
3634 public LSL_Types.LSLInteger llGetAgentInfo(string id)
3635 {
3636 m_host.AddScriptLPS(1);
3637 NotImplemented("llGetAgentInfo");
3638 return 0;
3639 }
3640
3641 public void llAdjustSoundVolume(double volume)
3642 {
3643 m_host.AddScriptLPS(1);
3644 m_host.AdjustSoundGain(volume);
3645 }
3646
3647 public void llSetSoundQueueing(int queue)
3648 {
3649 m_host.AddScriptLPS(1);
3650 NotImplemented("llSetSoundQueueing");
3651 }
3652
3653 public void llSetSoundRadius(double radius)
3654 {
3655 m_host.AddScriptLPS(1);
3656 NotImplemented("llSetSoundRadius");
3657 }
3658
3659 public string llKey2Name(string id)
3660 {
3661 m_host.AddScriptLPS(1);
3662 LLUUID key = new LLUUID();
3663 if (LLUUID.TryParse(id,out key))
3664 {
3665 ScenePresence presence = World.GetScenePresence(key);
3666
3667 if (presence != null)
3668 {
3669 return presence.Name;
3670 }
3671
3672 if (World.GetSceneObjectPart(key) != null)
3673 {
3674 return World.GetSceneObjectPart(key).Name;
3675 }
3676 }
3677 return String.Empty;
3678 }
3679
3680
3681
3682 public void llSetTextureAnim(int mode, int face, int sizex, int sizey, double start, double length, double rate)
3683 {
3684 m_host.AddScriptLPS(1);
3685 Primitive.TextureAnimation pTexAnim = new Primitive.TextureAnimation();
3686 pTexAnim.Flags =(uint) mode;
3687
3688 //ALL_SIDES
3689 if (face == -1)
3690 face = 255;
3691
3692 pTexAnim.Face = (uint)face;
3693 pTexAnim.Length = (float)length;
3694 pTexAnim.Rate = (float)rate;
3695 pTexAnim.SizeX = (uint)sizex;
3696 pTexAnim.SizeY = (uint)sizey;
3697 pTexAnim.Start = (float)start;
3698
3699 m_host.AddTextureAnimation(pTexAnim);
3700 m_host.SendFullUpdateToAllClients();
3701 }
3702
3703 public void llTriggerSoundLimited(string sound, double volume, LSL_Types.Vector3 top_north_east,
3704 LSL_Types.Vector3 bottom_south_west)
3705 {
3706 m_host.AddScriptLPS(1);
3707 NotImplemented("llTriggerSoundLimited");
3708 }
3709
3710 public void llEjectFromLand(string pest)
3711 {
3712 m_host.AddScriptLPS(1);
3713 NotImplemented("llEjectFromLand");
3714 }
3715
3716 public LSL_Types.list llParseString2List(string str, LSL_Types.list separators, LSL_Types.list spacers)
3717 {
3718 m_host.AddScriptLPS(1);
3719 LSL_Types.list ret = new LSL_Types.list();
3720 object[] delimiters = new object[separators.Length + spacers.Length];
3721 separators.Data.CopyTo(delimiters, 0);
3722 spacers.Data.CopyTo(delimiters, separators.Length);
3723 bool dfound = false;
3724 do
3725 {
3726 dfound = false;
3727 int cindex = -1;
3728 string cdeli = "";
3729 for (int i = 0; i < delimiters.Length; i++)
3730 {
3731 int index = str.IndexOf(delimiters[i].ToString());
3732 bool found = index != -1;
3733 if (found)
3734 {
3735 if ((cindex > index) || (cindex == -1))
3736 {
3737 cindex = index;
3738 cdeli = (string)delimiters[i];
3739 }
3740 dfound = dfound || found;
3741 }
3742 }
3743 if (cindex != -1)
3744 {
3745 if (cindex > 0)
3746 {
3747 ret.Add(str.Substring(0, cindex));
3748 if (spacers.Contains(cdeli))
3749 {
3750 ret.Add(cdeli);
3751 }
3752 }
3753 if (cindex == 0 && spacers.Contains(cdeli))
3754 {
3755 ret.Add(cdeli);
3756 }
3757 str = str.Substring(cindex + cdeli.Length);
3758 }
3759 } while (dfound);
3760 if (str != "")
3761 {
3762 ret.Add(str);
3763 }
3764 return ret;
3765 }
3766
3767 public LSL_Types.LSLInteger llOverMyLand(string id)
3768 {
3769
3770 m_host.AddScriptLPS(1);
3771 LLUUID key = new LLUUID();
3772 if (LLUUID.TryParse(id,out key))
3773 {
3774 SceneObjectPart obj = new SceneObjectPart();
3775 obj = World.GetSceneObjectPart(World.Entities[key].LocalId);
3776 if (obj.OwnerID == World.GetLandOwner(obj.AbsolutePosition.X, obj.AbsolutePosition.Y))
3777 {
3778 return 1;
3779 }
3780 else
3781 {
3782 return 0;
3783 }
3784 }
3785 else
3786 {
3787 return 0;
3788 }
3789 }
3790
3791 public string llGetLandOwnerAt(LSL_Types.Vector3 pos)
3792 {
3793 m_host.AddScriptLPS(1);
3794 return World.GetLandOwner((float)pos.x, (float)pos.y).ToString();
3795 }
3796
3797 public LSL_Types.Vector3 llGetAgentSize(string id)
3798 {
3799 m_host.AddScriptLPS(1);
3800 NotImplemented("llGetAgentSize");
3801 return new LSL_Types.Vector3();
3802 }
3803
3804 public LSL_Types.LSLInteger llSameGroup(string agent)
3805 {
3806 m_host.AddScriptLPS(1);
3807 NotImplemented("llSameGroup");
3808 return 0;
3809 }
3810
3811 public void llUnSit(string id)
3812 {
3813 m_host.AddScriptLPS(1);
3814
3815 LLUUID key = new LLUUID();
3816 if (LLUUID.TryParse(id, out key))
3817 {
3818 ScenePresence av = World.GetScenePresence(key);
3819
3820 if (av != null)
3821 {
3822 if (llAvatarOnSitTarget() == id)
3823 {
3824 // if the avatar is sitting on this object, then
3825 // we can unsit them. We don't want random scripts unsitting random people
3826 // Lets avoid the popcorn avatar scenario.
3827 av.StandUp();
3828 }
3829 else
3830 {
3831 // If the object owner also owns the parcel
3832 // or
3833 // if the land is group owned and the object is group owned by the same group
3834 // or
3835 // if the object is owned by a person with estate access.
3836
3837 ILandObject parcel = World.LandChannel.GetLandObject(av.AbsolutePosition.X, av.AbsolutePosition.Y);
3838 if (parcel != null)
3839 {
3840 if (m_host.ObjectOwner == parcel.landData.ownerID ||
3841 (m_host.OwnerID == m_host.GroupID && m_host.GroupID == parcel.landData.groupID
3842 && parcel.landData.isGroupOwned) || World.ExternalChecks.ExternalChecksCanBeGodLike(m_host.OwnerID))
3843 {
3844 av.StandUp();
3845 }
3846 }
3847 }
3848 }
3849
3850 }
3851
3852 }
3853
3854 public LSL_Types.Vector3 llGroundSlope(LSL_Types.Vector3 offset)
3855 {
3856 m_host.AddScriptLPS(1);
3857 NotImplemented("llGroundSlope");
3858 return new LSL_Types.Vector3();
3859 }
3860
3861 public LSL_Types.Vector3 llGroundNormal(LSL_Types.Vector3 offset)
3862 {
3863 m_host.AddScriptLPS(1);
3864 NotImplemented("llGroundNormal");
3865 return new LSL_Types.Vector3();
3866 }
3867
3868 public LSL_Types.Vector3 llGroundContour(LSL_Types.Vector3 offset)
3869 {
3870 m_host.AddScriptLPS(1);
3871 NotImplemented("llGroundContour");
3872 return new LSL_Types.Vector3();
3873 }
3874
3875 public LSL_Types.LSLInteger llGetAttached()
3876 {
3877 m_host.AddScriptLPS(1);
3878 NotImplemented("llGetAttached");
3879 return 0;
3880 }
3881
3882 public LSL_Types.LSLInteger llGetFreeMemory()
3883 {
3884 m_host.AddScriptLPS(1);
3885 NotImplemented("llGetFreeMemory");
3886 return 0;
3887 }
3888
3889 public string llGetRegionName()
3890 {
3891 m_host.AddScriptLPS(1);
3892 return World.RegionInfo.RegionName;
3893 }
3894
3895 public double llGetRegionTimeDilation()
3896 {
3897 m_host.AddScriptLPS(1);
3898 return (double)World.TimeDilation;
3899 }
3900
3901 public double llGetRegionFPS()
3902 {
3903 m_host.AddScriptLPS(1);
3904 //TODO: return actual FPS
3905 return 10.0f;
3906 }
3907
3908 /* particle system rules should be coming into this routine as doubles, that is
3909 rule[0] should be an integer from this list and rule[1] should be the arg
3910 for the same integer. wiki.secondlife.com has most of this mapping, but some
3911 came from http://www.caligari-designs.com/p4u2
3912
3913 We iterate through the list for 'Count' elements, incrementing by two for each
3914 iteration and set the members of Primitive.ParticleSystem, one at a time.
3915 */
3916
3917 public enum PrimitiveRule : int
3918 {
3919 PSYS_PART_FLAGS = 0,
3920 PSYS_PART_START_COLOR = 1,
3921 PSYS_PART_START_ALPHA = 2,
3922 PSYS_PART_END_COLOR = 3,
3923 PSYS_PART_END_ALPHA = 4,
3924 PSYS_PART_START_SCALE = 5,
3925 PSYS_PART_END_SCALE = 6,
3926 PSYS_PART_MAX_AGE = 7,
3927 PSYS_SRC_ACCEL = 8,
3928 PSYS_SRC_PATTERN = 9,
3929 PSYS_SRC_TEXTURE = 12,
3930 PSYS_SRC_BURST_RATE = 13,
3931 PSYS_SRC_BURST_PART_COUNT = 15,
3932 PSYS_SRC_BURST_RADIUS = 16,
3933 PSYS_SRC_BURST_SPEED_MIN = 17,
3934 PSYS_SRC_BURST_SPEED_MAX = 18,
3935 PSYS_SRC_MAX_AGE = 19,
3936 PSYS_SRC_TARGET_KEY = 20,
3937 PSYS_SRC_OMEGA = 21,
3938 PSYS_SRC_ANGLE_BEGIN = 22,
3939 PSYS_SRC_ANGLE_END = 23
3940 }
3941
3942 internal Primitive.ParticleSystem.ParticleDataFlags ConvertUINTtoFlags(uint flags)
3943 {
3944 Primitive.ParticleSystem.ParticleDataFlags returnval = Primitive.ParticleSystem.ParticleDataFlags.None;
3945
3946 return returnval;
3947 }
3948
3949
3950 public void llParticleSystem(LSL_Types.list rules)
3951 {
3952 m_host.AddScriptLPS(1);
3953 Primitive.ParticleSystem prules = new Primitive.ParticleSystem();
3954 LSL_Types.Vector3 tempv = new LSL_Types.Vector3();
3955
3956 float tempf = 0;
3957
3958 for (int i = 0; i < rules.Length; i += 2)
3959 {
3960 switch ((int)rules.Data[i])
3961 {
3962 case (int)BuiltIn_Commands_BaseClass.PSYS_PART_FLAGS:
3963 prules.PartDataFlags = (Primitive.ParticleSystem.ParticleDataFlags)((uint)Convert.ToInt32(rules.Data[i + 1].ToString()));
3964 break;
3965
3966 case (int)BuiltIn_Commands_BaseClass.PSYS_PART_START_COLOR:
3967 tempv = (LSL_Types.Vector3)rules.Data[i + 1];
3968 prules.PartStartColor.R = (float)tempv.x;
3969 prules.PartStartColor.G = (float)tempv.y;
3970 prules.PartStartColor.B = (float)tempv.z;
3971 break;
3972
3973 case (int)BuiltIn_Commands_BaseClass.PSYS_PART_START_ALPHA:
3974 tempf = Convert.ToSingle(rules.Data[i + 1].ToString());
3975 prules.PartStartColor.A = (float)tempf;
3976 break;
3977
3978 case (int)BuiltIn_Commands_BaseClass.PSYS_PART_END_COLOR:
3979 tempv = (LSL_Types.Vector3)rules.Data[i + 1];
3980 //prules.PartEndColor = new LLColor(tempv.x,tempv.y,tempv.z,1);
3981
3982 prules.PartEndColor.R = (float)tempv.x;
3983 prules.PartEndColor.G = (float)tempv.y;
3984 prules.PartEndColor.B = (float)tempv.z;
3985 break;
3986
3987 case (int)BuiltIn_Commands_BaseClass.PSYS_PART_END_ALPHA:
3988 tempf = Convert.ToSingle(rules.Data[i + 1].ToString());
3989 prules.PartEndColor.A = (float)tempf;
3990 break;
3991
3992 case (int)BuiltIn_Commands_BaseClass.PSYS_PART_START_SCALE:
3993 tempv = (LSL_Types.Vector3)rules.Data[i + 1];
3994 prules.PartStartScaleX = (float)tempv.x;
3995 prules.PartStartScaleY = (float)tempv.y;
3996 break;
3997
3998 case (int)BuiltIn_Commands_BaseClass.PSYS_PART_END_SCALE:
3999 tempv = (LSL_Types.Vector3)rules.Data[i + 1];
4000 prules.PartEndScaleX = (float)tempv.x;
4001 prules.PartEndScaleY = (float)tempv.y;
4002 break;
4003
4004 case (int)BuiltIn_Commands_BaseClass.PSYS_PART_MAX_AGE:
4005 tempf = Convert.ToSingle(rules.Data[i + 1].ToString());
4006 prules.PartMaxAge = (float)tempf;
4007 break;
4008
4009 case (int)BuiltIn_Commands_BaseClass.PSYS_SRC_ACCEL:
4010 tempv = (LSL_Types.Vector3)rules.Data[i + 1];
4011 prules.PartAcceleration.X = (float)tempv.x;
4012 prules.PartAcceleration.Y = (float)tempv.y;
4013 prules.PartAcceleration.Z = (float)tempv.z;
4014 break;
4015
4016 case (int)BuiltIn_Commands_BaseClass.PSYS_SRC_PATTERN:
4017 int tmpi = int.Parse(rules.Data[i + 1].ToString());
4018 prules.Pattern = (Primitive.ParticleSystem.SourcePattern)tmpi;
4019 break;
4020
4021 // Xantor 03-May-2008
4022 // Wiki: PSYS_SRC_TEXTURE string inventory item name or key of the particle texture
4023 // "" = default texture.
4024 case (int)BuiltIn_Commands_BaseClass.PSYS_SRC_TEXTURE:
4025 LLUUID tkey = LLUUID.Zero;
4026
4027 // if we can parse the string as a key, use it.
4028 if (LLUUID.TryParse(rules.Data[i + 1].ToString(), out tkey))
4029 {
4030 prules.Texture = tkey;
4031 }
4032 // else try to locate the name in inventory of object. found returns key,
4033 // not found returns LLUUID.Zero which will translate to the default particle texture
4034 else
4035 {
4036 prules.Texture = InventoryKey(rules.Data[i+1].ToString());
4037 }
4038 break;
4039
4040 case (int)BuiltIn_Commands_BaseClass.PSYS_SRC_BURST_RATE:
4041 tempf = Convert.ToSingle(rules.Data[i + 1].ToString());
4042 prules.BurstRate = (float)tempf;
4043 break;
4044
4045 case (int)BuiltIn_Commands_BaseClass.PSYS_SRC_BURST_PART_COUNT:
4046 prules.BurstPartCount = (byte)Convert.ToByte(rules.Data[i + 1].ToString());
4047 break;
4048
4049 case (int)BuiltIn_Commands_BaseClass.PSYS_SRC_BURST_RADIUS:
4050 tempf = Convert.ToSingle(rules.Data[i + 1].ToString());
4051 prules.BurstRadius = (float)tempf;
4052 break;
4053
4054 case (int)BuiltIn_Commands_BaseClass.PSYS_SRC_BURST_SPEED_MIN:
4055 tempf = Convert.ToSingle(rules.Data[i + 1].ToString());
4056 prules.BurstSpeedMin = (float)tempf;
4057 break;
4058
4059 case (int)BuiltIn_Commands_BaseClass.PSYS_SRC_BURST_SPEED_MAX:
4060 tempf = Convert.ToSingle(rules.Data[i + 1].ToString());
4061 prules.BurstSpeedMax = (float)tempf;
4062 break;
4063
4064 case (int)BuiltIn_Commands_BaseClass.PSYS_SRC_MAX_AGE:
4065 tempf = Convert.ToSingle(rules.Data[i + 1].ToString());
4066 prules.MaxAge = (float)tempf;
4067 break;
4068
4069 case (int)BuiltIn_Commands_BaseClass.PSYS_SRC_TARGET_KEY:
4070 LLUUID key = LLUUID.Zero;
4071 if (LLUUID.TryParse(rules.Data[i + 1].ToString(), out key))
4072 {
4073 prules.Target = key;
4074 }
4075 else
4076 {
4077 prules.Target = m_host.UUID;
4078 }
4079 break;
4080
4081 case (int)BuiltIn_Commands_BaseClass.PSYS_SRC_OMEGA:
4082 // AL: This is an assumption, since it is the only thing that would match.
4083 tempv = (LSL_Types.Vector3)rules.Data[i + 1];
4084 prules.AngularVelocity.X = (float)tempv.x;
4085 prules.AngularVelocity.Y = (float)tempv.y;
4086 prules.AngularVelocity.Z = (float)tempv.z;
4087 //cast?? prules.MaxAge = (float)rules[i + 1];
4088 break;
4089
4090 case (int)BuiltIn_Commands_BaseClass.PSYS_SRC_ANGLE_BEGIN:
4091 tempf = Convert.ToSingle(rules.Data[i + 1].ToString());
4092 prules.InnerAngle = (float)tempf;
4093 break;
4094
4095 case (int)BuiltIn_Commands_BaseClass.PSYS_SRC_ANGLE_END:
4096 tempf = Convert.ToSingle(rules.Data[i + 1].ToString());
4097 prules.OuterAngle = (float)tempf;
4098 break;
4099 }
4100
4101 }
4102 prules.CRC = 1;
4103
4104 m_host.AddNewParticleSystem(prules);
4105 m_host.SendFullUpdateToAllClients();
4106 }
4107
4108 public void llGroundRepel(double height, int water, double tau)
4109 {
4110 m_host.AddScriptLPS(1);
4111 NotImplemented("llGroundRepel");
4112 }
4113
4114 public void llGiveInventoryList(string destination, string category, LSL_Types.list inventory)
4115 {
4116 m_host.AddScriptLPS(1);
4117 NotImplemented("llGiveInventoryList");
4118 }
4119
4120 public void llSetVehicleType(int type)
4121 {
4122 m_host.AddScriptLPS(1);
4123 NotImplemented("llSetVehicleType");
4124 }
4125
4126 public void llSetVehicledoubleParam(int param, double value)
4127 {
4128 m_host.AddScriptLPS(1);
4129 NotImplemented("llSetVehicledoubleParam");
4130 }
4131
4132 public void llSetVehicleFloatParam(int param, float value)
4133 {
4134 m_host.AddScriptLPS(1);
4135 NotImplemented("llSetVehicleFloatParam");
4136 }
4137
4138 public void llSetVehicleVectorParam(int param, LSL_Types.Vector3 vec)
4139 {
4140 m_host.AddScriptLPS(1);
4141 NotImplemented("llSetVehicleVectorParam");
4142 }
4143
4144 public void llSetVehicleRotationParam(int param, LSL_Types.Quaternion rot)
4145 {
4146 m_host.AddScriptLPS(1);
4147 NotImplemented("llSetVehicleRotationParam");
4148 }
4149
4150 public void llSetVehicleFlags(int flags)
4151 {
4152 m_host.AddScriptLPS(1);
4153 NotImplemented("llSetVehicleFlags");
4154 }
4155
4156 public void llRemoveVehicleFlags(int flags)
4157 {
4158 m_host.AddScriptLPS(1);
4159 NotImplemented("llRemoveVehicleFlags");
4160 }
4161
4162 public void llSitTarget(LSL_Types.Vector3 offset, LSL_Types.Quaternion rot)
4163 {
4164 m_host.AddScriptLPS(1);
4165 // LSL quaternions can normalize to 0, normal Quaternions can't.
4166 if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0)
4167 rot.z = 1; // ZERO_ROTATION = 0,0,0,1
4168
4169 m_host.SetSitTarget(new Vector3((float)offset.x, (float)offset.y, (float)offset.z), new Quaternion((float)rot.s, (float)rot.x, (float)rot.y, (float)rot.z));
4170 }
4171
4172 public string llAvatarOnSitTarget()
4173 {
4174 m_host.AddScriptLPS(1);
4175 return m_host.GetAvatarOnSitTarget().ToString();
4176 //LLUUID AVID = m_host.GetAvatarOnSitTarget();
4177
4178 //if (AVID != LLUUID.Zero)
4179 // return AVID.ToString();
4180 //else
4181 // return String.Empty;
4182 }
4183
4184 public void llAddToLandPassList(string avatar, double hours)
4185 {
4186 m_host.AddScriptLPS(1);
4187 LLUUID key;
4188 LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData;
4189 if (land.ownerID == m_host.OwnerID)
4190 {
4191 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
4192 if (LLUUID.TryParse(avatar, out key))
4193 {
4194 entry.AgentID = key;
4195 entry.Flags = ParcelManager.AccessList.Access;
4196 entry.Time = DateTime.Now.AddHours(hours);
4197 land.parcelAccessList.Add(entry);
4198 }
4199 }
4200 }
4201
4202 public void llSetTouchText(string text)
4203 {
4204 m_host.AddScriptLPS(1);
4205 m_host.TouchName = text;
4206 }
4207
4208 public void llSetSitText(string text)
4209 {
4210 m_host.AddScriptLPS(1);
4211 m_host.SitName = text;
4212 }
4213
4214 public void llSetCameraEyeOffset(LSL_Types.Vector3 offset)
4215 {
4216 m_host.AddScriptLPS(1);
4217 NotImplemented("llSetCameraEyeOffset");
4218 }
4219
4220 public void llSetCameraAtOffset(LSL_Types.Vector3 offset)
4221 {
4222 m_host.AddScriptLPS(1);
4223 NotImplemented("llSetCameraAtOffset");
4224 }
4225
4226 public string llDumpList2String(LSL_Types.list src, string seperator)
4227 {
4228 m_host.AddScriptLPS(1);
4229 if (src.Length == 0)
4230 {
4231 return String.Empty;
4232 }
4233 string ret = String.Empty;
4234 foreach (object o in src.Data)
4235 {
4236 ret = ret + o.ToString() + seperator;
4237 }
4238 ret = ret.Substring(0, ret.Length - seperator.Length);
4239 return ret;
4240 }
4241
4242 public LSL_Types.LSLInteger llScriptDanger(LSL_Types.Vector3 pos)
4243 {
4244 m_host.AddScriptLPS(1);
4245 bool result = World.scriptDanger(m_host.LocalId, new LLVector3((float)pos.x, (float)pos.y, (float)pos.z));
4246 if (result)
4247 {
4248 return 1;
4249 }
4250 else
4251 {
4252 return 0;
4253 }
4254
4255 }
4256
4257 public void llDialog(string avatar, string message, LSL_Types.list buttons, int chat_channel)
4258 {
4259 m_host.AddScriptLPS(1);
4260 LLUUID av = new LLUUID();
4261 if (!LLUUID.TryParse(avatar,out av))
4262 {
4263 LSLError("First parameter to llDialog needs to be a key");
4264 return;
4265 }
4266 if (buttons.Length > 12)
4267 {
4268 LSLError("No more than 12 buttons can be shown");
4269 return;
4270 }
4271 string[] buts = new string[buttons.Length];
4272 for (int i = 0; i < buttons.Length; i++)
4273 {
4274 if (buttons.Data[i].ToString() == String.Empty)
4275 {
4276 LSLError("button label cannot be blank");
4277 return;
4278 }
4279 if (buttons.Data[i].ToString().Length > 24)
4280 {
4281 LSLError("button label cannot be longer than 24 characters");
4282 return;
4283 }
4284 buts[i] = buttons.Data[i].ToString();
4285 }
4286 World.SendDialogToUser(av, m_host.Name, m_host.UUID, m_host.OwnerID, message, new LLUUID("00000000-0000-2222-3333-100000001000"), chat_channel, buts);
4287 }
4288
4289 public void llVolumeDetect(int detect)
4290 {
4291 m_host.AddScriptLPS(1);
4292 NotImplemented("llVolumeDetect");
4293 }
4294
4295 /// <summary>
4296 /// Reset the named script. The script must be present
4297 /// in the same prim.
4298 /// </summary>
4299
4300 public void llResetOtherScript(string name)
4301 {
4302 LLUUID item;
4303
4304 m_host.AddScriptLPS(1);
4305
4306 if ((item = ScriptByName(name)) != LLUUID.Zero)
4307 m_ScriptEngine.ResetScript(item);
4308 else
4309 ShoutError("llResetOtherScript: script "+name+" not found");
4310 }
4311
4312 public LSL_Types.LSLInteger llGetScriptState(string name)
4313 {
4314 LLUUID item;
4315
4316 m_host.AddScriptLPS(1);
4317
4318 if ((item = ScriptByName(name)) != LLUUID.Zero)
4319 {
4320 return m_ScriptEngine.GetScriptState(item) ?1:0;
4321 }
4322
4323 ShoutError("llGetScriptState: script "+name+" not found");
4324
4325 // If we didn't find it, then it's safe to
4326 // assume it is not running.
4327
4328 return 0;
4329 }
4330
4331 public void llRemoteLoadScript()
4332 {
4333 m_host.AddScriptLPS(1);
4334 Deprecated("llRemoteLoadScript");
4335 }
4336
4337 public void llSetRemoteScriptAccessPin(int pin)
4338 {
4339 m_host.AddScriptLPS(1);
4340 NotImplemented("llSetRemoteScriptAccessPin");
4341 }
4342
4343 public void llRemoteLoadScriptPin(string target, string name, int pin, int running, int start_param)
4344 {
4345 m_host.AddScriptLPS(1);
4346 NotImplemented("llRemoteLoadScriptPin");
4347 }
4348
4349 // remote_data(integer type, key channel, key message_id, string sender, integer ival, string sval)
4350 // Not sure where these constants should live:
4351 // REMOTE_DATA_CHANNEL = 1
4352 // REMOTE_DATA_REQUEST = 2
4353 // REMOTE_DATA_REPLY = 3
4354 public void llOpenRemoteDataChannel()
4355 {
4356 m_host.AddScriptLPS(1);
4357 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
4358 if (xmlrpcMod.IsEnabled())
4359 {
4360 LLUUID channelID = xmlrpcMod.OpenXMLRPCChannel(m_localID, m_itemID, LLUUID.Zero);
4361 object[] resobj = new object[] { new LSL_Types.LSLInteger(1), new LSL_Types.LSLString(channelID.ToString()), new LSL_Types.LSLString(LLUUID.Zero.ToString()), new LSL_Types.LSLString(String.Empty), new LSL_Types.LSLInteger(0), new LSL_Types.LSLString(String.Empty) };
4362 m_ScriptEngine.PostScriptEvent(m_itemID, new XEventParams(
4363 "remote_data", resobj,
4364 new XDetectParams[0]));
4365 }
4366 }
4367
4368 public string llSendRemoteData(string channel, string dest, int idata, string sdata)
4369 {
4370 m_host.AddScriptLPS(1);
4371 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
4372 return (xmlrpcMod.SendRemoteData(m_localID, m_itemID, channel, dest, idata, sdata)).ToString();
4373 }
4374
4375 public void llRemoteDataReply(string channel, string message_id, string sdata, int idata)
4376 {
4377 m_host.AddScriptLPS(1);
4378 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
4379 xmlrpcMod.RemoteDataReply(channel, message_id, sdata, idata);
4380 }
4381
4382 public void llCloseRemoteDataChannel(string channel)
4383 {
4384 m_host.AddScriptLPS(1);
4385 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
4386 xmlrpcMod.CloseXMLRPCChannel(channel);
4387 }
4388
4389 public string llMD5String(string src, int nonce)
4390 {
4391 m_host.AddScriptLPS(1);
4392 return Util.Md5Hash(src + ":" + nonce.ToString());
4393 }
4394
4395 public void llSetPrimitiveParams(LSL_Types.list rules)
4396 {
4397 llSetLinkPrimitiveParams(m_host.LinkNum+1, rules);
4398 }
4399
4400 public void llSetLinkPrimitiveParams(int linknumber, LSL_Types.list rules)
4401 {
4402 m_host.AddScriptLPS(1);
4403
4404 SceneObjectPart part=null;
4405
4406 if (m_host.LinkNum+1 != linknumber)
4407 {
4408 foreach (SceneObjectPart partInst in m_host.ParentGroup.GetParts())
4409 {
4410 if ((partInst.LinkNum + 1) == linknumber)
4411 {
4412 part = partInst;
4413 break;
4414 }
4415 }
4416 }
4417 else
4418 {
4419 part = m_host;
4420 }
4421
4422 if (part == null)
4423 return;
4424
4425 int idx = 0;
4426
4427 while (idx < rules.Length)
4428 {
4429 int code = Convert.ToInt32(rules.Data[idx++]);
4430
4431 int remain = rules.Length - idx;
4432
4433 int face;
4434 LSL_Types.Vector3 v;
4435
4436 switch (code)
4437 {
4438 case 6: // PRIM_POSITION
4439 if (remain < 1)
4440 return;
4441
4442 v=new LSL_Types.Vector3(rules.Data[idx++].ToString());
4443 SetPos(part, v);
4444
4445 break;
4446
4447 case 8: // PRIM_ROTATION
4448 if (remain < 1)
4449 return;
4450
4451 LSL_Types.Quaternion q = new LSL_Types.Quaternion(rules.Data[idx++].ToString());
4452 SetRot(part, q);
4453
4454 break;
4455
4456 case 17: // PRIM_TEXTURE
4457 if (remain < 5)
4458 return;
4459
4460 face=Convert.ToInt32(rules.Data[idx++]);
4461 string tex=rules.Data[idx++].ToString();
4462 LSL_Types.Vector3 repeats=new LSL_Types.Vector3(rules.Data[idx++].ToString());
4463 LSL_Types.Vector3 offsets=new LSL_Types.Vector3(rules.Data[idx++].ToString());
4464 double rotation=Convert.ToDouble(rules.Data[idx++]);
4465
4466 SetTexture(part, tex, face);
4467 ScaleTexture(part, repeats.x, repeats.y, face);
4468 OffsetTexture(part, offsets.x, offsets.y, face);
4469 RotateTexture(part, rotation, face);
4470
4471 break;
4472
4473 case 18: // PRIM_COLOR
4474 if (remain < 3)
4475 return;
4476
4477 face=Convert.ToInt32(rules.Data[idx++]);
4478 LSL_Types.Vector3 color=new LSL_Types.Vector3(rules.Data[idx++].ToString());
4479 double alpha=Convert.ToDouble(rules.Data[idx++]);
4480
4481 SetColor(part, color, face);
4482 SetAlpha(part, alpha, face);
4483
4484 break;
4485
4486 case 7: // PRIM_SIZE
4487 if (remain < 1)
4488 return;
4489
4490 v=new LSL_Types.Vector3(rules.Data[idx++].ToString());
4491 SetScale(part, v);
4492
4493 break;
4494 }
4495 }
4496 }
4497
4498 public string llStringToBase64(string str)
4499 {
4500 m_host.AddScriptLPS(1);
4501 try
4502 {
4503 byte[] encData_byte = new byte[str.Length];
4504 encData_byte = Encoding.UTF8.GetBytes(str);
4505 string encodedData = Convert.ToBase64String(encData_byte);
4506 return encodedData;
4507 }
4508 catch (Exception e)
4509 {
4510 throw new Exception("Error in base64Encode" + e.Message);
4511 }
4512 }
4513
4514 public string llBase64ToString(string str)
4515 {
4516 m_host.AddScriptLPS(1);
4517 UTF8Encoding encoder = new UTF8Encoding();
4518 Decoder utf8Decode = encoder.GetDecoder();
4519 try
4520 {
4521 byte[] todecode_byte = Convert.FromBase64String(str);
4522 int charCount = utf8Decode.GetCharCount(todecode_byte, 0, todecode_byte.Length);
4523 char[] decoded_char = new char[charCount];
4524 utf8Decode.GetChars(todecode_byte, 0, todecode_byte.Length, decoded_char, 0);
4525 string result = new String(decoded_char);
4526 return result;
4527 }
4528 catch (Exception e)
4529 {
4530 throw new Exception("Error in base64Decode" + e.Message);
4531 }
4532 }
4533
4534 public void llXorBase64Strings()
4535 {
4536 m_host.AddScriptLPS(1);
4537 Deprecated("llXorBase64Strings");
4538 }
4539
4540 public void llRemoteDataSetRegion()
4541 {
4542 m_host.AddScriptLPS(1);
4543 NotImplemented("llRemoteDataSetRegion");
4544 }
4545
4546 public double llLog10(double val)
4547 {
4548 m_host.AddScriptLPS(1);
4549 return (double)Math.Log10(val);
4550 }
4551
4552 public double llLog(double val)
4553 {
4554 m_host.AddScriptLPS(1);
4555 return (double)Math.Log(val);
4556 }
4557
4558 public LSL_Types.list llGetAnimationList(string id)
4559 {
4560 m_host.AddScriptLPS(1);
4561 NotImplemented("llGetAnimationList");
4562 return new LSL_Types.list();
4563 }
4564
4565 public void llSetParcelMusicURL(string url)
4566 {
4567 m_host.AddScriptLPS(1);
4568 LLUUID landowner = World.GetLandOwner(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y);
4569 if (landowner == LLUUID.Zero)
4570 {
4571 return;
4572 }
4573 if (landowner != m_host.ObjectOwner)
4574 {
4575 return;
4576 }
4577 World.SetLandMusicURL(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y, url);
4578 }
4579
4580 public void osSetParcelMediaURL(string url)
4581 {
4582 m_host.AddScriptLPS(1);
4583 LLUUID landowner = World.GetLandOwner(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y);
4584
4585 if (landowner == LLUUID.Zero)
4586 {
4587 return;
4588 }
4589
4590 if (landowner != m_host.ObjectOwner)
4591 {
4592 return;
4593 }
4594
4595 World.SetLandMediaURL(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y, url);
4596 }
4597
4598 public LSL_Types.Vector3 llGetRootPosition()
4599 {
4600 m_host.AddScriptLPS(1);
4601 return new LSL_Types.Vector3(m_host.ParentGroup.AbsolutePosition.X, m_host.ParentGroup.AbsolutePosition.Y, m_host.ParentGroup.AbsolutePosition.Z);
4602 }
4603
4604 public LSL_Types.Quaternion llGetRootRotation()
4605 {
4606 m_host.AddScriptLPS(1);
4607 return new LSL_Types.Quaternion(m_host.ParentGroup.GroupRotation.X, m_host.ParentGroup.GroupRotation.Y, m_host.ParentGroup.GroupRotation.Z, m_host.ParentGroup.GroupRotation.W);
4608 }
4609
4610 public string llGetObjectDesc()
4611 {
4612 return m_host.Description!=null?m_host.Description:String.Empty;
4613 }
4614
4615 public void llSetObjectDesc(string desc)
4616 {
4617 m_host.AddScriptLPS(1);
4618 m_host.Description = desc!=null?desc:String.Empty;
4619 }
4620
4621 public string llGetCreator()
4622 {
4623 m_host.AddScriptLPS(1);
4624 return m_host.ObjectCreator.ToString();
4625 }
4626
4627 public string llGetTimestamp()
4628 {
4629 m_host.AddScriptLPS(1);
4630 return DateTime.Now.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ");
4631 }
4632
4633 public void llSetLinkAlpha(int linknumber, double alpha, int face)
4634 {
4635 m_host.AddScriptLPS(1);
4636 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknumber);
4637 if (linknumber > -1)
4638 {
4639 LLObject.TextureEntry tex = part.Shape.Textures;
4640 LLColor texcolor;
4641 if (face > -1)
4642 {
4643 texcolor = tex.CreateFace((uint)face).RGBA;
4644 texcolor.A = (float)Math.Abs(alpha - 1);
4645 tex.FaceTextures[face].RGBA = texcolor;
4646 part.UpdateTexture(tex);
4647 return;
4648 }
4649 else if (face == -1)
4650 {
4651 texcolor = tex.DefaultTexture.RGBA;
4652 texcolor.A = (float)Math.Abs(alpha - 1);
4653 tex.DefaultTexture.RGBA = texcolor;
4654 for (uint i = 0; i < 32; i++)
4655 {
4656 if (tex.FaceTextures[i] != null)
4657 {
4658 texcolor = tex.FaceTextures[i].RGBA;
4659 texcolor.A = (float)Math.Abs(alpha - 1);
4660 tex.FaceTextures[i].RGBA = texcolor;
4661 }
4662 }
4663 texcolor = tex.DefaultTexture.RGBA;
4664 texcolor.A = (float)Math.Abs(alpha - 1);
4665 tex.DefaultTexture.RGBA = texcolor;
4666 part.UpdateTexture(tex);
4667 return;
4668 }
4669 return;
4670 }
4671 else if (linknumber == -1)
4672 {
4673 int num = m_host.ParentGroup.PrimCount;
4674 for (int w = 0; w < num; w++)
4675 {
4676 linknumber = w;
4677 part = m_host.ParentGroup.GetLinkNumPart(linknumber);
4678 LLObject.TextureEntry tex = part.Shape.Textures;
4679 LLColor texcolor;
4680 if (face > -1)
4681 {
4682 texcolor = tex.CreateFace((uint)face).RGBA;
4683 texcolor.A = (float)Math.Abs(alpha - 1);
4684 tex.FaceTextures[face].RGBA = texcolor;
4685 part.UpdateTexture(tex);
4686 }
4687 else if (face == -1)
4688 {
4689 texcolor = tex.DefaultTexture.RGBA;
4690 texcolor.A = (float)Math.Abs(alpha - 1);
4691 tex.DefaultTexture.RGBA = texcolor;
4692 for (uint i = 0; i < 32; i++)
4693 {
4694 if (tex.FaceTextures[i] != null)
4695 {
4696 texcolor = tex.FaceTextures[i].RGBA;
4697 texcolor.A = (float)Math.Abs(alpha - 1);
4698 tex.FaceTextures[i].RGBA = texcolor;
4699 }
4700 }
4701 texcolor = tex.DefaultTexture.RGBA;
4702 texcolor.A = (float)Math.Abs(alpha - 1);
4703 tex.DefaultTexture.RGBA = texcolor;
4704 part.UpdateTexture(tex);
4705 }
4706 }
4707 return;
4708 }
4709 }
4710
4711 public LSL_Types.LSLInteger llGetNumberOfPrims()
4712 {
4713 m_host.AddScriptLPS(1);
4714 return m_host.ParentGroup.PrimCount;
4715 }
4716
4717 public LSL_Types.list llGetBoundingBox(string obj)
4718 {
4719 m_host.AddScriptLPS(1);
4720 NotImplemented("llGetBoundingBox");
4721 return new LSL_Types.list();
4722 }
4723
4724 public LSL_Types.Vector3 llGetGeometricCenter()
4725 {
4726 return new LSL_Types.Vector3(m_host.GetGeometricCenter().X, m_host.GetGeometricCenter().Y, m_host.GetGeometricCenter().Z);
4727 }
4728
4729 public LSL_Types.list llGetPrimitiveParams(LSL_Types.list rules)
4730 {
4731 m_host.AddScriptLPS(1);
4732
4733 LSL_Types.list res = new LSL_Types.list();
4734 int idx=0;
4735 while (idx < rules.Length)
4736 {
4737 int code=Convert.ToInt32(rules.Data[idx++]);
4738 int remain=rules.Length-idx;
4739
4740 switch (code)
4741 {
4742 case 2: // PRIM_MATERIAL
4743 res.Add(new LSL_Types.LSLInteger(m_host.Material));
4744 break;
4745
4746 case 3: // PRIM_PHYSICS
4747 if ((m_host.GetEffectiveObjectFlags() & (uint)LLObject.ObjectFlags.Physics) != 0)
4748 res.Add(new LSL_Types.LSLInteger(1));
4749 else
4750 res.Add(new LSL_Types.LSLInteger(0));
4751 break;
4752
4753 case 4: // PRIM_TEMP_ON_REZ
4754 if ((m_host.GetEffectiveObjectFlags() & (uint)LLObject.ObjectFlags.TemporaryOnRez) != 0)
4755 res.Add(new LSL_Types.LSLInteger(1));
4756 else
4757 res.Add(new LSL_Types.LSLInteger(0));
4758 break;
4759
4760 case 5: // PRIM_PHANTOM
4761 if ((m_host.GetEffectiveObjectFlags() & (uint)LLObject.ObjectFlags.Phantom) != 0)
4762 res.Add(new LSL_Types.LSLInteger(1));
4763 else
4764 res.Add(new LSL_Types.LSLInteger(0));
4765 break;
4766
4767 case 6: // PRIM_POSITION
4768 res.Add(new LSL_Types.Vector3(m_host.AbsolutePosition.X,
4769 m_host.AbsolutePosition.Y,
4770 m_host.AbsolutePosition.Z));
4771 break;
4772
4773 case 7: // PRIM_SIZE
4774 res.Add(new LSL_Types.Vector3(m_host.Scale.X,
4775 m_host.Scale.Y,
4776 m_host.Scale.Z));
4777 break;
4778
4779 case 8: // PRIM_ROTATION
4780 res.Add(new LSL_Types.Quaternion(m_host.RotationOffset.X,
4781 m_host.RotationOffset.Y,
4782 m_host.RotationOffset.Z,
4783 m_host.RotationOffset.W));
4784 break;
4785
4786 case 9: // PRIM_TYPE
4787 // TODO--------------
4788 res.Add(new LSL_Types.LSLInteger(0));
4789 break;
4790
4791 case 17: // PRIM_TEXTURE
4792 if (remain < 1)
4793 return res;
4794
4795 int face=Convert.ToInt32(rules.Data[idx++]);
4796 if (face == -1)
4797 face = 0;
4798
4799 LLObject.TextureEntry tex = m_host.Shape.Textures;
4800 LLObject.TextureEntryFace texface = tex.GetFace((uint)face);
4801
4802 res.Add(new LSL_Types.LSLString(texface.TextureID.ToString()));
4803 res.Add(new LSL_Types.Vector3(texface.RepeatU,
4804 texface.RepeatV,
4805 0));
4806 res.Add(new LSL_Types.Vector3(texface.OffsetU,
4807 texface.OffsetV,
4808 0));
4809 res.Add(new LSL_Types.LSLFloat(texface.Rotation));
4810 break;
4811
4812 case 18: // PRIM_COLOR
4813 if (remain < 1)
4814 return res;
4815
4816 face=Convert.ToInt32(rules.Data[idx++]);
4817
4818 tex = m_host.Shape.Textures;
4819 LLColor texcolor;
4820 if (face == -1) // TMP: Until we can determine number of sides, ALL_SIDES (-1) will return default color
4821 texcolor = tex.DefaultTexture.RGBA;
4822 else
4823 texcolor = tex.GetFace((uint)face).RGBA;
4824 res.Add(new LSL_Types.Vector3((255 - (texcolor.R * 255)) / 255,
4825 (255 - (texcolor.G * 255)) / 255,
4826 (255 - (texcolor.B * 255)) / 255));
4827 res.Add(new LSL_Types.LSLFloat((texcolor.A * 255) / 255));
4828 break;
4829
4830 case 19: // PRIM_BUMP_SHINY
4831 // TODO--------------
4832 if (remain < 1)
4833 return res;
4834
4835 face=Convert.ToInt32(rules.Data[idx++]);
4836
4837 res.Add(new LSL_Types.LSLInteger(0));
4838 res.Add(new LSL_Types.LSLInteger(0));
4839 break;
4840
4841 case 20: // PRIM_FULLBRIGHT
4842 // TODO--------------
4843 if (remain < 1)
4844 return res;
4845
4846 face=Convert.ToInt32(rules.Data[idx++]);
4847
4848 res.Add(new LSL_Types.LSLInteger(0));
4849 break;
4850
4851 case 21: // PRIM_FLEXIBLE
4852 PrimitiveBaseShape shape = m_host.Shape;
4853
4854 if (shape.FlexiEntry)
4855 res.Add(new LSL_Types.LSLInteger(1)); // active
4856 else
4857 res.Add(new LSL_Types.LSLInteger(0));
4858 res.Add(new LSL_Types.LSLInteger(shape.FlexiSoftness));// softness
4859 res.Add(new LSL_Types.LSLFloat(shape.FlexiGravity)); // gravity
4860 res.Add(new LSL_Types.LSLFloat(shape.FlexiDrag)); // friction
4861 res.Add(new LSL_Types.LSLFloat(shape.FlexiWind)); // wind
4862 res.Add(new LSL_Types.LSLFloat(shape.FlexiTension)); // tension
4863 res.Add(new LSL_Types.Vector3(shape.FlexiForceX, // force
4864 shape.FlexiForceY,
4865 shape.FlexiForceZ));
4866 break;
4867
4868 case 22: // PRIM_TEXGEN
4869 // TODO--------------
4870 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
4871 if (remain < 1)
4872 return res;
4873
4874 face=Convert.ToInt32(rules.Data[idx++]);
4875
4876 res.Add(new LSL_Types.LSLInteger(0));
4877 break;
4878
4879 case 23: // PRIM_POINT_LIGHT:
4880 shape = m_host.Shape;
4881
4882 if (shape.LightEntry)
4883 res.Add(new LSL_Types.LSLInteger(1)); // active
4884 else
4885 res.Add(new LSL_Types.LSLInteger(0));
4886 res.Add(new LSL_Types.Vector3(shape.LightColorR, // color
4887 shape.LightColorG,
4888 shape.LightColorB));
4889 res.Add(new LSL_Types.LSLFloat(shape.LightIntensity)); // intensity
4890 res.Add(new LSL_Types.LSLFloat(shape.LightRadius)); // radius
4891 res.Add(new LSL_Types.LSLFloat(shape.LightFalloff)); // falloff
4892 break;
4893
4894 case 24: // PRIM_GLOW
4895 // TODO--------------
4896 if (remain < 1)
4897 return res;
4898
4899 face=Convert.ToInt32(rules.Data[idx++]);
4900
4901 res.Add(new LSL_Types.LSLFloat(0));
4902 break;
4903 }
4904 }
4905 return res;
4906 }
4907
4908 // <remarks>
4909 // <para>
4910 // The .NET definition of base 64 is:
4911 // <list>
4912 // <item>
4913 // Significant: A-Z a-z 0-9 + -
4914 // </item>
4915 // <item>
4916 // Whitespace: \t \n \r ' '
4917 // </item>
4918 // <item>
4919 // Valueless: =
4920 // </item>
4921 // <item>
4922 // End-of-string: \0 or '=='
4923 // </item>
4924 // </list>
4925 // </para>
4926 // <para>
4927 // Each point in a base-64 string represents
4928 // a 6 bit value. A 32-bit integer can be
4929 // represented using 6 characters (with some
4930 // redundancy).
4931 // </para>
4932 // <para>
4933 // LSL requires a base64 string to be 8
4934 // characters in length. LSL also uses '/'
4935 // rather than '-' (MIME compliant).
4936 // </para>
4937 // <para>
4938 // RFC 1341 used as a reference (as specified
4939 // by the SecondLife Wiki).
4940 // </para>
4941 // <para>
4942 // SL do not record any kind of exception for
4943 // these functions, so the string to integer
4944 // conversion returns '0' if an invalid
4945 // character is encountered during conversion.
4946 // </para>
4947 // <para>
4948 // References
4949 // <list>
4950 // <item>
4951 // http://lslwiki.net/lslwiki/wakka.php?wakka=Base64
4952 // </item>
4953 // <item>
4954 // </item>
4955 // </list>
4956 // </para>
4957 // </remarks>
4958
4959 // <summary>
4960 // Table for converting 6-bit integers into
4961 // base-64 characters
4962 // </summary>
4963
4964 private static readonly char[] i2ctable =
4965 {
4966 'A','B','C','D','E','F','G','H',
4967 'I','J','K','L','M','N','O','P',
4968 'Q','R','S','T','U','V','W','X',
4969 'Y','Z',
4970 'a','b','c','d','e','f','g','h',
4971 'i','j','k','l','m','n','o','p',
4972 'q','r','s','t','u','v','w','x',
4973 'y','z',
4974 '0','1','2','3','4','5','6','7',
4975 '8','9',
4976 '+','/'
4977 };
4978
4979 // <summary>
4980 // Table for converting base-64 characters
4981 // into 6-bit integers.
4982 // </summary>
4983
4984 private static readonly int[] c2itable =
4985 {
4986 -1,-1,-1,-1,-1,-1,-1,-1, // 0x
4987 -1,-1,-1,-1,-1,-1,-1,-1,
4988 -1,-1,-1,-1,-1,-1,-1,-1, // 1x
4989 -1,-1,-1,-1,-1,-1,-1,-1,
4990 -1,-1,-1,-1,-1,-1,-1,-1, // 2x
4991 -1,-1,-1,63,-1,-1,-1,64,
4992 53,54,55,56,57,58,59,60, // 3x
4993 61,62,-1,-1,-1,0,-1,-1,
4994 -1,1,2,3,4,5,6,7, // 4x
4995 8,9,10,11,12,13,14,15,
4996 16,17,18,19,20,21,22,23, // 5x
4997 24,25,26,-1,-1,-1,-1,-1,
4998 -1,27,28,29,30,31,32,33, // 6x
4999 34,35,36,37,38,39,40,41,
5000 42,43,44,45,46,47,48,49, // 7x
5001 50,51,52,-1,-1,-1,-1,-1,
5002 -1,-1,-1,-1,-1,-1,-1,-1, // 8x
5003 -1,-1,-1,-1,-1,-1,-1,-1,
5004 -1,-1,-1,-1,-1,-1,-1,-1, // 9x
5005 -1,-1,-1,-1,-1,-1,-1,-1,
5006 -1,-1,-1,-1,-1,-1,-1,-1, // Ax
5007 -1,-1,-1,-1,-1,-1,-1,-1,
5008 -1,-1,-1,-1,-1,-1,-1,-1, // Bx
5009 -1,-1,-1,-1,-1,-1,-1,-1,
5010 -1,-1,-1,-1,-1,-1,-1,-1, // Cx
5011 -1,-1,-1,-1,-1,-1,-1,-1,
5012 -1,-1,-1,-1,-1,-1,-1,-1, // Dx
5013 -1,-1,-1,-1,-1,-1,-1,-1,
5014 -1,-1,-1,-1,-1,-1,-1,-1, // Ex
5015 -1,-1,-1,-1,-1,-1,-1,-1,
5016 -1,-1,-1,-1,-1,-1,-1,-1, // Fx
5017 -1,-1,-1,-1,-1,-1,-1,-1
5018 };
5019
5020 // <summary>
5021 // Converts a 32-bit integer into a Base64
5022 // character string. Base64 character strings
5023 // are always 8 characters long. All iinteger
5024 // values are acceptable.
5025 // </summary>
5026 // <param name="number">
5027 // 32-bit integer to be converted.
5028 // </param>
5029 // <returns>
5030 // 8 character string. The 1st six characters
5031 // contain the encoded number, the last two
5032 // characters are padded with "=".
5033 // </returns>
5034
5035 public string llIntegerToBase64(int number)
5036 {
5037 // uninitialized string
5038
5039 char[] imdt = new char[8];
5040
5041 m_host.AddScriptLPS(1);
5042
5043 // Manually unroll the loop
5044
5045 imdt[7] = '=';
5046 imdt[6] = '=';
5047 imdt[5] = i2ctable[number<<4 & 0x3F];
5048 imdt[4] = i2ctable[number>>2 & 0x3F];
5049 imdt[3] = i2ctable[number>>8 & 0x3F];
5050 imdt[2] = i2ctable[number>>14 & 0x3F];
5051 imdt[1] = i2ctable[number>>20 & 0x3F];
5052 imdt[0] = i2ctable[number>>26 & 0x3F];
5053
5054 return new string(imdt);
5055 }
5056
5057 // <summary>
5058 // Converts an eight character base-64 string
5059 // into a 32-bit integer.
5060 // </summary>
5061 // <param name="str">
5062 // 8 characters string to be converted. Other
5063 // length strings return zero.
5064 // </param>
5065 // <returns>
5066 // Returns an integer representing the
5067 // encoded value providedint he 1st 6
5068 // characters of the string.
5069 // </returns>
5070 // <remarks>
5071 // This is coded to behave like LSL's
5072 // implementation (I think), based upon the
5073 // information available at the Wiki.
5074 // If more than 8 characters are supplied,
5075 // zero is returned.
5076 // If a NULL string is supplied, zero will
5077 // be returned.
5078 // If fewer than 6 characters are supplied, then
5079 // the answer will reflect a partial
5080 // accumulation.
5081 // <para>
5082 // The 6-bit segments are
5083 // extracted left-to-right in big-endian mode,
5084 // which means that segment 6 only contains the
5085 // two low-order bits of the 32 bit integer as
5086 // its high order 2 bits. A short string therefore
5087 // means loss of low-order information. E.g.
5088 //
5089 // |<---------------------- 32-bit integer ----------------------->|<-Pad->|
5090 // |<--Byte 0----->|<--Byte 1----->|<--Byte 2----->|<--Byte 3----->|<-Pad->|
5091 // |3|3|2|2|2|2|2|2|2|2|2|2|1|1|1|1|1|1|1|1|1|1| | | | | | | | | | |P|P|P|P|
5092 // |1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|P|P|P|P|
5093 // | str[0] | str[1] | str[2] | str[3] | str[4] | str[6] |
5094 //
5095 // </para>
5096 // </remarks>
5097
5098 public LSL_Types.LSLInteger llBase64ToInteger(string str)
5099 {
5100 int number = 0;
5101 int digit;
5102
5103 m_host.AddScriptLPS(1);
5104
5105 // Require a well-fromed base64 string
5106
5107 if (str.Length > 8)
5108 return 0;
5109
5110 // The loop is unrolled in the interests
5111 // of performance and simple necessity.
5112 //
5113 // MUST find 6 digits to be well formed
5114 // -1 == invalid
5115 // 0 == padding
5116
5117 if ((digit=c2itable[str[0]])<=0)
5118 {
5119 return digit<0?(int)0:number;
5120 }
5121 number += --digit<<26;
5122
5123 if ((digit=c2itable[str[1]])<=0)
5124 {
5125 return digit<0?(int)0:number;
5126 }
5127 number += --digit<<20;
5128
5129 if ((digit=c2itable[str[2]])<=0)
5130 {
5131 return digit<0?(int)0:number;
5132 }
5133 number += --digit<<14;
5134
5135 if ((digit=c2itable[str[3]])<=0)
5136 {
5137 return digit<0?(int)0:number;
5138 }
5139 number += --digit<<8;
5140
5141 if ((digit=c2itable[str[4]])<=0)
5142 {
5143 return digit<0?(int)0:number;
5144 }
5145 number += --digit<<2;
5146
5147 if ((digit=c2itable[str[5]])<=0)
5148 {
5149 return digit<0?(int)0:number;
5150 }
5151 number += --digit>>4;
5152
5153 // ignore trailing padding
5154
5155 return number;
5156 }
5157
5158 public double llGetGMTclock()
5159 {
5160 m_host.AddScriptLPS(1);
5161 return DateTime.UtcNow.TimeOfDay.TotalSeconds;
5162 }
5163
5164 public string llGetSimulatorHostname()
5165 {
5166 m_host.AddScriptLPS(1);
5167 return System.Environment.MachineName;
5168 }
5169
5170 public void llSetLocalRot(LSL_Types.Quaternion rot)
5171 {
5172 m_host.AddScriptLPS(1);
5173 m_host.RotationOffset = new LLQuaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s);
5174 }
5175
5176 // <summary>
5177 // Scan the string supplied in 'src' and
5178 // tokenize it based upon two sets of
5179 // tokenizers provided in two lists,
5180 // separators and spacers.
5181 // </summary>
5182 //
5183 // <remarks>
5184 // Separators demarcate tokens and are
5185 // elided as they are encountered. Spacers
5186 // also demarcate tokens, but are themselves
5187 // retained as tokens.
5188 //
5189 // Both separators and spacers may be arbitrarily
5190 // long strings. i.e. ":::".
5191 //
5192 // The function returns an ordered list
5193 // representing the tokens found in the supplied
5194 // sources string. If two successive tokenizers
5195 // are encountered, then a NULL entry is added
5196 // to the list.
5197 //
5198 // It is a precondition that the source and
5199 // toekizer lisst are non-null. If they are null,
5200 // then a null pointer exception will be thrown
5201 // while their lengths are being determined.
5202 //
5203 // A small amount of working memoryis required
5204 // of approximately 8*#tokenizers.
5205 //
5206 // There are many ways in which this function
5207 // can be implemented, this implementation is
5208 // fairly naive and assumes that when the
5209 // function is invooked with a short source
5210 // string and/or short lists of tokenizers, then
5211 // performance will not be an issue.
5212 //
5213 // In order to minimize the perofrmance
5214 // effects of long strings, or large numbers
5215 // of tokeizers, the function skips as far as
5216 // possible whenever a toekenizer is found,
5217 // and eliminates redundant tokenizers as soon
5218 // as is possible.
5219 //
5220 // The implementation tries to avoid any copying
5221 // of arrays or other objects.
5222 // </remarks>
5223
5224 public LSL_Types.list llParseStringKeepNulls(string src, LSL_Types.list separators, LSL_Types.list spacers)
5225 {
5226 int beginning = 0;
5227 int srclen = src.Length;
5228 int seplen = separators.Length;
5229 object[] separray = separators.Data;
5230 int spclen = spacers.Length;
5231 object[] spcarray = spacers.Data;
5232 int mlen = seplen+spclen;
5233
5234 int[] offset = new int[mlen+1];
5235 bool[] active = new bool[mlen];
5236
5237 int best;
5238 int j;
5239
5240 // Initial capacity reduces resize cost
5241
5242 LSL_Types.list tokens = new LSL_Types.list();
5243
5244 m_host.AddScriptLPS(1);
5245
5246 // All entries are initially valid
5247
5248 for (int i = 0; i < mlen; i++)
5249 active[i] = true;
5250
5251 offset[mlen] = srclen;
5252
5253 while (beginning < srclen)
5254 {
5255
5256 best = mlen; // as bad as it gets
5257
5258 // Scan for separators
5259
5260 for (j = 0; j < seplen; j++)
5261 {
5262 if (active[j])
5263 {
5264 // scan all of the markers
5265 if ((offset[j] = src.IndexOf((string)separray[j],beginning)) == -1)
5266 {
5267 // not present at all
5268 active[j] = false;
5269 }
5270 else
5271 {
5272 // present and correct
5273 if (offset[j] < offset[best])
5274 {
5275 // closest so far
5276 best = j;
5277 if (offset[best] == beginning)
5278 break;
5279 }
5280 }
5281 }
5282 }
5283
5284 // Scan for spacers
5285
5286 if (offset[best] != beginning)
5287 {
5288 for (j = seplen; (j < mlen) && (offset[best] > beginning); j++)
5289 {
5290 if (active[j])
5291 {
5292 // scan all of the markers
5293 if ((offset[j] = src.IndexOf((string)spcarray[j-seplen],beginning)) == -1)
5294 {
5295 // not present at all
5296 active[j] = false;
5297 } else
5298 {
5299 // present and correct
5300 if (offset[j] < offset[best])
5301 {
5302 // closest so far
5303 best = j;
5304 }
5305 }
5306 }
5307 }
5308 }
5309
5310 // This is the normal exit from the scanning loop
5311
5312 if (best == mlen)
5313 {
5314 // no markers were found on this pass
5315 // so we're pretty much done
5316 tokens.Add(src.Substring(beginning, srclen-beginning));
5317 break;
5318 }
5319
5320 // Otherwise we just add the newly delimited token
5321 // and recalculate where the search should continue.
5322
5323 tokens.Add(src.Substring(beginning,offset[best]-beginning));
5324
5325 if (best<seplen)
5326 {
5327 beginning = offset[best]+((string)separray[best]).Length;
5328 } else
5329 {
5330 beginning = offset[best]+((string)spcarray[best-seplen]).Length;
5331 tokens.Add(spcarray[best-seplen]);
5332 }
5333
5334 }
5335
5336 // This an awkward an not very intuitive boundary case. If the
5337 // last substring is a tokenizer, then there is an implied trailing
5338 // null list entry. Hopefully the single comparison will not be too
5339 // arduous. Alternatively the 'break' could be replced with a return
5340 // but that's shabby programming.
5341
5342 if (beginning == srclen)
5343 {
5344 if (srclen != 0)
5345 tokens.Add("");
5346 }
5347
5348 return tokens;
5349 }
5350
5351 public void llRezAtRoot(string inventory, LSL_Types.Vector3 position, LSL_Types.Vector3 velocity,
5352 LSL_Types.Quaternion rot, int param)
5353 {
5354 m_host.AddScriptLPS(1);
5355 NotImplemented("llRezAtRoot");
5356 }
5357
5358 public LSL_Types.LSLInteger llGetObjectPermMask(int mask)
5359 {
5360 m_host.AddScriptLPS(1);
5361
5362 int permmask = 0;
5363
5364 if (mask == BuiltIn_Commands_BaseClass.MASK_BASE)//0
5365 {
5366 permmask = (int)m_host.BaseMask;
5367 }
5368
5369 else if (mask == BuiltIn_Commands_BaseClass.MASK_OWNER)//1
5370 {
5371 permmask = (int)m_host.OwnerMask;
5372 }
5373
5374 else if (mask == BuiltIn_Commands_BaseClass.MASK_GROUP)//2
5375 {
5376 permmask = (int)m_host.GroupMask;
5377 }
5378
5379 else if (mask == BuiltIn_Commands_BaseClass.MASK_EVERYONE)//3
5380 {
5381 permmask = (int)m_host.EveryoneMask;
5382 }
5383
5384 else if (mask == BuiltIn_Commands_BaseClass.MASK_NEXT)//4
5385 {
5386 permmask = (int)m_host.NextOwnerMask;
5387 }
5388
5389 return permmask;
5390 }
5391
5392 public void llSetObjectPermMask(int mask, int value)
5393 {
5394 m_host.AddScriptLPS(1);
5395
5396 if (mask == BuiltIn_Commands_BaseClass.MASK_BASE)//0
5397 {
5398 m_host.BaseMask = (uint)value;
5399 }
5400
5401 else if (mask == BuiltIn_Commands_BaseClass.MASK_OWNER)//1
5402 {
5403 m_host.OwnerMask = (uint)value;
5404 }
5405
5406 else if (mask == BuiltIn_Commands_BaseClass.MASK_GROUP)//2
5407 {
5408 m_host.GroupMask = (uint)value;
5409 }
5410
5411 else if (mask == BuiltIn_Commands_BaseClass.MASK_EVERYONE)//3
5412 {
5413 m_host.EveryoneMask = (uint)value;
5414 }
5415
5416 else if (mask == BuiltIn_Commands_BaseClass.MASK_NEXT)//4
5417 {
5418 m_host.NextOwnerMask = (uint)value;
5419 }
5420 }
5421
5422 public LSL_Types.LSLInteger llGetInventoryPermMask(string item, int mask)
5423 {
5424 m_host.AddScriptLPS(1);
5425 foreach (KeyValuePair<LLUUID, TaskInventoryItem> inv in m_host.TaskInventory)
5426 {
5427 if (inv.Value.Name == item)
5428 {
5429 switch (mask)
5430 {
5431 case 0:
5432 return (int)inv.Value.BaseMask;
5433 case 1:
5434 return (int)inv.Value.OwnerMask;
5435 case 2:
5436 return (int)inv.Value.GroupMask;
5437 case 3:
5438 return (int)inv.Value.EveryoneMask;
5439 case 4:
5440 return (int)inv.Value.NextOwnerMask;
5441 }
5442 }
5443 }
5444 return -1;
5445 }
5446
5447 public void llSetInventoryPermMask(string item, int mask, int value)
5448 {
5449 m_host.AddScriptLPS(1);
5450 NotImplemented("llSetInventoryPermMask");
5451 }
5452
5453 public string llGetInventoryCreator(string item)
5454 {
5455 m_host.AddScriptLPS(1);
5456 foreach (KeyValuePair<LLUUID, TaskInventoryItem> inv in m_host.TaskInventory)
5457 {
5458 if (inv.Value.Name == item)
5459 {
5460 return inv.Value.CreatorID.ToString();
5461 }
5462 }
5463 llSay(0, "No item name '" + item + "'");
5464 return String.Empty;
5465 }
5466
5467 public void llOwnerSay(string msg)
5468 {
5469 m_host.AddScriptLPS(1);
5470
5471 World.SimChatBroadcast(Helpers.StringToField(msg), ChatTypeEnum.Owner, 0, m_host.AbsolutePosition, m_host.Name, m_host.UUID, false);
5472// IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
5473// wComm.DeliverMessage(ChatTypeEnum.Owner, 0, m_host.Name, m_host.UUID, msg);
5474 }
5475
5476 public string llRequestSimulatorData(string simulator, int data)
5477 {
5478try
5479{
5480 m_host.AddScriptLPS(1);
5481
5482 string reply = String.Empty;
5483
5484 RegionInfo info = m_ScriptEngine.World.RequestClosestRegion(simulator);
5485
5486 switch(data)
5487 {
5488 case 5: // DATA_SIM_POS
5489 if(info == null)
5490 return LLUUID.Zero.ToString();
5491 reply = new LSL_Types.Vector3(
5492 info.RegionLocX * Constants.RegionSize,
5493 info.RegionLocY * Constants.RegionSize,
5494 0).ToString();
5495 break;
5496 case 6: // DATA_SIM_STATUS
5497 if(info != null)
5498 reply = "up"; // Duh!
5499 else
5500 reply = "unknown";
5501 break;
5502 case 7: // DATA_SIM_RATING
5503 if(info == null)
5504 return LLUUID.Zero.ToString();
5505 int access = (int)info.EstateSettings.simAccess;
5506 if(access == 21)
5507 reply = "MATURE";
5508 else if(access == 13)
5509 reply = "MATURE";
5510 else
5511 reply = "UNKNOWN";
5512 break;
5513 default:
5514 return LLUUID.Zero.ToString(); // Raise no event
5515 }
5516 LLUUID rq = LLUUID.Random();
5517
5518 LLUUID tid = m_ScriptEngine.m_ASYNCLSLCommandManager.
5519 m_Dataserver.RegisterRequest(m_localID,
5520 m_itemID, rq.ToString());
5521
5522 m_ScriptEngine.m_ASYNCLSLCommandManager.
5523 m_Dataserver.DataserverReply(rq.ToString(), reply);
5524
5525 return tid.ToString();
5526}
5527catch(Exception e)
5528{
5529Console.WriteLine(e.ToString());
5530return LLUUID.Zero.ToString();
5531}
5532 }
5533
5534 public void llForceMouselook(int mouselook)
5535 {
5536 m_host.AddScriptLPS(1);
5537 NotImplemented("llForceMouselook");
5538 }
5539
5540 public double llGetObjectMass(string id)
5541 {
5542 m_host.AddScriptLPS(1);
5543 LLUUID key = new LLUUID();
5544 if (LLUUID.TryParse(id,out key))
5545 {
5546 return (double)World.GetSceneObjectPart(World.Entities[key].LocalId).GetMass();
5547 }
5548 return 0;
5549 }
5550
5551 /// <summary>
5552 /// illListReplaceList removes the sub-list defined by the inclusive indices
5553 /// start and end and inserts the src list in its place. The inclusive
5554 /// nature of the indices means that at least one element must be deleted
5555 /// if the indices are within the bounds of the existing list. I.e. 2,2
5556 /// will remove the element at index 2 and replace it with the source
5557 /// list. Both indices may be negative, with the usual interpretation. An
5558 /// interesting case is where end is lower than start. As these indices
5559 /// bound the list to be removed, then 0->end, and start->lim are removed
5560 /// and the source list is added as a suffix.
5561 /// </summary>
5562
5563 public LSL_Types.list llListReplaceList(LSL_Types.list dest, LSL_Types.list src, int start, int end)
5564 {
5565
5566 LSL_Types.list pref = null;
5567
5568 m_host.AddScriptLPS(1);
5569
5570 // Note that although we have normalized, both
5571 // indices could still be negative.
5572 if (start < 0)
5573 {
5574 start = start+dest.Length;
5575 }
5576
5577 if (end < 0)
5578 {
5579 end = end+dest.Length;
5580 }
5581 // The comventional case, remove a sequence starting with
5582 // start and ending with end. And then insert the source
5583 // list.
5584 if (start <= end)
5585 {
5586 // If greater than zero, then there is going to be a
5587 // surviving prefix. Otherwise the inclusive nature
5588 // of the indices mean that we're going to add the
5589 // source list as a prefix.
5590 if (start > 0)
5591 {
5592 pref = dest.GetSublist(0,start-1);
5593 // Only add a suffix if there is something
5594 // beyond the end index (it's inclusive too).
5595 if (end+1 < dest.Length)
5596 {
5597 return pref + src + dest.GetSublist(end+1,-1);
5598 }
5599 else
5600 {
5601 return pref + src;
5602 }
5603 }
5604 // If start is less than or equal to zero, then
5605 // the new list is simply a prefix. We still need to
5606 // figure out any necessary surgery to the destination
5607 // based upon end. Note that if end exceeds the upper
5608 // bound in this case, the entire destination list
5609 // is removed.
5610 else
5611 {
5612 if (end+1 < dest.Length)
5613 {
5614 return src + dest.GetSublist(end+1,-1);
5615 }
5616 else
5617 {
5618 return src;
5619 }
5620 }
5621 }
5622 // Finally, if start > end, we strip away a prefix and
5623 // a suffix, to leave the list that sits <between> ens
5624 // and start, and then tag on the src list. AT least
5625 // that's my interpretation. We can get sublist to do
5626 // this for us. Note that one, or both of the indices
5627 // might have been negative.
5628 else
5629 {
5630 return dest.GetSublist(end+1,start-1)+src;
5631 }
5632 }
5633
5634 public void llLoadURL(string avatar_id, string message, string url)
5635 {
5636 m_host.AddScriptLPS(1);
5637 LLUUID avatarId = new LLUUID(avatar_id);
5638 m_ScriptEngine.World.SendUrlToUser(avatarId, m_host.Name, m_host.UUID, m_host.ObjectOwner, false, message,
5639 url);
5640 }
5641
5642 public void llParcelMediaCommandList(LSL_Types.list commandList)
5643 {
5644 m_host.AddScriptLPS(1);
5645 NotImplemented("llParcelMediaCommandList");
5646 }
5647
5648 public void llParcelMediaQuery()
5649 {
5650 m_host.AddScriptLPS(1);
5651 NotImplemented("llParcelMediaQuery");
5652 }
5653
5654 public LSL_Types.LSLInteger llModPow(int a, int b, int c)
5655 {
5656 m_host.AddScriptLPS(1);
5657 Int64 tmp = 0;
5658 Math.DivRem(Convert.ToInt64(Math.Pow(a, b)), c, out tmp);
5659 return Convert.ToInt32(tmp);
5660 }
5661
5662 public LSL_Types.LSLInteger llGetInventoryType(string name)
5663 {
5664 m_host.AddScriptLPS(1);
5665 foreach (KeyValuePair<LLUUID, TaskInventoryItem> inv in m_host.TaskInventory)
5666 {
5667 if (inv.Value.Name == name)
5668 {
5669 return inv.Value.InvType;
5670 }
5671 }
5672 return -1;
5673 }
5674
5675 public void llSetPayPrice(int price, LSL_Types.list quick_pay_buttons)
5676 {
5677 m_host.AddScriptLPS(1);
5678
5679 if (quick_pay_buttons.Data.Length != 4)
5680 {
5681 LSLError("List must have 4 elements");
5682 return;
5683 }
5684 m_host.ParentGroup.RootPart.PayPrice[0]=price;
5685 m_host.ParentGroup.RootPart.PayPrice[1]=(int)quick_pay_buttons.Data[0];
5686 m_host.ParentGroup.RootPart.PayPrice[2]=(int)quick_pay_buttons.Data[1];
5687 m_host.ParentGroup.RootPart.PayPrice[3]=(int)quick_pay_buttons.Data[2];
5688 m_host.ParentGroup.RootPart.PayPrice[4]=(int)quick_pay_buttons.Data[3];
5689 }
5690
5691 public LSL_Types.Vector3 llGetCameraPos()
5692 {
5693 m_host.AddScriptLPS(1);
5694 NotImplemented("llGetCameraPos");
5695 return new LSL_Types.Vector3();
5696 }
5697
5698 public LSL_Types.Quaternion llGetCameraRot()
5699 {
5700 m_host.AddScriptLPS(1);
5701 NotImplemented("llGetCameraRot");
5702 return new LSL_Types.Quaternion();
5703 }
5704
5705 public void llSetPrimURL()
5706 {
5707 m_host.AddScriptLPS(1);
5708 NotImplemented("llSetPrimURL");
5709 }
5710
5711 public void llRefreshPrimURL()
5712 {
5713 m_host.AddScriptLPS(1);
5714 NotImplemented("llRefreshPrimURL");
5715 }
5716
5717 public string llEscapeURL(string url)
5718 {
5719 m_host.AddScriptLPS(1);
5720 try
5721 {
5722 return Uri.EscapeUriString(url);
5723 }
5724 catch (Exception ex)
5725 {
5726 return "llEscapeURL: " + ex.ToString();
5727 }
5728 }
5729
5730 public string llUnescapeURL(string url)
5731 {
5732 m_host.AddScriptLPS(1);
5733 try
5734 {
5735 return Uri.UnescapeDataString(url);
5736 }
5737 catch (Exception ex)
5738 {
5739 return "llUnescapeURL: " + ex.ToString();
5740 }
5741 }
5742
5743 public void llMapDestination(string simname, LSL_Types.Vector3 pos, LSL_Types.Vector3 look_at)
5744 {
5745 m_host.AddScriptLPS(1);
5746 NotImplemented("llMapDestination");
5747 }
5748
5749 public void llAddToLandBanList(string avatar, double hours)
5750 {
5751 m_host.AddScriptLPS(1);
5752 LLUUID key;
5753 LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData;
5754 if (land.ownerID == m_host.OwnerID)
5755 {
5756 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
5757 if (LLUUID.TryParse(avatar, out key))
5758 {
5759 entry.AgentID = key;
5760 entry.Flags = ParcelManager.AccessList.Ban;
5761 entry.Time = DateTime.Now.AddHours(hours);
5762 land.parcelAccessList.Add(entry);
5763 }
5764 }
5765 }
5766
5767 public void llRemoveFromLandPassList(string avatar)
5768 {
5769 m_host.AddScriptLPS(1);
5770 LLUUID key;
5771 LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData;
5772 if (land.ownerID == m_host.OwnerID)
5773 {
5774 if (LLUUID.TryParse(avatar, out key))
5775 {
5776 foreach (ParcelManager.ParcelAccessEntry entry in land.parcelAccessList)
5777 {
5778 if (entry.AgentID == key && entry.Flags == ParcelManager.AccessList.Access)
5779 {
5780 land.parcelAccessList.Remove(entry);
5781 break;
5782 }
5783 }
5784 }
5785 }
5786 }
5787
5788 public void llRemoveFromLandBanList(string avatar)
5789 {
5790 m_host.AddScriptLPS(1);
5791 LLUUID key;
5792 LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData;
5793 if (land.ownerID == m_host.OwnerID)
5794 {
5795 if (LLUUID.TryParse(avatar, out key))
5796 {
5797 foreach (ParcelManager.ParcelAccessEntry entry in land.parcelAccessList)
5798 {
5799 if (entry.AgentID == key && entry.Flags == ParcelManager.AccessList.Ban)
5800 {
5801 land.parcelAccessList.Remove(entry);
5802 break;
5803 }
5804 }
5805 }
5806 }
5807 }
5808
5809 public void llSetCameraParams(LSL_Types.list rules)
5810 {
5811 m_host.AddScriptLPS(1);
5812 NotImplemented("llSetCameraParams");
5813 }
5814
5815 public void llClearCameraParams()
5816 {
5817 m_host.AddScriptLPS(1);
5818 NotImplemented("llClearCameraParams");
5819 }
5820
5821 public double llListStatistics(int operation, LSL_Types.list src)
5822 {
5823 m_host.AddScriptLPS(1);
5824 LSL_Types.list nums = LSL_Types.list.ToDoubleList(src);
5825 switch (operation)
5826 {
5827 case BuiltIn_Commands_BaseClass.LIST_STAT_RANGE:
5828 return nums.Range();
5829 case BuiltIn_Commands_BaseClass.LIST_STAT_MIN:
5830 return nums.Min();
5831 case BuiltIn_Commands_BaseClass.LIST_STAT_MAX:
5832 return nums.Max();
5833 case BuiltIn_Commands_BaseClass.LIST_STAT_MEAN:
5834 return nums.Mean();
5835 case BuiltIn_Commands_BaseClass.LIST_STAT_MEDIAN:
5836 return nums.Median();
5837 case BuiltIn_Commands_BaseClass.LIST_STAT_NUM_COUNT:
5838 return nums.NumericLength();
5839 case BuiltIn_Commands_BaseClass.LIST_STAT_STD_DEV:
5840 return nums.StdDev();
5841 case BuiltIn_Commands_BaseClass.LIST_STAT_SUM:
5842 return nums.Sum();
5843 case BuiltIn_Commands_BaseClass.LIST_STAT_SUM_SQUARES:
5844 return nums.SumSqrs();
5845 case BuiltIn_Commands_BaseClass.LIST_STAT_GEOMETRIC_MEAN:
5846 return nums.GeometricMean();
5847 case BuiltIn_Commands_BaseClass.LIST_STAT_HARMONIC_MEAN:
5848 return nums.HarmonicMean();
5849 default:
5850 return 0.0;
5851 }
5852 }
5853
5854 public LSL_Types.LSLInteger llGetUnixTime()
5855 {
5856 m_host.AddScriptLPS(1);
5857 return Util.UnixTimeSinceEpoch();
5858 }
5859
5860 public LSL_Types.LSLInteger llGetParcelFlags(LSL_Types.Vector3 pos)
5861 {
5862 m_host.AddScriptLPS(1);
5863 return (int)World.LandChannel.GetLandObject((float)pos.x, (float)pos.y).landData.landFlags;
5864 }
5865
5866 public LSL_Types.LSLInteger llGetRegionFlags()
5867 {
5868 m_host.AddScriptLPS(1);
5869 return (int)World.RegionInfo.EstateSettings.regionFlags;
5870 }
5871
5872 public string llXorBase64StringsCorrect(string str1, string str2)
5873 {
5874 m_host.AddScriptLPS(1);
5875 string ret = String.Empty;
5876 string src1 = llBase64ToString(str1);
5877 string src2 = llBase64ToString(str2);
5878 int c = 0;
5879 for (int i = 0; i < src1.Length; i++)
5880 {
5881 ret += src1[i] ^ src2[c];
5882
5883 c++;
5884 if (c > src2.Length)
5885 c = 0;
5886 }
5887 return llStringToBase64(ret);
5888 }
5889
5890 public string llHTTPRequest(string url, LSL_Types.list parameters, string body)
5891 {
5892 // Partial implementation: support for parameter flags needed
5893 // see http://wiki.secondlife.com/wiki/LlHTTPRequest
5894 // parameter flags support are implemented in ScriptsHttpRequests.cs
5895 // in StartHttpRequest
5896
5897 m_host.AddScriptLPS(1);
5898 IHttpRequests httpScriptMod =
5899 m_ScriptEngine.World.RequestModuleInterface<IHttpRequests>();
5900 List<string> param = new List<string>();
5901 foreach (object o in parameters.Data)
5902 {
5903 param.Add(o.ToString());
5904 }
5905 LLUUID reqID = httpScriptMod.
5906 StartHttpRequest(m_localID, m_itemID, url, param, body);
5907
5908 if (reqID != LLUUID.Zero)
5909 return reqID.ToString();
5910 else
5911 return null;
5912 }
5913
5914 public void llResetLandBanList()
5915 {
5916 m_host.AddScriptLPS(1);
5917 LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData;
5918 if (land.ownerID == m_host.OwnerID)
5919 {
5920 foreach (ParcelManager.ParcelAccessEntry entry in land.parcelAccessList)
5921 {
5922 if (entry.Flags == ParcelManager.AccessList.Ban)
5923 {
5924 land.parcelAccessList.Remove(entry);
5925 }
5926 }
5927 }
5928 }
5929
5930 public void llResetLandPassList()
5931 {
5932 m_host.AddScriptLPS(1);
5933 LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData;
5934 if (land.ownerID == m_host.OwnerID)
5935 {
5936 foreach (ParcelManager.ParcelAccessEntry entry in land.parcelAccessList)
5937 {
5938 if (entry.Flags == ParcelManager.AccessList.Access)
5939 {
5940 land.parcelAccessList.Remove(entry);
5941 }
5942 }
5943 }
5944 }
5945
5946 public LSL_Types.LSLInteger llGetParcelPrimCount(LSL_Types.Vector3 pos, int category, int sim_wide)
5947 {
5948 m_host.AddScriptLPS(1);
5949
5950 LandData land = World.GetLandData((float)pos.x, (float)pos.y);
5951
5952 if (land == null)
5953 {
5954 return 0;
5955 }
5956
5957 else
5958 {
5959 if (sim_wide == 1)
5960 {
5961 if (category == 0)
5962 {
5963 return land.simwidePrims;
5964 }
5965
5966 else
5967 {
5968 //public int simwideArea = 0;
5969 return 0;
5970 }
5971 }
5972
5973 else
5974 {
5975 if (category == 0)//Total Prims
5976 {
5977 return 0;//land.
5978 }
5979
5980 else if (category == 1)//Owner Prims
5981 {
5982 return land.ownerPrims;
5983 }
5984
5985 else if (category == 2)//Group Prims
5986 {
5987 return land.groupPrims;
5988 }
5989
5990 else if (category == 3)//Other Prims
5991 {
5992 return land.otherPrims;
5993 }
5994
5995 else if (category == 4)//Selected
5996 {
5997 return land.selectedPrims;
5998 }
5999
6000 else if (category == 5)//Temp
6001 {
6002 return 0;//land.
6003 }
6004 }
6005 }
6006 return 0;
6007 }
6008
6009 public LSL_Types.list llGetParcelPrimOwners(LSL_Types.Vector3 pos)
6010 {
6011 m_host.AddScriptLPS(1);
6012 LandObject land = (LandObject)World.LandChannel.GetLandObject((float)pos.x, (float)pos.y);
6013 LSL_Types.list ret = new LSL_Types.list();
6014 if (land != null)
6015 {
6016 foreach (KeyValuePair<LLUUID, int> d in land.getLandObjectOwners())
6017 {
6018 ret.Add(d.Key.ToString());
6019 ret.Add(d.Value);
6020 }
6021 }
6022 return ret;
6023 }
6024
6025 public LSL_Types.LSLInteger llGetObjectPrimCount(string object_id)
6026 {
6027 m_host.AddScriptLPS(1);
6028 SceneObjectPart part = World.GetSceneObjectPart(new LLUUID(object_id));
6029 if (part == null)
6030 {
6031 return 0;
6032 }
6033 else
6034 {
6035 return part.ParentGroup.Children.Count;
6036 }
6037 }
6038
6039 public LSL_Types.LSLInteger llGetParcelMaxPrims(LSL_Types.Vector3 pos, int sim_wide)
6040 {
6041 m_host.AddScriptLPS(1);
6042 // Alondria: This currently just is utilizing the normal grid's 0.22 prims/m2 calculation
6043 // Which probably will be irrelevent in OpenSim....
6044 LandData land = World.GetLandData((float)pos.x, (float)pos.y);
6045
6046 float bonusfactor = World.RegionInfo.EstateSettings.objectBonusFactor;
6047
6048 if (land == null)
6049 {
6050 return 0;
6051 }
6052
6053 if (sim_wide == 1)
6054 {
6055 decimal v = land.simwideArea * (decimal)(0.22) * (decimal)bonusfactor;
6056
6057 return (int)v;
6058 }
6059
6060 else
6061 {
6062 decimal v = land.area * (decimal)(0.22) * (decimal)bonusfactor;
6063
6064 return (int)v;
6065 }
6066
6067 }
6068
6069 public LSL_Types.list llGetParcelDetails(LSL_Types.Vector3 pos, LSL_Types.list param)
6070 {
6071 m_host.AddScriptLPS(1);
6072 LandData land = World.GetLandData((float)pos.x, (float)pos.y);
6073 if (land == null)
6074 {
6075 return new LSL_Types.list(0);
6076 }
6077 LSL_Types.list ret = new LSL_Types.list();
6078 foreach (object o in param.Data)
6079 {
6080 switch (o.ToString())
6081 {
6082 case "0":
6083 ret = ret + new LSL_Types.list(land.landName);
6084 break;
6085 case "1":
6086 ret = ret + new LSL_Types.list(land.landDesc);
6087 break;
6088 case "2":
6089 ret = ret + new LSL_Types.list(land.ownerID.ToString());
6090 break;
6091 case "3":
6092 ret = ret + new LSL_Types.list(land.groupID.ToString());
6093 break;
6094 case "4":
6095 ret = ret + new LSL_Types.list(land.area);
6096 break;
6097 default:
6098 ret = ret + new LSL_Types.list(0);
6099 break;
6100 }
6101 }
6102 return ret;
6103 }
6104
6105 public void llSetLinkTexture(int linknumber, string texture, int face)
6106 {
6107 m_host.AddScriptLPS(1);
6108 NotImplemented("llSetLinkTexture");
6109 }
6110
6111 public string llStringTrim(string src, int type)
6112 {
6113 m_host.AddScriptLPS(1);
6114 if (type == (int)BuiltIn_Commands_BaseClass.STRING_TRIM_HEAD) { return src.TrimStart(); }
6115 if (type == (int)BuiltIn_Commands_BaseClass.STRING_TRIM_TAIL) { return src.TrimEnd(); }
6116 if (type == (int)BuiltIn_Commands_BaseClass.STRING_TRIM) { return src.Trim(); }
6117 return src;
6118 }
6119
6120 public LSL_Types.list llGetObjectDetails(string id, LSL_Types.list args)
6121 {
6122 m_host.AddScriptLPS(1);
6123 LSL_Types.list ret = new LSL_Types.list();
6124 LLUUID key = new LLUUID();
6125 if (LLUUID.TryParse(id, out key))
6126 {
6127 ScenePresence av = World.GetScenePresence(key);
6128
6129 if (av != null)
6130 {
6131 foreach (object o in args.Data)
6132 {
6133 switch (o.ToString())
6134 {
6135 case "1":
6136 ret.Add(av.Firstname + " " + av.Lastname);
6137 break;
6138 case "2":
6139 ret.Add("");
6140 break;
6141 case "3":
6142 ret.Add(new LSL_Types.Vector3((double)av.AbsolutePosition.X, (double)av.AbsolutePosition.Y, (double)av.AbsolutePosition.Z));
6143 break;
6144 case "4":
6145 ret.Add(new LSL_Types.Quaternion((double)av.Rotation.x, (double)av.Rotation.y, (double)av.Rotation.z, (double)av.Rotation.w));
6146 break;
6147 case "5":
6148 ret.Add(new LSL_Types.Vector3(av.Velocity.X,av.Velocity.Y,av.Velocity.Z));
6149 break;
6150 case "6":
6151 ret.Add(id);
6152 break;
6153 case "7":
6154 ret.Add(LLUUID.Zero.ToString());
6155 break;
6156 case "8":
6157 ret.Add(LLUUID.Zero.ToString());
6158 break;
6159 }
6160 }
6161 return ret;
6162 }
6163 SceneObjectPart obj = World.GetSceneObjectPart(key);
6164 if (obj != null)
6165 {
6166 foreach (object o in args.Data)
6167 {
6168 switch (o.ToString())
6169 {
6170 case "1":
6171 ret.Add(obj.Name);
6172 break;
6173 case "2":
6174 ret.Add(obj.Description);
6175 break;
6176 case "3":
6177 ret.Add(new LSL_Types.Vector3(obj.AbsolutePosition.X,obj.AbsolutePosition.Y,obj.AbsolutePosition.Z));
6178 break;
6179 case "4":
6180 ret.Add(new LSL_Types.Quaternion(obj.RotationOffset.X, obj.RotationOffset.Y, obj.RotationOffset.Z, obj.RotationOffset.W));
6181 break;
6182 case "5":
6183 ret.Add(new LSL_Types.Vector3(obj.Velocity.X, obj.Velocity.Y, obj.Velocity.Z));
6184 break;
6185 case "6":
6186 ret.Add(obj.OwnerID.ToString());
6187 break;
6188 case "7":
6189 ret.Add(obj.GroupID.ToString());
6190 break;
6191 case "8":
6192 ret.Add(obj.CreatorID.ToString());
6193 break;
6194 }
6195 }
6196 return ret;
6197 }
6198 }
6199 return new LSL_Types.list();
6200 }
6201
6202
6203 internal LLUUID ScriptByName(string name)
6204 {
6205 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
6206 {
6207 if (item.Type == 10 && item.Name == name)
6208 return item.ItemID;
6209 }
6210 return LLUUID.Zero;
6211 }
6212
6213 internal void ShoutError(string msg)
6214 {
6215 llShout(BuiltIn_Commands_BaseClass.DEBUG_CHANNEL, msg);
6216 }
6217
6218
6219
6220 internal void NotImplemented(string command)
6221 {
6222 if (throwErrorOnNotImplemented)
6223 throw new NotImplementedException("Command not implemented: " + command);
6224 }
6225
6226 internal void Deprecated(string command)
6227 {
6228 throw new Exception("Command deprecated: " + command);
6229 }
6230
6231 internal void LSLError(string msg)
6232 {
6233 throw new Exception("LSL Runtime Error: " + msg);
6234 }
6235
6236 public delegate void AssetRequestCallback(LLUUID assetID, AssetBase asset);
6237 private void WithNotecard(LLUUID assetID, AssetRequestCallback cb)
6238 {
6239 World.AssetCache.GetAsset(assetID, delegate(LLUUID i, AssetBase a) { cb(i, a); }, false);
6240 }
6241
6242 public string llGetNumberOfNotecardLines(string name)
6243 {
6244 m_host.AddScriptLPS(1);
6245
6246 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
6247 {
6248 if (item.Type == 7 && item.Name == name)
6249 {
6250 LLUUID tid = m_ScriptEngine.m_ASYNCLSLCommandManager.
6251 m_Dataserver.RegisterRequest(m_localID,
6252 m_itemID, item.AssetID.ToString());
6253 if(NotecardCache.IsCached(item.AssetID))
6254 {
6255 m_ScriptEngine.m_ASYNCLSLCommandManager.
6256 m_Dataserver.DataserverReply(item.AssetID.ToString(),
6257 NotecardCache.GetLines(item.AssetID).ToString());
6258 return tid.ToString();
6259 }
6260 WithNotecard(item.AssetID, delegate (LLUUID id, AssetBase a)
6261 {
6262 System.Text.ASCIIEncoding enc =
6263 new System.Text.ASCIIEncoding();
6264 string data = enc.GetString(a.Data);
6265 Console.WriteLine(data);
6266 NotecardCache.Cache(id, data);
6267 m_ScriptEngine.m_ASYNCLSLCommandManager.
6268 m_Dataserver.DataserverReply(id.ToString(),
6269 NotecardCache.GetLines(id).ToString());
6270 });
6271
6272 return tid.ToString();
6273 }
6274 }
6275 return LLUUID.Zero.ToString();
6276 }
6277
6278 public string llGetNotecardLine(string name, int line)
6279 {
6280 m_host.AddScriptLPS(1);
6281
6282 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
6283 {
6284 if (item.Type == 7 && item.Name == name)
6285 {
6286 LLUUID tid = m_ScriptEngine.m_ASYNCLSLCommandManager.
6287 m_Dataserver.RegisterRequest(m_localID,
6288 m_itemID, item.AssetID.ToString());
6289 if(NotecardCache.IsCached(item.AssetID))
6290 {
6291 m_ScriptEngine.m_ASYNCLSLCommandManager.
6292 m_Dataserver.DataserverReply(item.AssetID.ToString(),
6293 NotecardCache.GetLine(item.AssetID, line));
6294 return tid.ToString();
6295 }
6296 WithNotecard(item.AssetID, delegate (LLUUID id, AssetBase a)
6297 {
6298 System.Text.ASCIIEncoding enc =
6299 new System.Text.ASCIIEncoding();
6300 string data = enc.GetString(a.Data);
6301 Console.WriteLine(data);
6302 NotecardCache.Cache(id, data);
6303 m_ScriptEngine.m_ASYNCLSLCommandManager.
6304 m_Dataserver.DataserverReply(id.ToString(),
6305 NotecardCache.GetLine(id, line));
6306 });
6307
6308 return tid.ToString();
6309 }
6310 }
6311
6312 return String.Empty;
6313 }
6314
6315 }
6316
6317 public class NotecardCache
6318 {
6319 private class Notecard
6320 {
6321 public string[] text;
6322 public DateTime lastRef;
6323 }
6324
6325 private static Dictionary<LLUUID, Notecard> m_Notecards =
6326 new Dictionary<LLUUID, Notecard>();
6327
6328 public static void Cache(LLUUID assetID, string text)
6329 {
6330 CacheCheck();
6331
6332 lock(m_Notecards)
6333 {
6334 if(m_Notecards.ContainsKey(assetID))
6335 return;
6336
6337 Notecard nc = new Notecard();
6338 nc.lastRef=DateTime.Now;
6339 nc.text = ParseText(text.Replace("\r", "").Split('\n'));
6340 m_Notecards[assetID] = nc;
6341 }
6342 }
6343
6344 private static string[] ParseText(string[] input)
6345 {
6346 int idx=0;
6347 int level=0;
6348 List<string> output = new List<string>();
6349 string[] words;
6350
6351 while(idx < input.Length)
6352 {
6353 if(input[idx] == "{")
6354 {
6355 level++;
6356 idx++;
6357 continue;
6358 }
6359 if(input[idx]== "}")
6360 {
6361 level--;
6362 idx++;
6363 continue;
6364 }
6365
6366 switch(level)
6367 {
6368 case 0:
6369 words = input[idx].Split(' '); // Linden text ver
6370 int version = int.Parse(words[3]);
6371 if(version != 2)
6372 return new String[0];
6373 break;
6374 case 1:
6375 words = input[idx].Split(' ');
6376 if(words[0] == "LLEmbeddedItems")
6377 break;
6378 if(words[0] == "Text")
6379 {
6380 int len = int.Parse(words[2]);
6381 idx++;
6382
6383 int count=-1;
6384
6385 while(count < len)
6386 {
6387 int l = input[idx].Length;
6388 string ln = input[idx];
6389
6390 int need = len-count-1;
6391 if(ln.Length > need)
6392 ln=ln.Substring(0, need);
6393
6394 output.Add(ln);
6395 count+=ln.Length+1;
6396 idx++;
6397 }
6398
6399 return output.ToArray();
6400 }
6401 break;
6402 case 2:
6403 words = input[idx].Split(' '); // count
6404 if(words[0] == "count")
6405 {
6406 int c = int.Parse(words[1]);
6407 if(c > 0)
6408 return new String[0];
6409 break;
6410 }
6411 break;
6412 }
6413 idx++;
6414 }
6415 return output.ToArray();
6416 }
6417
6418 public static bool IsCached(LLUUID assetID)
6419 {
6420 lock(m_Notecards)
6421 {
6422 return m_Notecards.ContainsKey(assetID);
6423 }
6424 }
6425
6426 public static int GetLines(LLUUID assetID)
6427 {
6428 if(!IsCached(assetID))
6429 return -1;
6430
6431 lock(m_Notecards)
6432 {
6433 m_Notecards[assetID].lastRef = DateTime.Now;
6434 return m_Notecards[assetID].text.Length;
6435 }
6436 }
6437
6438 public static string GetLine(LLUUID assetID, int line)
6439 {
6440 if(line < 0)
6441 return "";
6442
6443 string data;
6444
6445 if(!IsCached(assetID))
6446 return "";
6447
6448 lock(m_Notecards)
6449 {
6450 m_Notecards[assetID].lastRef = DateTime.Now;
6451
6452 if(line >= m_Notecards[assetID].text.Length)
6453 return "\n\n\n";
6454
6455 data=m_Notecards[assetID].text[line];
6456 if(data.Length > 255)
6457 data = data.Substring(0, 255);
6458
6459 return data;
6460 }
6461 }
6462
6463 public static void CacheCheck()
6464 {
6465 foreach (LLUUID key in new List<LLUUID>(m_Notecards.Keys))
6466 {
6467 Notecard nc = m_Notecards[key];
6468 if(nc.lastRef.AddSeconds(30) < DateTime.Now)
6469 m_Notecards.Remove(key);
6470 }
6471 }
6472
6473 }
6474}
diff --git a/OpenSim/Region/ScriptEngine/XEngine/OSSL_ScriptCommands.cs b/OpenSim/Region/ScriptEngine/XEngine/OSSL_ScriptCommands.cs
new file mode 100644
index 0000000..bc4e8ba
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/XEngine/OSSL_ScriptCommands.cs
@@ -0,0 +1,553 @@
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 */
27using System;
28using Axiom.Math;
29using libsecondlife;
30using Nini.Config;
31using OpenSim.Framework.Console;
32using OpenSim.Region.Environment.Interfaces;
33using OpenSim.Region.Environment.Scenes;
34using OpenSim.Region.ScriptEngine.XEngine.Script;
35
36namespace OpenSim.Region.ScriptEngine.XEngine
37{
38 [Serializable]
39 public class OSSL_ScriptCommands : MarshalByRefObject, IOSSL_ScriptCommands
40 {
41 internal XEngine m_ScriptEngine;
42 internal XScriptInstance m_Instance;
43 internal SceneObjectPart m_host;
44 internal uint m_localID;
45 internal LLUUID m_itemID;
46
47 public OSSL_ScriptCommands(XEngine scriptEngine,
48 XScriptInstance instance, SceneObjectPart host,
49 uint localID, LLUUID itemID)
50 {
51 m_ScriptEngine = scriptEngine;
52 m_Instance = instance;
53 m_host = host;
54 m_localID = localID;
55 m_itemID = itemID;
56 }
57
58
59 //
60 // OpenSim functions
61 //
62
63 public int osTerrainSetHeight(int x, int y, double val)
64 {
65 if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
66 {
67 OSSLError("osTerrainSetHeight: permission denied");
68 return 0;
69 }
70
71 m_host.AddScriptLPS(1);
72 if (x > 255 || x < 0 || y > 255 || y < 0)
73 OSSLError("osTerrainSetHeight: Coordinate out of bounds");
74
75 if (World.ExternalChecks.ExternalChecksCanTerraformLand(m_host.OwnerID, new LLVector3(x, y, 0)))
76 {
77 World.Heightmap[x, y] = val;
78 return 1;
79 }
80 else
81 {
82 return 0;
83 }
84 }
85
86 public double osTerrainGetHeight(int x, int y)
87 {
88 if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
89 {
90 OSSLError("osTerrainGetHeight: permission denied");
91 return 0.0;
92 }
93
94 m_host.AddScriptLPS(1);
95 if (x > 255 || x < 0 || y > 255 || y < 0)
96 OSSLError("osTerrainGetHeight: Coordinate out of bounds");
97
98 return World.Heightmap[x, y];
99 }
100
101 public int osRegionRestart(double seconds)
102 {
103 if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
104 {
105 OSSLError("osRegionRestart: permission denied");
106 return 0;
107 }
108
109 m_host.AddScriptLPS(1);
110 if (World.ExternalChecks.ExternalChecksCanIssueEstateCommand(m_host.OwnerID))
111 {
112 World.Restart((float)seconds);
113 return 1;
114 }
115 else
116 {
117 return 0;
118 }
119 }
120
121 public void osRegionNotice(string msg)
122 {
123 if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
124 {
125 OSSLError("osRegionNotice: permission denied");
126 return;
127 }
128
129 m_host.AddScriptLPS(1);
130 World.SendGeneralAlert(msg);
131 }
132
133 public void osSetRot(LLUUID target, Quaternion rotation)
134 {
135 if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
136 {
137 OSSLError("osSetRot: permission denied");
138 return;
139 }
140
141 m_host.AddScriptLPS(1);
142 if (World.Entities.ContainsKey(target))
143 {
144 World.Entities[target].Rotation = rotation;
145 }
146 else
147 {
148 OSSLError("osSetRot: Invalid target");
149 }
150 }
151
152 public string osSetDynamicTextureURL(string dynamicID, string contentType, string url, string extraParams,
153 int timer)
154 {
155 if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
156 {
157 OSSLError("osSetDynamicTextureURL: permission denied");
158 return String.Empty;
159 }
160
161 m_host.AddScriptLPS(1);
162 if (dynamicID == String.Empty)
163 {
164 IDynamicTextureManager textureManager = World.RequestModuleInterface<IDynamicTextureManager>();
165 LLUUID createdTexture =
166 textureManager.AddDynamicTextureURL(World.RegionInfo.RegionID, m_host.UUID, contentType, url,
167 extraParams, timer);
168 return createdTexture.ToString();
169 }
170 else
171 {
172 //TODO update existing dynamic textures
173 }
174
175 return LLUUID.Zero.ToString();
176 }
177
178 public string osSetDynamicTextureURLBlend(string dynamicID, string contentType, string url, string extraParams,
179 int timer, int alpha)
180 {
181 if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
182 {
183 OSSLError("osSetDynamicTextureURLBlend: permission denied");
184 return String.Empty;
185 }
186
187 m_host.AddScriptLPS(1);
188 if (dynamicID == String.Empty)
189 {
190 IDynamicTextureManager textureManager = World.RequestModuleInterface<IDynamicTextureManager>();
191 LLUUID createdTexture =
192 textureManager.AddDynamicTextureURL(World.RegionInfo.RegionID, m_host.UUID, contentType, url,
193 extraParams, timer, true, (byte) alpha);
194 return createdTexture.ToString();
195 }
196 else
197 {
198 //TODO update existing dynamic textures
199 }
200
201 return LLUUID.Zero.ToString();
202 }
203
204 public string osSetDynamicTextureData(string dynamicID, string contentType, string data, string extraParams,
205 int timer)
206 {
207 if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
208 {
209 OSSLError("osSetDynamicTextureData: permission denied");
210 return String.Empty;
211 }
212
213 m_host.AddScriptLPS(1);
214 if (dynamicID == String.Empty)
215 {
216 IDynamicTextureManager textureManager = World.RequestModuleInterface<IDynamicTextureManager>();
217 if (textureManager != null)
218 {
219 LLUUID createdTexture =
220 textureManager.AddDynamicTextureData(World.RegionInfo.RegionID, m_host.UUID, contentType, data,
221 extraParams, timer);
222 return createdTexture.ToString();
223 }
224 }
225 else
226 {
227 //TODO update existing dynamic textures
228 }
229
230 return LLUUID.Zero.ToString();
231 }
232
233 public string osSetDynamicTextureDataBlend(string dynamicID, string contentType, string data, string extraParams,
234 int timer, int alpha)
235 {
236 if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
237 {
238 OSSLError("osSetDynamicTextureDataBlend: permission denied");
239 return String.Empty;
240 }
241
242 m_host.AddScriptLPS(1);
243 if (dynamicID == String.Empty)
244 {
245 IDynamicTextureManager textureManager = World.RequestModuleInterface<IDynamicTextureManager>();
246 if (textureManager != null)
247 {
248 LLUUID createdTexture =
249 textureManager.AddDynamicTextureData(World.RegionInfo.RegionID, m_host.UUID, contentType, data,
250 extraParams, timer, true, (byte) alpha);
251 return createdTexture.ToString();
252 }
253 }
254 else
255 {
256 //TODO update existing dynamic textures
257 }
258
259 return LLUUID.Zero.ToString();
260 }
261
262 public bool osConsoleCommand(string command)
263 {
264 m_host.AddScriptLPS(1);
265 if (m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowosConsoleCommand", false))
266 {
267 if (World.ExternalChecks.ExternalChecksCanRunConsoleCommand(m_host.OwnerID))
268 {
269 MainConsole.Instance.RunCommand(command);
270 return true;
271 }
272 return false;
273 }
274 return false;
275 }
276 public void osSetPrimFloatOnWater(int floatYN)
277 {
278 if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
279 {
280 OSSLError("osSetPrimFloatOnWater: permission denied");
281 return;
282 }
283
284 m_host.AddScriptLPS(1);
285 if (m_host.ParentGroup != null)
286 {
287 if (m_host.ParentGroup.RootPart != null)
288 {
289 m_host.ParentGroup.RootPart.SetFloatOnWater(floatYN);
290 }
291 }
292 }
293
294 // Adam's super super custom animation functions
295 public void osAvatarPlayAnimation(string avatar, string animation)
296 {
297 if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
298 {
299 OSSLError("osAvatarPlayAnimation: permission denied");
300 return;
301 }
302
303 m_host.AddScriptLPS(1);
304 if (World.Entities.ContainsKey(avatar) && World.Entities[avatar] is ScenePresence)
305 {
306 ScenePresence target = (ScenePresence)World.Entities[avatar];
307 target.AddAnimation(avatar);
308 }
309 }
310
311 public void osAvatarStopAnimation(string avatar, string animation)
312 {
313 if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
314 {
315 OSSLError("osAvatarStopAnimation: permission denied");
316 return;
317 }
318
319 m_host.AddScriptLPS(1);
320 if (World.Entities.ContainsKey(avatar) && World.Entities[avatar] is ScenePresence)
321 {
322 ScenePresence target = (ScenePresence)World.Entities[avatar];
323 target.RemoveAnimation(animation);
324 }
325 }
326
327 //Texture draw functions
328 public string osMovePen(string drawList, int x, int y)
329 {
330 if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
331 {
332 OSSLError("osMovePen: permission denied");
333 return String.Empty;
334 }
335
336 m_host.AddScriptLPS(1);
337 drawList += "MoveTo " + x + "," + y + ";";
338 return drawList;
339 }
340
341 public string osDrawLine(string drawList, int startX, int startY, int endX, int endY)
342 {
343 if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
344 {
345 OSSLError("osDrawLine: permission denied");
346 return String.Empty;
347 }
348
349 m_host.AddScriptLPS(1);
350 drawList += "MoveTo "+ startX+","+ startY +"; LineTo "+endX +","+endY +"; ";
351 return drawList;
352 }
353
354 public string osDrawLine(string drawList, int endX, int endY)
355 {
356 if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
357 {
358 OSSLError("osDrawLine: permission denied");
359 return String.Empty;
360 }
361
362 m_host.AddScriptLPS(1);
363 drawList += "LineTo " + endX + "," + endY + "; ";
364 return drawList;
365 }
366
367 public string osDrawText(string drawList, string text)
368 {
369 if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
370 {
371 OSSLError("osDrawText: permission denied");
372 return String.Empty;
373 }
374
375 m_host.AddScriptLPS(1);
376 drawList += "Text " + text + "; ";
377 return drawList;
378 }
379
380 public string osDrawEllipse(string drawList, int width, int height)
381 {
382 if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
383 {
384 OSSLError("osDrawEllipse: permission denied");
385 return String.Empty;
386 }
387
388 m_host.AddScriptLPS(1);
389 drawList += "Ellipse " + width + "," + height + "; ";
390 return drawList;
391 }
392
393 public string osDrawRectangle(string drawList, int width, int height)
394 {
395 if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
396 {
397 OSSLError("osDrawRectangle: permission denied");
398 return String.Empty;
399 }
400
401 m_host.AddScriptLPS(1);
402 drawList += "Rectangle " + width + "," + height + "; ";
403 return drawList;
404 }
405
406 public string osDrawFilledRectangle(string drawList, int width, int height)
407 {
408 if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
409 {
410 OSSLError("osDrawFilledRectangle: permission denied");
411 return String.Empty;
412 }
413
414 m_host.AddScriptLPS(1);
415 drawList += "FillRectangle " + width + "," + height + "; ";
416 return drawList;
417 }
418
419 public string osSetFontSize(string drawList, int fontSize)
420 {
421 if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
422 {
423 OSSLError("osSetFontSize: permission denied");
424 return String.Empty;
425 }
426
427 m_host.AddScriptLPS(1);
428 drawList += "FontSize "+ fontSize +"; ";
429 return drawList;
430 }
431
432 public string osSetPenSize(string drawList, int penSize)
433 {
434 if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
435 {
436 OSSLError("osSetPenSize: permission denied");
437 return String.Empty;
438 }
439
440 m_host.AddScriptLPS(1);
441 drawList += "PenSize " + penSize + "; ";
442 return drawList;
443 }
444
445 public string osSetPenColour(string drawList, string colour)
446 {
447 if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
448 {
449 OSSLError("osSetPenColour: permission denied");
450 return String.Empty;
451 }
452
453 m_host.AddScriptLPS(1);
454 drawList += "PenColour " + colour + "; ";
455 return drawList;
456 }
457
458 public string osDrawImage(string drawList, int width, int height, string imageUrl)
459 {
460 if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
461 {
462 OSSLError("osDrawImage: permission denied");
463 return String.Empty;
464 }
465
466 m_host.AddScriptLPS(1);
467 drawList +="Image " +width + "," + height+ ","+ imageUrl +"; " ;
468 return drawList;
469 }
470
471 public void osSetStateEvents(int events)
472 {
473 if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
474 {
475 OSSLError("osSetStateEvents: permission denied");
476 return;
477 }
478
479 m_host.SetScriptEvents(m_itemID, events);
480 }
481
482 public void osSetRegionWaterHeight(double height)
483 {
484 if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
485 {
486 OSSLError("osSetRegionWaterHeight: permission denied");
487 return;
488 }
489
490 m_host.AddScriptLPS(1);
491 //Check to make sure that the script's owner is the estate manager/master
492 //World.Permissions.GenericEstatePermission(
493 if (World.ExternalChecks.ExternalChecksCanBeGodLike(m_host.OwnerID))
494 {
495 World.EventManager.TriggerRequestChangeWaterHeight((float)height);
496 }
497 }
498
499 public double osList2Double(LSL_Types.list src, int index)
500 {
501 if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
502 {
503 OSSLError("osList2Double: permission denied");
504 return 0.0;
505 }
506
507 m_host.AddScriptLPS(1);
508 if (index < 0)
509 {
510 index = src.Length + index;
511 }
512 if (index >= src.Length)
513 {
514 return 0.0;
515 }
516 return Convert.ToDouble(src.Data[index]);
517 }
518
519 public void osSetParcelMediaURL(string url)
520 {
521 if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
522 {
523 OSSLError("osSetParcelMediaURL: permission denied");
524 return;
525 }
526
527 m_host.AddScriptLPS(1);
528 LLUUID landowner = World.GetLandOwner(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y);
529
530 if (landowner == LLUUID.Zero)
531 {
532 return;
533 }
534
535 if (landowner != m_host.ObjectOwner)
536 {
537 return;
538 }
539
540 World.SetLandMediaURL(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y, url);
541 }
542
543 public Scene World
544 {
545 get { return m_ScriptEngine.World; }
546 }
547
548 internal void OSSLError(string msg)
549 {
550 throw new Exception("OSSL Runtime Error: " + msg);
551 }
552 }
553}
diff --git a/OpenSim/Region/ScriptEngine/XEngine/Script/AssemblyResolver.cs b/OpenSim/Region/ScriptEngine/XEngine/Script/AssemblyResolver.cs
new file mode 100644
index 0000000..8107788
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/XEngine/Script/AssemblyResolver.cs
@@ -0,0 +1,65 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.IO;
30using System.Reflection;
31
32namespace OpenSim.Region.ScriptEngine.XEngine.Script
33{
34 [Serializable]
35 public class AssemblyResolver
36 {
37 public static Assembly OnAssemblyResolve(object sender,
38 ResolveEventArgs args)
39 {
40 if(!(sender is System.AppDomain))
41 return null;
42
43 AppDomain myDomain = (AppDomain)sender;
44 string dirName = myDomain.FriendlyName;
45
46 string[] pathList=new string[] {"bin", "ScriptEngines",
47 Path.Combine("ScriptEngines", dirName)};
48
49 string assemblyName = args.Name;
50 if(assemblyName.IndexOf(",") != -1)
51 assemblyName=args.Name.Substring(0, args.Name.IndexOf(","));
52
53 foreach (string s in pathList)
54 {
55 string path=Path.Combine(Directory.GetCurrentDirectory(),
56 Path.Combine(s, assemblyName))+".dll";
57
58 if(File.Exists(path))
59 return Assembly.LoadFrom(path);
60 }
61
62 return null;
63 }
64 }
65}
diff --git a/OpenSim/Region/ScriptEngine/XEngine/Script/BuiltIn_Commands_BaseClass.cs b/OpenSim/Region/ScriptEngine/XEngine/Script/BuiltIn_Commands_BaseClass.cs
new file mode 100644
index 0000000..bae8192
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/XEngine/Script/BuiltIn_Commands_BaseClass.cs
@@ -0,0 +1,2393 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Runtime.Remoting.Lifetime;
30using System.Threading;
31using System.Reflection;
32using System.Collections;
33using System.Collections.Generic;
34using OpenSim.Region.Environment.Interfaces;
35using integer = OpenSim.Region.ScriptEngine.XEngine.Script.LSL_Types.LSLInteger;
36using key = System.String;
37using vector = OpenSim.Region.ScriptEngine.XEngine.Script.LSL_Types.Vector3;
38using rotation = OpenSim.Region.ScriptEngine.XEngine.Script.LSL_Types.Quaternion;
39
40namespace OpenSim.Region.ScriptEngine.XEngine.Script
41{
42 public class BuiltIn_Commands_BaseClass : MarshalByRefObject, IOSSL_ScriptCommands, ILSL_ScriptCommands, IScript
43 {
44 //private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
45
46 // Object never expires
47 public override Object InitializeLifetimeService()
48 {
49 //Console.WriteLine("LSL_BaseClass: InitializeLifetimeService()");
50 // return null;
51 ILease lease = (ILease)base.InitializeLifetimeService();
52
53 if (lease.CurrentState == LeaseState.Initial)
54 {
55 lease.InitialLeaseTime = TimeSpan.Zero; // TimeSpan.FromMinutes(1);
56 //lease.SponsorshipTimeout = TimeSpan.FromMinutes(2);
57 //lease.RenewOnCallTime = TimeSpan.FromSeconds(2);
58 }
59 return lease;
60 }
61
62 public ILSL_ScriptCommands m_LSL_Functions;
63 public IOSSL_ScriptCommands m_OSSL_Functions;
64
65 public BuiltIn_Commands_BaseClass()
66 {
67 }
68
69 public Type Start(ILSL_ScriptCommands LSL_Functions, IOSSL_ScriptCommands OSSL_Functions)
70 {
71 m_LSL_Functions = LSL_Functions;
72 m_OSSL_Functions = OSSL_Functions;
73 m_InitialValues=GetVars();
74 return GetType();
75 }
76
77 private Dictionary<string, object> m_InitialValues =
78 new Dictionary<string, object>();
79 private Dictionary<string, FieldInfo> m_Fields =
80 new Dictionary<string, FieldInfo>();
81
82 public Dictionary<string, object> GetVars()
83 {
84 m_Fields.Clear();
85
86 Dictionary<string, object> vars = new Dictionary<string, object>();
87
88 Type t = GetType();
89
90 FieldInfo[] fields = t.GetFields(BindingFlags.NonPublic |
91 BindingFlags.Public |
92 BindingFlags.Instance |
93 BindingFlags.DeclaredOnly);
94
95 foreach (FieldInfo field in fields)
96 {
97 m_Fields[field.Name]=field;
98
99 vars[field.Name]=field.GetValue(this);
100 }
101
102 return vars;
103 }
104
105 public void SetVars(Dictionary<string, object> vars)
106 {
107 foreach (KeyValuePair<string, object> var in vars)
108 {
109 if(m_Fields.ContainsKey(var.Key))
110 {
111 m_Fields[var.Key].SetValue(this, var.Value);
112 }
113 }
114 }
115
116 public void ResetVars()
117 {
118 SetVars(m_InitialValues);
119 }
120
121 public string State
122 {
123 get { return m_LSL_Functions.State; }
124 set { m_LSL_Functions.State = value; }
125 }
126
127 public void state(string newState)
128 {
129 m_LSL_Functions.state(newState);
130 }
131
132 public void llSay(int channelID, string text)
133 {
134 m_LSL_Functions.llSay(channelID, text);
135 }
136
137 //
138 // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs
139 //
140 // They are only forwarders to LSL_BuiltIn_Commands.cs
141 //
142
143 public ICommander GetCommander(string name)
144 {
145 return m_LSL_Functions.GetCommander(name);
146 }
147
148 public double llSin(double f)
149 {
150 return m_LSL_Functions.llSin(f);
151 }
152 public double llCos(double f)
153 {
154 return m_LSL_Functions.llCos(f);
155 }
156
157 public double llTan(double f)
158 {
159 return m_LSL_Functions.llTan(f);
160 }
161
162 public double llAtan2(double x, double y)
163 {
164 return m_LSL_Functions.llAtan2(x, y);
165 }
166
167 public double llSqrt(double f)
168 {
169 return m_LSL_Functions.llSqrt(f);
170 }
171
172 public double llPow(double fbase, double fexponent)
173 {
174 return m_LSL_Functions.llPow(fbase, fexponent);
175 }
176
177 public LSL_Types.LSLInteger llAbs(int i)
178 {
179 return m_LSL_Functions.llAbs(i);
180 }
181
182 public double llFabs(double f)
183 {
184 return m_LSL_Functions.llFabs(f);
185 }
186
187 public double llFrand(double mag)
188 {
189 return m_LSL_Functions.llFrand(mag);
190 }
191
192 public LSL_Types.LSLInteger llFloor(double f)
193 {
194 return m_LSL_Functions.llFloor(f);
195 }
196
197 public LSL_Types.LSLInteger llCeil(double f)
198 {
199 return m_LSL_Functions.llCeil(f);
200 }
201
202 public LSL_Types.LSLInteger llRound(double f)
203 {
204 return m_LSL_Functions.llRound(f);
205 }
206
207 public double llVecMag(vector v)
208 {
209 return m_LSL_Functions.llVecMag(v);
210 }
211
212 public vector llVecNorm(vector v)
213 {
214 return m_LSL_Functions.llVecNorm(v);
215 }
216
217 public double llVecDist(vector a, vector b)
218 {
219 return m_LSL_Functions.llVecDist(a, b);
220 }
221
222 public vector llRot2Euler(rotation r)
223 {
224 return m_LSL_Functions.llRot2Euler(r);
225 }
226
227 public rotation llEuler2Rot(vector v)
228 {
229 return m_LSL_Functions.llEuler2Rot(v);
230 }
231
232 public rotation llAxes2Rot(vector fwd, vector left, vector up)
233 {
234 return m_LSL_Functions.llAxes2Rot(fwd, left, up);
235 }
236
237 public vector llRot2Fwd(rotation r)
238 {
239 return m_LSL_Functions.llRot2Fwd(r);
240 }
241
242 public vector llRot2Left(rotation r)
243 {
244 return m_LSL_Functions.llRot2Left(r);
245 }
246
247 public vector llRot2Up(rotation r)
248 {
249 return m_LSL_Functions.llRot2Up(r);
250 }
251
252 public rotation llRotBetween(vector start, vector end)
253 {
254 return m_LSL_Functions.llRotBetween(start, end);
255 }
256
257 public void llWhisper(int channelID, string text)
258 {
259 m_LSL_Functions.llWhisper(channelID, text);
260 }
261
262 //
263 // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs
264 //
265 public void llShout(int channelID, string text)
266 {
267 m_LSL_Functions.llShout(channelID, text);
268 }
269
270 public void llRegionSay(int channelID, string text)
271 {
272 m_LSL_Functions.llRegionSay(channelID, text);
273 }
274
275 public LSL_Types.LSLInteger llListen(int channelID, string name, string ID, string msg)
276 {
277 return m_LSL_Functions.llListen(channelID, name, ID, msg);
278 }
279
280 public void llListenControl(int number, int active)
281 {
282 m_LSL_Functions.llListenControl(number, active);
283 }
284
285 public void llListenRemove(int number)
286 {
287 m_LSL_Functions.llListenRemove(number);
288 }
289
290 public void llSensor(string name, string id, int type, double range, double arc)
291 {
292 m_LSL_Functions.llSensor(name, id, type, range, arc);
293 }
294
295 public void llSensorRepeat(string name, string id, int type, double range, double arc, double rate)
296 {
297 m_LSL_Functions.llSensorRepeat(name, id, type, range, arc, rate);
298 }
299
300 public void llSensorRemove()
301 {
302 m_LSL_Functions.llSensorRemove();
303 }
304
305 public string llDetectedName(int number)
306 {
307 return m_LSL_Functions.llDetectedName(number);
308 }
309
310 public string llDetectedKey(int number)
311 {
312 return m_LSL_Functions.llDetectedKey(number);
313 }
314
315 public string llDetectedOwner(int number)
316 {
317 return m_LSL_Functions.llDetectedOwner(number);
318 }
319
320 public LSL_Types.LSLInteger llDetectedType(int number)
321 {
322 return m_LSL_Functions.llDetectedType(number);
323 }
324
325 public vector llDetectedPos(int number)
326 {
327 return m_LSL_Functions.llDetectedPos(number);
328 }
329
330 public vector llDetectedVel(int number)
331 {
332 return m_LSL_Functions.llDetectedVel(number);
333 }
334
335 public vector llDetectedGrab(int number)
336 {
337 return m_LSL_Functions.llDetectedGrab(number);
338 }
339
340 public rotation llDetectedRot(int number)
341 {
342 return m_LSL_Functions.llDetectedRot(number);
343 }
344
345 public LSL_Types.LSLInteger llDetectedGroup(int number)
346 {
347 return m_LSL_Functions.llDetectedGroup(number);
348 }
349
350 public LSL_Types.LSLInteger llDetectedLinkNumber(int number)
351 {
352 return m_LSL_Functions.llDetectedLinkNumber(number);
353 }
354
355 //
356 // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs
357 //
358 public void llDie()
359 {
360 m_LSL_Functions.llDie();
361 }
362
363 public double llGround(vector offset)
364 {
365 return m_LSL_Functions.llGround(offset);
366 }
367
368 public double llCloud(vector offset)
369 {
370 return m_LSL_Functions.llCloud(offset);
371 }
372
373 public vector llWind(vector offset)
374 {
375 return m_LSL_Functions.llWind(offset);
376 }
377
378 public void llSetStatus(int status, int value)
379 {
380 m_LSL_Functions.llSetStatus(status, value);
381 }
382
383 public LSL_Types.LSLInteger llGetStatus(int status)
384 {
385 return m_LSL_Functions.llGetStatus(status);
386 }
387
388 public void llSetScale(vector scale)
389 {
390 m_LSL_Functions.llSetScale(scale);
391 }
392
393 public vector llGetScale()
394 {
395 return m_LSL_Functions.llGetScale();
396 }
397
398 public void llSetColor(vector color, int face)
399 {
400 m_LSL_Functions.llSetColor(color, face);
401 }
402
403 public double llGetAlpha(int face)
404 {
405 return m_LSL_Functions.llGetAlpha(face);
406 }
407
408 public void llSetAlpha(double alpha, int face)
409 {
410 m_LSL_Functions.llSetAlpha(alpha, face);
411 }
412
413 public vector llGetColor(int face)
414 {
415 return m_LSL_Functions.llGetColor(face);
416 }
417
418 public void llSetTexture(string texture, int face)
419 {
420 m_LSL_Functions.llSetTexture(texture, face);
421 }
422
423 public void llScaleTexture(double u, double v, int face)
424 {
425 m_LSL_Functions.llScaleTexture(u, v, face);
426 }
427
428 public void llOffsetTexture(double u, double v, int face)
429 {
430 m_LSL_Functions.llOffsetTexture(u, v, face);
431 }
432
433 public void llRotateTexture(double rotation, int face)
434 {
435 m_LSL_Functions.llRotateTexture(rotation, face);
436 }
437
438 public string llGetTexture(int face)
439 {
440 return m_LSL_Functions.llGetTexture(face);
441 }
442
443 //
444 // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs
445 //
446 public void llSetPos(vector pos)
447 {
448 m_LSL_Functions.llSetPos(pos);
449 }
450
451 public vector llGetPos()
452 {
453 return m_LSL_Functions.llGetPos();
454 }
455
456 public vector llGetLocalPos()
457 {
458 return m_LSL_Functions.llGetLocalPos();
459 }
460
461 public void llSetRot(rotation rot)
462 {
463 m_LSL_Functions.llSetRot(rot);
464 }
465
466 public rotation llGetRot()
467 {
468 return m_LSL_Functions.llGetRot();
469 }
470
471 public rotation llGetLocalRot()
472 {
473 return m_LSL_Functions.llGetLocalRot();
474 }
475
476 public void llSetForce(vector force, int local)
477 {
478 m_LSL_Functions.llSetForce(force, local);
479 }
480
481 public vector llGetForce()
482 {
483 return m_LSL_Functions.llGetForce();
484 }
485
486 public LSL_Types.LSLInteger llTarget(vector position, double range)
487 {
488 return m_LSL_Functions.llTarget(position, range);
489 }
490
491 public void llTargetRemove(int number)
492 {
493 m_LSL_Functions.llTargetRemove(number);
494 }
495
496 public LSL_Types.LSLInteger llRotTarget(rotation rot, double error)
497 {
498 return m_LSL_Functions.llRotTarget(rot, error);
499 }
500
501 public void llRotTargetRemove(int number)
502 {
503 m_LSL_Functions.llRotTargetRemove(number);
504 }
505
506 public void llMoveToTarget(vector target, double tau)
507 {
508 m_LSL_Functions.llMoveToTarget(target, tau);
509 }
510
511 public void llStopMoveToTarget()
512 {
513 m_LSL_Functions.llStopMoveToTarget();
514 }
515
516 public void llApplyImpulse(vector force, int local)
517 {
518 m_LSL_Functions.llApplyImpulse(force, local);
519 }
520
521 //
522 // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs
523 //
524 public void llApplyRotationalImpulse(vector force, int local)
525 {
526 m_LSL_Functions.llApplyRotationalImpulse(force, local);
527 }
528
529 public void llSetTorque(vector torque, int local)
530 {
531 m_LSL_Functions.llSetTorque(torque, local);
532 }
533
534 public vector llGetTorque()
535 {
536 return m_LSL_Functions.llGetTorque();
537 }
538
539 public void llSetForceAndTorque(vector force, vector torque, int local)
540 {
541 m_LSL_Functions.llSetForceAndTorque(force, torque, local);
542 }
543
544 public vector llGetVel()
545 {
546 return m_LSL_Functions.llGetVel();
547 }
548
549 public vector llGetAccel()
550 {
551 return m_LSL_Functions.llGetAccel();
552 }
553
554 public vector llGetOmega()
555 {
556 return m_LSL_Functions.llGetOmega();
557 }
558
559 public double llGetTimeOfDay()
560 {
561 return m_LSL_Functions.llGetTimeOfDay();
562 }
563
564 public double llGetWallclock()
565 {
566 return m_LSL_Functions.llGetWallclock();
567 }
568
569 public double llGetTime()
570 {
571 return m_LSL_Functions.llGetTime();
572 }
573
574 public void llResetTime()
575 {
576 m_LSL_Functions.llResetTime();
577 }
578
579 public double llGetAndResetTime()
580 {
581 return m_LSL_Functions.llGetAndResetTime();
582 }
583
584 public void llSound()
585 {
586 m_LSL_Functions.llSound();
587 }
588
589 public void llPlaySound(string sound, double volume)
590 {
591 m_LSL_Functions.llPlaySound(sound, volume);
592 }
593
594 public void llLoopSound(string sound, double volume)
595 {
596 m_LSL_Functions.llLoopSound(sound, volume);
597 }
598
599 public void llLoopSoundMaster(string sound, double volume)
600 {
601 m_LSL_Functions.llLoopSoundMaster(sound, volume);
602 }
603
604 public void llLoopSoundSlave(string sound, double volume)
605 {
606 m_LSL_Functions.llLoopSoundSlave(sound, volume);
607 }
608
609 public void llPlaySoundSlave(string sound, double volume)
610 {
611 m_LSL_Functions.llPlaySoundSlave(sound, volume);
612 }
613
614 //
615 // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs
616 //
617 public void llTriggerSound(string sound, double volume)
618 {
619 m_LSL_Functions.llTriggerSound(sound, volume);
620 }
621
622 public void llStopSound()
623 {
624 m_LSL_Functions.llStopSound();
625 }
626
627 public void llPreloadSound(string sound)
628 {
629 m_LSL_Functions.llPreloadSound(sound);
630 }
631
632 public string llGetSubString(string src, int start, int end)
633 {
634 return m_LSL_Functions.llGetSubString(src, start, end);
635 }
636
637 public string llDeleteSubString(string src, int start, int end)
638 {
639 return m_LSL_Functions.llDeleteSubString(src, start, end);
640 }
641
642 public string llInsertString(string dst, int position, string src)
643 {
644 return m_LSL_Functions.llInsertString(dst, position, src);
645 }
646
647 public string llToUpper(string source)
648 {
649 return m_LSL_Functions.llToUpper(source);
650 }
651
652 public string llToLower(string source)
653 {
654 return m_LSL_Functions.llToLower(source);
655 }
656
657 public LSL_Types.LSLInteger llGiveMoney(string destination, int amount)
658 {
659 return m_LSL_Functions.llGiveMoney(destination, amount);
660 }
661
662 public void llMakeExplosion()
663 {
664 m_LSL_Functions.llMakeExplosion();
665 }
666
667 public void llMakeFountain()
668 {
669 m_LSL_Functions.llMakeFountain();
670 }
671
672 public void llMakeSmoke()
673 {
674 m_LSL_Functions.llMakeSmoke();
675 }
676
677 public void llMakeFire()
678 {
679 m_LSL_Functions.llMakeFire();
680 }
681
682 public void llRezObject(string inventory, vector pos, vector vel, rotation rot, int param)
683 {
684 m_LSL_Functions.llRezObject(inventory, pos, vel, rot, param);
685 }
686
687 public void llLookAt(vector target, double strength, double damping)
688 {
689 m_LSL_Functions.llLookAt(target, strength, damping);
690 }
691
692 public void llStopLookAt()
693 {
694 m_LSL_Functions.llStopLookAt();
695 }
696
697 public void llSetTimerEvent(double sec)
698 {
699 m_LSL_Functions.llSetTimerEvent(sec);
700 }
701
702 public void llSleep(double sec)
703 {
704 m_LSL_Functions.llSleep(sec);
705 }
706
707 //
708 // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs
709 //
710 public double llGetMass()
711 {
712 return m_LSL_Functions.llGetMass();
713 }
714
715 public void llCollisionFilter(string name, string id, int accept)
716 {
717 m_LSL_Functions.llCollisionFilter(name, id, accept);
718 }
719
720 public void llTakeControls(int controls, int accept, int pass_on)
721 {
722 m_LSL_Functions.llTakeControls(controls, accept, pass_on);
723 }
724
725 public void llReleaseControls()
726 {
727 m_LSL_Functions.llReleaseControls();
728 }
729
730 public void llAttachToAvatar(int attachment)
731 {
732 m_LSL_Functions.llAttachToAvatar(attachment);
733 }
734
735 public void llDetachFromAvatar()
736 {
737 m_LSL_Functions.llDetachFromAvatar();
738 }
739
740 public void llTakeCamera()
741 {
742 m_LSL_Functions.llTakeCamera();
743 }
744
745 public void llReleaseCamera()
746 {
747 m_LSL_Functions.llReleaseCamera();
748 }
749
750 public string llGetOwner()
751 {
752 return m_LSL_Functions.llGetOwner();
753 }
754
755 public void llInstantMessage(string user, string message)
756 {
757 m_LSL_Functions.llInstantMessage(user, message);
758 }
759
760 public void llEmail(string address, string subject, string message)
761 {
762 m_LSL_Functions.llEmail(address, subject, message);
763 }
764
765 public void llGetNextEmail(string address, string subject)
766 {
767 m_LSL_Functions.llGetNextEmail(address, subject);
768 }
769
770 public string llGetKey()
771 {
772 return m_LSL_Functions.llGetKey();
773 }
774
775 public void llSetBuoyancy(double buoyancy)
776 {
777 m_LSL_Functions.llSetBuoyancy(buoyancy);
778 }
779
780 public void llSetHoverHeight(double height, int water, double tau)
781 {
782 m_LSL_Functions.llSetHoverHeight(height, water, tau);
783 }
784
785 public void llStopHover()
786 {
787 m_LSL_Functions.llStopHover();
788 }
789
790 public void llMinEventDelay(double delay)
791 {
792 m_LSL_Functions.llMinEventDelay(delay);
793 }
794
795 public void llSoundPreload()
796 {
797 m_LSL_Functions.llSoundPreload();
798 }
799
800 public void llRotLookAt(rotation target, double strength, double damping)
801 {
802 m_LSL_Functions.llRotLookAt(target, strength, damping);
803 }
804
805 //
806 // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs
807 //
808 public LSL_Types.LSLInteger llStringLength(string str)
809 {
810 return m_LSL_Functions.llStringLength(str);
811 }
812
813 public void llStartAnimation(string anim)
814 {
815 m_LSL_Functions.llStartAnimation(anim);
816 }
817
818 public void llStopAnimation(string anim)
819 {
820 m_LSL_Functions.llStopAnimation(anim);
821 }
822
823 public void llPointAt()
824 {
825 m_LSL_Functions.llPointAt();
826 }
827
828 public void llStopPointAt()
829 {
830 m_LSL_Functions.llStopPointAt();
831 }
832
833 public void llTargetOmega(vector axis, double spinrate, double gain)
834 {
835 m_LSL_Functions.llTargetOmega(axis, spinrate, gain);
836 }
837
838 public LSL_Types.LSLInteger llGetStartParameter()
839 {
840 return m_LSL_Functions.llGetStartParameter();
841 }
842
843 public void llGodLikeRezObject(string inventory, vector pos)
844 {
845 m_LSL_Functions.llGodLikeRezObject(inventory, pos);
846 }
847
848 public void llRequestPermissions(string agent, int perm)
849 {
850 m_LSL_Functions.llRequestPermissions(agent, perm);
851 }
852
853 public string llGetPermissionsKey()
854 {
855 return m_LSL_Functions.llGetPermissionsKey();
856 }
857
858 public LSL_Types.LSLInteger llGetPermissions()
859 {
860 return m_LSL_Functions.llGetPermissions();
861 }
862
863 public LSL_Types.LSLInteger llGetLinkNumber()
864 {
865 return m_LSL_Functions.llGetLinkNumber();
866 }
867
868 public void llSetLinkColor(int linknumber, vector color, int face)
869 {
870 m_LSL_Functions.llSetLinkColor(linknumber, color, face);
871 }
872
873 public void llCreateLink(string target, int parent)
874 {
875 m_LSL_Functions.llCreateLink(target, parent);
876 }
877
878 public void llBreakLink(int linknum)
879 {
880 m_LSL_Functions.llBreakLink(linknum);
881 }
882
883 public void llBreakAllLinks()
884 {
885 m_LSL_Functions.llBreakAllLinks();
886 }
887
888 public string llGetLinkKey(int linknum)
889 {
890 return m_LSL_Functions.llGetLinkKey(linknum);
891 }
892
893 public string llGetLinkName(int linknum)
894 {
895 return m_LSL_Functions.llGetLinkName(linknum);
896 }
897
898 public LSL_Types.LSLInteger llGetInventoryNumber(int type)
899 {
900 return m_LSL_Functions.llGetInventoryNumber(type);
901 }
902
903 public string llGetInventoryName(int type, int number)
904 {
905 return m_LSL_Functions.llGetInventoryName(type, number);
906 }
907
908 //
909 // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs
910 //
911 public void llSetScriptState(string name, int run)
912 {
913 m_LSL_Functions.llSetScriptState(name, run);
914 }
915
916 public double llGetEnergy()
917 {
918 return m_LSL_Functions.llGetEnergy();
919 }
920
921 public void llGiveInventory(string destination, string inventory)
922 {
923 m_LSL_Functions.llGiveInventory(destination, inventory);
924 }
925
926 public void llRemoveInventory(string item)
927 {
928 m_LSL_Functions.llRemoveInventory(item);
929 }
930
931 public void llSetText(string text, vector color, double alpha)
932 {
933 m_LSL_Functions.llSetText(text, color, alpha);
934 }
935
936 public double llWater(vector offset)
937 {
938 return m_LSL_Functions.llWater(offset);
939 }
940
941 public void llPassTouches(int pass)
942 {
943 m_LSL_Functions.llPassTouches(pass);
944 }
945
946 public string llRequestAgentData(string id, int data)
947 {
948 return m_LSL_Functions.llRequestAgentData(id, data);
949 }
950
951 public string llRequestInventoryData(string name)
952 {
953 return m_LSL_Functions.llRequestInventoryData(name);
954 }
955
956 public void llSetDamage(double damage)
957 {
958 m_LSL_Functions.llSetDamage(damage);
959 }
960
961 public void llTeleportAgentHome(string agent)
962 {
963 m_LSL_Functions.llTeleportAgentHome(agent);
964 }
965
966 public void llModifyLand(int action, int brush)
967 {
968 m_LSL_Functions.llModifyLand(action, brush);
969 }
970
971 public void llCollisionSound(string impact_sound, double impact_volume)
972 {
973 m_LSL_Functions.llCollisionSound(impact_sound, impact_volume);
974 }
975
976 public void llCollisionSprite(string impact_sprite)
977 {
978 m_LSL_Functions.llCollisionSprite(impact_sprite);
979 }
980
981 public string llGetAnimation(string id)
982 {
983 return m_LSL_Functions.llGetAnimation(id);
984 }
985
986 public void llResetScript()
987 {
988 m_LSL_Functions.llResetScript();
989 }
990
991 public void llMessageLinked(int linknum, int num, string str, string id)
992 {
993 m_LSL_Functions.llMessageLinked(linknum, num, str, id);
994 }
995
996 public void llPushObject(string target, vector impulse, vector ang_impulse, int local)
997 {
998 m_LSL_Functions.llPushObject(target, impulse, ang_impulse, local);
999 }
1000
1001 public void llPassCollisions(int pass)
1002 {
1003 m_LSL_Functions.llPassCollisions(pass);
1004 }
1005
1006 public string llGetScriptName()
1007 {
1008 return m_LSL_Functions.llGetScriptName();
1009 }
1010
1011 public LSL_Types.LSLInteger llGetNumberOfSides()
1012 {
1013 return m_LSL_Functions.llGetNumberOfSides();
1014 }
1015
1016 //
1017 // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs
1018 //
1019 public rotation llAxisAngle2Rot(vector axis, double angle)
1020 {
1021 return m_LSL_Functions.llAxisAngle2Rot(axis, angle);
1022 }
1023
1024 public vector llRot2Axis(rotation rot)
1025 {
1026 return m_LSL_Functions.llRot2Axis(rot);
1027 }
1028
1029 public double llRot2Angle(rotation rot)
1030 {
1031 return m_LSL_Functions.llRot2Angle(rot);
1032 }
1033
1034 public double llAcos(double val)
1035 {
1036 return m_LSL_Functions.llAcos(val);
1037 }
1038
1039 public double llAsin(double val)
1040 {
1041 return m_LSL_Functions.llAsin(val);
1042 }
1043
1044 public double llAngleBetween(rotation a, rotation b)
1045 {
1046 return m_LSL_Functions.llAngleBetween(a, b);
1047 }
1048
1049 public string llGetInventoryKey(string name)
1050 {
1051 return m_LSL_Functions.llGetInventoryKey(name);
1052 }
1053
1054 public void llAllowInventoryDrop(int add)
1055 {
1056 m_LSL_Functions.llAllowInventoryDrop(add);
1057 }
1058
1059 public vector llGetSunDirection()
1060 {
1061 return m_LSL_Functions.llGetSunDirection();
1062 }
1063
1064 public vector llGetTextureOffset(int face)
1065 {
1066 return m_LSL_Functions.llGetTextureOffset(face);
1067 }
1068
1069 public vector llGetTextureScale(int side)
1070 {
1071 return m_LSL_Functions.llGetTextureScale(side);
1072 }
1073
1074 public double llGetTextureRot(int side)
1075 {
1076 return m_LSL_Functions.llGetTextureRot(side);
1077 }
1078
1079 public LSL_Types.LSLInteger llSubStringIndex(string source, string pattern)
1080 {
1081 return m_LSL_Functions.llSubStringIndex(source, pattern);
1082 }
1083
1084 public string llGetOwnerKey(string id)
1085 {
1086 return m_LSL_Functions.llGetOwnerKey(id);
1087 }
1088
1089 public vector llGetCenterOfMass()
1090 {
1091 return m_LSL_Functions.llGetCenterOfMass();
1092 }
1093
1094 public LSL_Types.list llListSort(LSL_Types.list src, int stride, int ascending)
1095 {
1096 return m_LSL_Functions.llListSort(src, stride, ascending);
1097 }
1098
1099 public LSL_Types.LSLInteger llGetListLength(LSL_Types.list src)
1100 {
1101 return m_LSL_Functions.llGetListLength(src);
1102 }
1103
1104 //
1105 // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs
1106 //
1107 public LSL_Types.LSLInteger llList2Integer(LSL_Types.list src, int index)
1108 {
1109 return m_LSL_Functions.llList2Integer(src, index);
1110 }
1111
1112 public string llList2String(LSL_Types.list src, int index)
1113 {
1114 return m_LSL_Functions.llList2String(src, index);
1115 }
1116
1117 public string llList2Key(LSL_Types.list src, int index)
1118 {
1119 return m_LSL_Functions.llList2Key(src, index);
1120 }
1121
1122 public vector llList2Vector(LSL_Types.list src, int index)
1123 {
1124 return m_LSL_Functions.llList2Vector(src, index);
1125 }
1126
1127 public rotation llList2Rot(LSL_Types.list src, int index)
1128 {
1129 return m_LSL_Functions.llList2Rot(src, index);
1130 }
1131
1132 public LSL_Types.list llList2List(LSL_Types.list src, int start, int end)
1133 {
1134 return m_LSL_Functions.llList2List(src, start, end);
1135 }
1136
1137 public LSL_Types.list llDeleteSubList(LSL_Types.list src, int start, int end)
1138 {
1139 return m_LSL_Functions.llDeleteSubList(src, start, end);
1140 }
1141
1142 public LSL_Types.LSLInteger llGetListEntryType(LSL_Types.list src, int index)
1143 {
1144 return m_LSL_Functions.llGetListEntryType(src, index);
1145 }
1146
1147 public string llList2CSV(LSL_Types.list src)
1148 {
1149 return m_LSL_Functions.llList2CSV(src);
1150 }
1151
1152 public LSL_Types.list llCSV2List(string src)
1153 {
1154 return m_LSL_Functions.llCSV2List(src);
1155 }
1156
1157 public LSL_Types.list llListRandomize(LSL_Types.list src, int stride)
1158 {
1159 return m_LSL_Functions.llListRandomize(src, stride);
1160 }
1161
1162 public LSL_Types.list llList2ListStrided(LSL_Types.list src, int start, int end, int stride)
1163 {
1164 return m_LSL_Functions.llList2ListStrided(src, start, end, stride);
1165 }
1166
1167 public vector llGetRegionCorner()
1168 {
1169 return m_LSL_Functions.llGetRegionCorner();
1170 }
1171
1172 public LSL_Types.list llListInsertList(LSL_Types.list dest, LSL_Types.list src, int start)
1173 {
1174 return m_LSL_Functions.llListInsertList(dest, src, start);
1175 }
1176
1177 public LSL_Types.LSLInteger llListFindList(LSL_Types.list src, LSL_Types.list test)
1178 {
1179 return m_LSL_Functions.llListFindList(src, test);
1180 }
1181
1182 public string llGetObjectName()
1183 {
1184 return m_LSL_Functions.llGetObjectName();
1185 }
1186
1187 public void llSetObjectName(string name)
1188 {
1189 m_LSL_Functions.llSetObjectName(name);
1190 }
1191
1192 public string llGetDate()
1193 {
1194 return m_LSL_Functions.llGetDate();
1195 }
1196
1197 public LSL_Types.LSLInteger llEdgeOfWorld(vector pos, vector dir)
1198 {
1199 return m_LSL_Functions.llEdgeOfWorld(pos, dir);
1200 }
1201
1202 public LSL_Types.LSLInteger llGetAgentInfo(string id)
1203 {
1204 return m_LSL_Functions.llGetAgentInfo(id);
1205 }
1206
1207 //
1208 // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs
1209 //
1210 public void llAdjustSoundVolume(double volume)
1211 {
1212 m_LSL_Functions.llAdjustSoundVolume(volume);
1213 }
1214
1215 public void llSetSoundQueueing(int queue)
1216 {
1217 m_LSL_Functions.llSetSoundQueueing(queue);
1218 }
1219
1220 public void llSetSoundRadius(double radius)
1221 {
1222 m_LSL_Functions.llSetSoundRadius(radius);
1223 }
1224
1225 public string llKey2Name(string id)
1226 {
1227 return m_LSL_Functions.llKey2Name(id);
1228 }
1229
1230 public void llSetTextureAnim(int mode, int face, int sizex, int sizey, double start, double length, double rate)
1231 {
1232 m_LSL_Functions.llSetTextureAnim(mode, face, sizex, sizey, start, length, rate);
1233 }
1234
1235 public void llTriggerSoundLimited(string sound, double volume, vector top_north_east, vector bottom_south_west)
1236 {
1237 m_LSL_Functions.llTriggerSoundLimited(sound, volume, top_north_east, bottom_south_west);
1238 }
1239
1240 public void llEjectFromLand(string pest)
1241 {
1242 m_LSL_Functions.llEjectFromLand(pest);
1243 }
1244
1245 public LSL_Types.list llParseString2List(string str, LSL_Types.list separators, LSL_Types.list spacers)
1246 {
1247 return m_LSL_Functions.llParseString2List(str,separators,spacers);
1248 }
1249
1250 public LSL_Types.LSLInteger llOverMyLand(string id)
1251 {
1252 return m_LSL_Functions.llOverMyLand(id);
1253 }
1254
1255 public string llGetLandOwnerAt(vector pos)
1256 {
1257 return m_LSL_Functions.llGetLandOwnerAt(pos);
1258 }
1259
1260 public string llGetNotecardLine(string name, int line)
1261 {
1262 return m_LSL_Functions.llGetNotecardLine(name, line);
1263 }
1264
1265 public vector llGetAgentSize(string id)
1266 {
1267 return m_LSL_Functions.llGetAgentSize(id);
1268 }
1269
1270 public LSL_Types.LSLInteger llSameGroup(string agent)
1271 {
1272 return m_LSL_Functions.llSameGroup(agent);
1273 }
1274
1275 public void llUnSit(string id)
1276 {
1277 m_LSL_Functions.llUnSit(id);
1278 }
1279
1280 public vector llGroundSlope(vector offset)
1281 {
1282 return m_LSL_Functions.llGroundSlope(offset);
1283 }
1284
1285 public vector llGroundNormal(vector offset)
1286 {
1287 return m_LSL_Functions.llGroundNormal(offset);
1288 }
1289
1290 public vector llGroundContour(vector offset)
1291 {
1292 return m_LSL_Functions.llGroundContour(offset);
1293 }
1294
1295 public LSL_Types.LSLInteger llGetAttached()
1296 {
1297 return m_LSL_Functions.llGetAttached();
1298 }
1299
1300 public LSL_Types.LSLInteger llGetFreeMemory()
1301 {
1302 return m_LSL_Functions.llGetFreeMemory();
1303 }
1304
1305 public string llGetRegionName()
1306 {
1307 return m_LSL_Functions.llGetRegionName();
1308 }
1309
1310 public double llGetRegionTimeDilation()
1311 {
1312 return m_LSL_Functions.llGetRegionTimeDilation();
1313 }
1314
1315 public double llGetRegionFPS()
1316 {
1317 return m_LSL_Functions.llGetRegionFPS();
1318 }
1319
1320 //
1321 // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs
1322 //
1323 public void llParticleSystem(LSL_Types.list rules)
1324 {
1325 m_LSL_Functions.llParticleSystem(rules);
1326 }
1327
1328 public void llGroundRepel(double height, int water, double tau)
1329 {
1330 m_LSL_Functions.llGroundRepel(height, water, tau);
1331 }
1332
1333 public void llGiveInventoryList(string destination, string category, LSL_Types.list inventory)
1334 {
1335 m_LSL_Functions.llGiveInventoryList(destination, category, inventory);
1336 }
1337
1338 public void llSetVehicleType(int type)
1339 {
1340 m_LSL_Functions.llSetVehicleType(type);
1341 }
1342
1343 public void llSetVehicledoubleParam(int param, double value)
1344 {
1345 m_LSL_Functions.llSetVehicledoubleParam(param, value);
1346 }
1347
1348 public void llSetVehicleFloatParam(int param, float value)
1349 {
1350 m_LSL_Functions.llSetVehicleFloatParam(param, value);
1351 }
1352
1353 public void llSetVehicleVectorParam(int param, vector vec)
1354 {
1355 m_LSL_Functions.llSetVehicleVectorParam(param, vec);
1356 }
1357
1358 public void llSetVehicleRotationParam(int param, rotation rot)
1359 {
1360 m_LSL_Functions.llSetVehicleRotationParam(param, rot);
1361 }
1362
1363 public void llSetVehicleFlags(int flags)
1364 {
1365 m_LSL_Functions.llSetVehicleFlags(flags);
1366 }
1367
1368 public void llRemoveVehicleFlags(int flags)
1369 {
1370 m_LSL_Functions.llRemoveVehicleFlags(flags);
1371 }
1372
1373 public void llSitTarget(vector offset, rotation rot)
1374 {
1375 m_LSL_Functions.llSitTarget(offset, rot);
1376 }
1377
1378 public string llAvatarOnSitTarget()
1379 {
1380 return m_LSL_Functions.llAvatarOnSitTarget();
1381 }
1382
1383 public void llAddToLandPassList(string avatar, double hours)
1384 {
1385 m_LSL_Functions.llAddToLandPassList(avatar, hours);
1386 }
1387
1388 public void llSetTouchText(string text)
1389 {
1390 m_LSL_Functions.llSetTouchText(text);
1391 }
1392
1393 public void llSetSitText(string text)
1394 {
1395 m_LSL_Functions.llSetSitText(text);
1396 }
1397
1398 public void llSetCameraEyeOffset(vector offset)
1399 {
1400 m_LSL_Functions.llSetCameraEyeOffset(offset);
1401 }
1402
1403 public void llSetCameraAtOffset(vector offset)
1404 {
1405 m_LSL_Functions.llSetCameraAtOffset(offset);
1406 }
1407
1408 public string llDumpList2String(LSL_Types.list src, string seperator)
1409 {
1410 return m_LSL_Functions.llDumpList2String(src, seperator);
1411 }
1412
1413 public LSL_Types.LSLInteger llScriptDanger(vector pos)
1414 {
1415 return m_LSL_Functions.llScriptDanger(pos);
1416 }
1417
1418 public void llDialog(string avatar, string message, LSL_Types.list buttons, int chat_channel)
1419 {
1420 m_LSL_Functions.llDialog(avatar, message, buttons, chat_channel);
1421 }
1422
1423 public void llVolumeDetect(int detect)
1424 {
1425 m_LSL_Functions.llVolumeDetect(detect);
1426 }
1427
1428 public void llResetOtherScript(string name)
1429 {
1430 m_LSL_Functions.llResetOtherScript(name);
1431 }
1432
1433 public LSL_Types.LSLInteger llGetScriptState(string name)
1434 {
1435 return m_LSL_Functions.llGetScriptState(name);
1436 }
1437
1438 public void llRemoteLoadScript()
1439 {
1440 m_LSL_Functions.llRemoteLoadScript();
1441 }
1442
1443 public void llSetRemoteScriptAccessPin(int pin)
1444 {
1445 m_LSL_Functions.llSetRemoteScriptAccessPin(pin);
1446 }
1447
1448 public void llRemoteLoadScriptPin(string target, string name, int pin, int running, int start_param)
1449 {
1450 m_LSL_Functions.llRemoteLoadScriptPin(target, name, pin, running, start_param);
1451 }
1452
1453 //
1454 // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs
1455 //
1456 public void llOpenRemoteDataChannel()
1457 {
1458 m_LSL_Functions.llOpenRemoteDataChannel();
1459 }
1460
1461 public string llSendRemoteData(string channel, string dest, int idata, string sdata)
1462 {
1463 return m_LSL_Functions.llSendRemoteData(channel, dest, idata, sdata);
1464 }
1465
1466 public void llRemoteDataReply(string channel, string message_id, string sdata, int idata)
1467 {
1468 m_LSL_Functions.llRemoteDataReply(channel, message_id, sdata, idata);
1469 }
1470
1471 public void llCloseRemoteDataChannel(string channel)
1472 {
1473 m_LSL_Functions.llCloseRemoteDataChannel(channel);
1474 }
1475
1476 public string llMD5String(string src, int nonce)
1477 {
1478 return m_LSL_Functions.llMD5String(src, nonce);
1479 }
1480
1481 public void llSetPrimitiveParams(LSL_Types.list rules)
1482 {
1483 m_LSL_Functions.llSetPrimitiveParams(rules);
1484 }
1485
1486 public void llSetLinkPrimitiveParams(int linknumber, LSL_Types.list rules)
1487 {
1488 m_LSL_Functions.llSetLinkPrimitiveParams(linknumber, rules);
1489 }
1490 public string llStringToBase64(string str)
1491 {
1492 return m_LSL_Functions.llStringToBase64(str);
1493 }
1494
1495 public string llBase64ToString(string str)
1496 {
1497 return m_LSL_Functions.llBase64ToString(str);
1498 }
1499
1500 public void llXorBase64Strings()
1501 {
1502 m_LSL_Functions.llXorBase64Strings();
1503 }
1504
1505 public void llRemoteDataSetRegion()
1506 {
1507 m_LSL_Functions.llRemoteDataSetRegion();
1508 }
1509
1510 public double llLog10(double val)
1511 {
1512 return m_LSL_Functions.llLog10(val);
1513 }
1514
1515 public double llLog(double val)
1516 {
1517 return m_LSL_Functions.llLog(val);
1518 }
1519
1520 public LSL_Types.list llGetAnimationList(string id)
1521 {
1522 return m_LSL_Functions.llGetAnimationList(id);
1523 }
1524
1525 public void llSetParcelMusicURL(string url)
1526 {
1527 m_LSL_Functions.llSetParcelMusicURL(url);
1528 }
1529
1530 public vector llGetRootPosition()
1531 {
1532 return m_LSL_Functions.llGetRootPosition();
1533 }
1534
1535 public rotation llGetRootRotation()
1536 {
1537 return m_LSL_Functions.llGetRootRotation();
1538 }
1539
1540 public string llGetObjectDesc()
1541 {
1542 return m_LSL_Functions.llGetObjectDesc();
1543 }
1544
1545 public void llSetObjectDesc(string desc)
1546 {
1547 m_LSL_Functions.llSetObjectDesc(desc);
1548 }
1549
1550 public string llGetCreator()
1551 {
1552 return m_LSL_Functions.llGetCreator();
1553 }
1554
1555 public string llGetTimestamp()
1556 {
1557 return m_LSL_Functions.llGetTimestamp();
1558 }
1559
1560 public void llSetLinkAlpha(int linknumber, double alpha, int face)
1561 {
1562 m_LSL_Functions.llSetLinkAlpha(linknumber, alpha, face);
1563 }
1564
1565 public LSL_Types.LSLInteger llGetNumberOfPrims()
1566 {
1567 return m_LSL_Functions.llGetNumberOfPrims();
1568 }
1569
1570 public string llGetNumberOfNotecardLines(string name)
1571 {
1572 return m_LSL_Functions.llGetNumberOfNotecardLines(name);
1573 }
1574
1575 public LSL_Types.list llGetBoundingBox(string obj)
1576 {
1577 return m_LSL_Functions.llGetBoundingBox(obj);
1578 }
1579
1580 public vector llGetGeometricCenter()
1581 {
1582 return m_LSL_Functions.llGetGeometricCenter();
1583 }
1584
1585 public LSL_Types.list llGetPrimitiveParams(LSL_Types.list rules)
1586 {
1587 return m_LSL_Functions.llGetPrimitiveParams(rules);
1588 }
1589
1590 //
1591 // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs
1592 //
1593 public string llIntegerToBase64(int number)
1594 {
1595 return m_LSL_Functions.llIntegerToBase64(number);
1596 }
1597
1598 public LSL_Types.LSLInteger llBase64ToInteger(string str)
1599 {
1600 return m_LSL_Functions.llBase64ToInteger(str);
1601 }
1602
1603 public double llGetGMTclock()
1604 {
1605 return m_LSL_Functions.llGetGMTclock();
1606 }
1607
1608 public string llGetSimulatorHostname()
1609 {
1610 return m_LSL_Functions.llGetSimulatorHostname();
1611 }
1612
1613 public void llSetLocalRot(rotation rot)
1614 {
1615 m_LSL_Functions.llSetLocalRot(rot);
1616 }
1617
1618 public LSL_Types.list llParseStringKeepNulls(string src, LSL_Types.list seperators, LSL_Types.list spacers)
1619 {
1620 return m_LSL_Functions.llParseStringKeepNulls(src, seperators, spacers);
1621 }
1622
1623 public void llRezAtRoot(string inventory, vector position, vector velocity, rotation rot, int param)
1624 {
1625 m_LSL_Functions.llRezAtRoot(inventory, position, velocity, rot, param);
1626 }
1627
1628 public LSL_Types.LSLInteger llGetObjectPermMask(int mask)
1629 {
1630 return m_LSL_Functions.llGetObjectPermMask(mask);
1631 }
1632
1633 public void llSetObjectPermMask(int mask, int value)
1634 {
1635 m_LSL_Functions.llSetObjectPermMask(mask, value);
1636 }
1637
1638 public LSL_Types.LSLInteger llGetInventoryPermMask(string item, int mask)
1639 {
1640 return m_LSL_Functions.llGetInventoryPermMask(item, mask);
1641 }
1642
1643 public void llSetInventoryPermMask(string item, int mask, int value)
1644 {
1645 m_LSL_Functions.llSetInventoryPermMask(item, mask, value);
1646 }
1647
1648 public string llGetInventoryCreator(string item)
1649 {
1650 return m_LSL_Functions.llGetInventoryCreator(item);
1651 }
1652
1653 public void llOwnerSay(string msg)
1654 {
1655 m_LSL_Functions.llOwnerSay(msg);
1656 }
1657
1658 public string llRequestSimulatorData(string simulator, int data)
1659 {
1660 return m_LSL_Functions.llRequestSimulatorData(simulator, data);
1661 }
1662
1663 public void llForceMouselook(int mouselook)
1664 {
1665 m_LSL_Functions.llForceMouselook(mouselook);
1666 }
1667
1668 public double llGetObjectMass(string id)
1669 {
1670 return m_LSL_Functions.llGetObjectMass(id);
1671 }
1672
1673 public LSL_Types.list llListReplaceList(LSL_Types.list dest, LSL_Types.list src, int start, int end)
1674 {
1675 return m_LSL_Functions.llListReplaceList(dest, src, start, end);
1676 }
1677
1678 public void llLoadURL(string avatar_id, string message, string url)
1679 {
1680 m_LSL_Functions.llLoadURL(avatar_id, message, url);
1681 }
1682
1683 public void llParcelMediaCommandList(LSL_Types.list commandList)
1684 {
1685 m_LSL_Functions.llParcelMediaCommandList(commandList);
1686 }
1687
1688 public void llParcelMediaQuery()
1689 {
1690 m_LSL_Functions.llParcelMediaQuery();
1691 }
1692
1693 public LSL_Types.LSLInteger llModPow(int a, int b, int c)
1694 {
1695 return m_LSL_Functions.llModPow(a, b, c);
1696 }
1697
1698 //
1699 // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs
1700 //
1701 public LSL_Types.LSLInteger llGetInventoryType(string name)
1702 {
1703 return m_LSL_Functions.llGetInventoryType(name);
1704 }
1705
1706 public void llSetPayPrice(int price, LSL_Types.list quick_pay_buttons)
1707 {
1708 m_LSL_Functions.llSetPayPrice(price, quick_pay_buttons);
1709 }
1710
1711 public vector llGetCameraPos()
1712 {
1713 return m_LSL_Functions.llGetCameraPos();
1714 }
1715
1716 public rotation llGetCameraRot()
1717 {
1718 return m_LSL_Functions.llGetCameraRot();
1719 }
1720
1721 public void llSetPrimURL()
1722 {
1723 m_LSL_Functions.llSetPrimURL();
1724 }
1725
1726 public void llRefreshPrimURL()
1727 {
1728 m_LSL_Functions.llRefreshPrimURL();
1729 }
1730
1731 public string llEscapeURL(string url)
1732 {
1733 return m_LSL_Functions.llEscapeURL(url);
1734 }
1735
1736 public string llUnescapeURL(string url)
1737 {
1738 return m_LSL_Functions.llUnescapeURL(url);
1739 }
1740
1741 public void llMapDestination(string simname, vector pos, vector look_at)
1742 {
1743 m_LSL_Functions.llMapDestination(simname, pos, look_at);
1744 }
1745
1746 public void llAddToLandBanList(string avatar, double hours)
1747 {
1748 m_LSL_Functions.llAddToLandBanList(avatar, hours);
1749 }
1750
1751 public void llRemoveFromLandPassList(string avatar)
1752 {
1753 m_LSL_Functions.llRemoveFromLandPassList(avatar);
1754 }
1755
1756 public void llRemoveFromLandBanList(string avatar)
1757 {
1758 m_LSL_Functions.llRemoveFromLandBanList(avatar);
1759 }
1760
1761 public void llSetCameraParams(LSL_Types.list rules)
1762 {
1763 m_LSL_Functions.llSetCameraParams(rules);
1764 }
1765
1766 public void llClearCameraParams()
1767 {
1768 m_LSL_Functions.llClearCameraParams();
1769 }
1770
1771 public double llListStatistics(int operation, LSL_Types.list src)
1772 {
1773 return m_LSL_Functions.llListStatistics(operation, src);
1774 }
1775
1776 public LSL_Types.LSLInteger llGetUnixTime()
1777 {
1778 return m_LSL_Functions.llGetUnixTime();
1779 }
1780
1781 public LSL_Types.LSLInteger llGetParcelFlags(vector pos)
1782 {
1783 return m_LSL_Functions.llGetParcelFlags(pos);
1784 }
1785
1786 public LSL_Types.LSLInteger llGetRegionFlags()
1787 {
1788 return m_LSL_Functions.llGetRegionFlags();
1789 }
1790
1791 public string llXorBase64StringsCorrect(string str1, string str2)
1792 {
1793 return m_LSL_Functions.llXorBase64StringsCorrect(str1, str2);
1794 }
1795
1796 public string llHTTPRequest(string url, LSL_Types.list parameters, string body)
1797 {
1798 return m_LSL_Functions.llHTTPRequest(url, parameters, body);
1799 }
1800
1801 public void llResetLandBanList()
1802 {
1803 m_LSL_Functions.llResetLandBanList();
1804 }
1805
1806 public void llResetLandPassList()
1807 {
1808 m_LSL_Functions.llResetLandPassList();
1809 }
1810
1811 public LSL_Types.LSLInteger llGetParcelPrimCount(vector pos, int category, int sim_wide)
1812 {
1813 return m_LSL_Functions.llGetParcelPrimCount(pos, category, sim_wide);
1814 }
1815
1816 public LSL_Types.list llGetParcelPrimOwners(vector pos)
1817 {
1818 return m_LSL_Functions.llGetParcelPrimOwners(pos);
1819 }
1820
1821 public LSL_Types.LSLInteger llGetObjectPrimCount(string object_id)
1822 {
1823 return m_LSL_Functions.llGetObjectPrimCount(object_id);
1824 }
1825
1826 //
1827 // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs
1828 //
1829 public LSL_Types.LSLInteger llGetParcelMaxPrims(vector pos, int sim_wide)
1830 {
1831 return m_LSL_Functions.llGetParcelMaxPrims(pos, sim_wide);
1832 }
1833
1834 public LSL_Types.list llGetParcelDetails(vector pos, LSL_Types.list param)
1835 {
1836 return m_LSL_Functions.llGetParcelDetails(pos, param);
1837 }
1838
1839 public void llSetLinkTexture(int linknumber, string texture, int face)
1840 {
1841 m_LSL_Functions.llSetLinkTexture(linknumber, texture, face);
1842 }
1843
1844 public string llStringTrim(string src, int type)
1845 {
1846 return m_LSL_Functions.llStringTrim(src, type);
1847 }
1848
1849 public LSL_Types.list llGetObjectDetails(string id, LSL_Types.list args)
1850 {
1851 return m_LSL_Functions.llGetObjectDetails(id, args);
1852 }
1853
1854 public double llList2Float(LSL_Types.list src, int index)
1855 {
1856 return m_LSL_Functions.llList2Float(src, index);
1857 }
1858
1859 // LSL CONSTANTS
1860 public const int TRUE = 1;
1861 public const int FALSE = 0;
1862
1863 public const int STATUS_PHYSICS = 1;
1864 public const int STATUS_ROTATE_X = 2;
1865 public const int STATUS_ROTATE_Y = 4;
1866 public const int STATUS_ROTATE_Z = 8;
1867 public const int STATUS_PHANTOM = 16;
1868 public const int STATUS_SANDBOX = 32;
1869 public const int STATUS_BLOCK_GRAB = 64;
1870 public const int STATUS_DIE_AT_EDGE = 128;
1871 public const int STATUS_RETURN_AT_EDGE = 256;
1872 public const int STATUS_CAST_SHADOWS = 512;
1873
1874 public const int AGENT = 1;
1875 public const int ACTIVE = 2;
1876 public const int PASSIVE = 4;
1877 public const int SCRIPTED = 8;
1878
1879 public const int CONTROL_FWD = 1;
1880 public const int CONTROL_BACK = 2;
1881 public const int CONTROL_LEFT = 4;
1882 public const int CONTROL_RIGHT = 8;
1883 public const int CONTROL_UP = 16;
1884 public const int CONTROL_DOWN = 32;
1885 public const int CONTROL_ROT_LEFT = 256;
1886 public const int CONTROL_ROT_RIGHT = 512;
1887 public const int CONTROL_LBUTTON = 268435456;
1888 public const int CONTROL_ML_LBUTTON = 1073741824;
1889
1890 //Permissions
1891 public const int PERMISSION_DEBIT = 2;
1892 public const int PERMISSION_TAKE_CONTROLS = 4;
1893 public const int PERMISSION_REMAP_CONTROLS = 8;
1894 public const int PERMISSION_TRIGGER_ANIMATION = 16;
1895 public const int PERMISSION_ATTACH = 32;
1896 public const int PERMISSION_RELEASE_OWNERSHIP = 64;
1897 public const int PERMISSION_CHANGE_LINKS = 128;
1898 public const int PERMISSION_CHANGE_JOINTS = 256;
1899 public const int PERMISSION_CHANGE_PERMISSIONS = 512;
1900 public const int PERMISSION_TRACK_CAMERA = 1024;
1901
1902 public const int AGENT_FLYING = 1;
1903 public const int AGENT_ATTACHMENTS = 2;
1904 public const int AGENT_SCRIPTED = 4;
1905 public const int AGENT_MOUSELOOK = 8;
1906 public const int AGENT_SITTING = 16;
1907 public const int AGENT_ON_OBJECT = 32;
1908 public const int AGENT_AWAY = 64;
1909 public const int AGENT_WALKING = 128;
1910 public const int AGENT_IN_AIR = 256;
1911 public const int AGENT_TYPING = 512;
1912 public const int AGENT_CROUCHING = 1024;
1913 public const int AGENT_BUSY = 2048;
1914 public const int AGENT_ALWAYS_RUN = 4096;
1915
1916 //Particle Systems
1917 public const int PSYS_PART_INTERP_COLOR_MASK = 1;
1918 public const int PSYS_PART_INTERP_SCALE_MASK = 2;
1919 public const int PSYS_PART_BOUNCE_MASK = 4;
1920 public const int PSYS_PART_WIND_MASK = 8;
1921 public const int PSYS_PART_FOLLOW_SRC_MASK = 16;
1922 public const int PSYS_PART_FOLLOW_VELOCITY_MASK = 32;
1923 public const int PSYS_PART_TARGET_POS_MASK = 64;
1924 public const int PSYS_PART_TARGET_LINEAR_MASK = 128;
1925 public const int PSYS_PART_EMISSIVE_MASK = 256;
1926 public const int PSYS_PART_FLAGS = 0;
1927 public const int PSYS_PART_START_COLOR = 1;
1928 public const int PSYS_PART_START_ALPHA = 2;
1929 public const int PSYS_PART_END_COLOR = 3;
1930 public const int PSYS_PART_END_ALPHA = 4;
1931 public const int PSYS_PART_START_SCALE = 5;
1932 public const int PSYS_PART_END_SCALE = 6;
1933 public const int PSYS_PART_MAX_AGE = 7;
1934 public const int PSYS_SRC_ACCEL = 8;
1935 public const int PSYS_SRC_PATTERN = 9;
1936 public const int PSYS_SRC_INNERANGLE = 10;
1937 public const int PSYS_SRC_OUTERANGLE = 11;
1938 public const int PSYS_SRC_TEXTURE = 12;
1939 public const int PSYS_SRC_BURST_RATE = 13;
1940 public const int PSYS_SRC_BURST_PART_COUNT = 15;
1941 public const int PSYS_SRC_BURST_RADIUS = 16;
1942 public const int PSYS_SRC_BURST_SPEED_MIN = 17;
1943 public const int PSYS_SRC_BURST_SPEED_MAX = 18;
1944 public const int PSYS_SRC_MAX_AGE = 19;
1945 public const int PSYS_SRC_TARGET_KEY = 20;
1946 public const int PSYS_SRC_OMEGA = 21;
1947 public const int PSYS_SRC_ANGLE_BEGIN = 22;
1948 public const int PSYS_SRC_ANGLE_END = 23;
1949 public const int PSYS_SRC_PATTERN_DROP = 1;
1950 public const int PSYS_SRC_PATTERN_EXPLODE = 2;
1951 public const int PSYS_SRC_PATTERN_ANGLE = 4;
1952 public const int PSYS_SRC_PATTERN_ANGLE_CONE = 8;
1953 public const int PSYS_SRC_PATTERN_ANGLE_CONE_EMPTY = 16;
1954
1955 public const int VEHICLE_TYPE_NONE = 0;
1956 public const int VEHICLE_TYPE_SLED = 1;
1957 public const int VEHICLE_TYPE_CAR = 2;
1958 public const int VEHICLE_TYPE_BOAT = 3;
1959 public const int VEHICLE_TYPE_AIRPLANE = 4;
1960 public const int VEHICLE_TYPE_BALLOON = 5;
1961 public const int VEHICLE_LINEAR_FRICTION_TIMESCALE = 16;
1962 public const int VEHICLE_ANGULAR_FRICTION_TIMESCALE = 17;
1963 public const int VEHICLE_LINEAR_MOTOR_DIRECTION = 18;
1964 public const int VEHICLE_LINEAR_MOTOR_OFFSET = 20;
1965 public const int VEHICLE_ANGULAR_MOTOR_DIRECTION = 19;
1966 public const int VEHICLE_HOVER_HEIGHT = 24;
1967 public const int VEHICLE_HOVER_EFFICIENCY = 25;
1968 public const int VEHICLE_HOVER_TIMESCALE = 26;
1969 public const int VEHICLE_BUOYANCY = 27;
1970 public const int VEHICLE_LINEAR_DEFLECTION_EFFICIENCY = 28;
1971 public const int VEHICLE_LINEAR_DEFLECTION_TIMESCALE = 29;
1972 public const int VEHICLE_LINEAR_MOTOR_TIMESCALE = 30;
1973 public const int VEHICLE_LINEAR_MOTOR_DECAY_TIMESCALE = 31;
1974 public const int VEHICLE_ANGULAR_DEFLECTION_EFFICIENCY = 32;
1975 public const int VEHICLE_ANGULAR_DEFLECTION_TIMESCALE = 33;
1976 public const int VEHICLE_ANGULAR_MOTOR_TIMESCALE = 34;
1977 public const int VEHICLE_ANGULAR_MOTOR_DECAY_TIMESCALE = 35;
1978 public const int VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY = 36;
1979 public const int VEHICLE_VERTICAL_ATTRACTION_TIMESCALE = 37;
1980 public const int VEHICLE_BANKING_EFFICIENCY = 38;
1981 public const int VEHICLE_BANKING_MIX = 39;
1982 public const int VEHICLE_BANKING_TIMESCALE = 40;
1983 public const int VEHICLE_REFERENCE_FRAME = 44;
1984 public const int VEHICLE_FLAG_NO_DEFLECTION_UP = 1;
1985 public const int VEHICLE_FLAG_LIMIT_ROLL_ONLY = 2;
1986 public const int VEHICLE_FLAG_HOVER_WATER_ONLY = 4;
1987 public const int VEHICLE_FLAG_HOVER_TERRAIN_ONLY = 8;
1988 public const int VEHICLE_FLAG_HOVER_GLOBAL_HEIGHT = 16;
1989 public const int VEHICLE_FLAG_HOVER_UP_ONLY = 32;
1990 public const int VEHICLE_FLAG_LIMIT_MOTOR_UP = 64;
1991 public const int VEHICLE_FLAG_MOUSELOOK_STEER = 128;
1992 public const int VEHICLE_FLAG_MOUSELOOK_BANK = 256;
1993 public const int VEHICLE_FLAG_CAMERA_DECOUPLED = 512;
1994
1995 public const int INVENTORY_ALL = -1;
1996 public const int INVENTORY_NONE = -1;
1997 public const int INVENTORY_TEXTURE = 0;
1998 public const int INVENTORY_SOUND = 1;
1999 public const int INVENTORY_LANDMARK = 3;
2000 public const int INVENTORY_CLOTHING = 5;
2001 public const int INVENTORY_OBJECT = 6;
2002 public const int INVENTORY_NOTECARD = 7;
2003 public const int INVENTORY_SCRIPT = 10;
2004 public const int INVENTORY_BODYPART = 13;
2005 public const int INVENTORY_ANIMATION = 20;
2006 public const int INVENTORY_GESTURE = 21;
2007
2008 public const int ATTACH_CHEST = 1;
2009 public const int ATTACH_HEAD = 2;
2010 public const int ATTACH_LSHOULDER = 3;
2011 public const int ATTACH_RSHOULDER = 4;
2012 public const int ATTACH_LHAND = 5;
2013 public const int ATTACH_RHAND = 6;
2014 public const int ATTACH_LFOOT = 7;
2015 public const int ATTACH_RFOOT = 8;
2016 public const int ATTACH_BACK = 9;
2017 public const int ATTACH_PELVIS = 10;
2018 public const int ATTACH_MOUTH = 11;
2019 public const int ATTACH_CHIN = 12;
2020 public const int ATTACH_LEAR = 13;
2021 public const int ATTACH_REAR = 14;
2022 public const int ATTACH_LEYE = 15;
2023 public const int ATTACH_REYE = 16;
2024 public const int ATTACH_NOSE = 17;
2025 public const int ATTACH_RUARM = 18;
2026 public const int ATTACH_RLARM = 19;
2027 public const int ATTACH_LUARM = 20;
2028 public const int ATTACH_LLARM = 21;
2029 public const int ATTACH_RHIP = 22;
2030 public const int ATTACH_RULEG = 23;
2031 public const int ATTACH_RLLEG = 24;
2032 public const int ATTACH_LHIP = 25;
2033 public const int ATTACH_LULEG = 26;
2034 public const int ATTACH_LLLEG = 27;
2035 public const int ATTACH_BELLY = 28;
2036 public const int ATTACH_RPEC = 29;
2037 public const int ATTACH_LPEC = 30;
2038
2039 public const int LAND_LEVEL = 0;
2040 public const int LAND_RAISE = 1;
2041 public const int LAND_LOWER = 2;
2042 public const int LAND_SMOOTH = 3;
2043 public const int LAND_NOISE = 4;
2044 public const int LAND_REVERT = 5;
2045 public const int LAND_SMALL_BRUSH = 1;
2046 public const int LAND_MEDIUM_BRUSH = 2;
2047 public const int LAND_LARGE_BRUSH = 3;
2048
2049 //Agent Dataserver
2050 public const int DATA_ONLINE = 1;
2051 public const int DATA_NAME = 2;
2052 public const int DATA_BORN = 3;
2053 public const int DATA_RATING = 4;
2054 public const int DATA_SIM_POS = 5;
2055 public const int DATA_SIM_STATUS = 6;
2056 public const int DATA_SIM_RATING = 7;
2057 public const int DATA_PAYINFO = 8;
2058
2059 public const int ANIM_ON = 1;
2060 public const int LOOP = 2;
2061 public const int REVERSE = 4;
2062 public const int PING_PONG = 8;
2063 public const int SMOOTH = 16;
2064 public const int ROTATE = 32;
2065 public const int SCALE = 64;
2066 public const int ALL_SIDES = -1;
2067 public const int LINK_SET = -1;
2068 public const int LINK_ROOT = 1;
2069 public const int LINK_ALL_OTHERS = -2;
2070 public const int LINK_ALL_CHILDREN = -3;
2071 public const int LINK_THIS = -4;
2072 public const int CHANGED_INVENTORY = 1;
2073 public const int CHANGED_COLOR = 2;
2074 public const int CHANGED_SHAPE = 4;
2075 public const int CHANGED_SCALE = 8;
2076 public const int CHANGED_TEXTURE = 16;
2077 public const int CHANGED_LINK = 32;
2078 public const int CHANGED_ALLOWED_DROP = 64;
2079 public const int CHANGED_OWNER = 128;
2080 public const int TYPE_INVALID = 0;
2081 public const int TYPE_INTEGER = 1;
2082 public const int TYPE_double = 2;
2083 public const int TYPE_STRING = 3;
2084 public const int TYPE_KEY = 4;
2085 public const int TYPE_VECTOR = 5;
2086 public const int TYPE_ROTATION = 6;
2087
2088 //XML RPC Remote Data Channel
2089 public const int REMOTE_DATA_CHANNEL = 1;
2090 public const int REMOTE_DATA_REQUEST = 2;
2091 public const int REMOTE_DATA_REPLY = 3;
2092
2093 //llHTTPRequest
2094 public const int HTTP_METHOD = 0;
2095 public const int HTTP_MIMETYPE = 1;
2096 public const int HTTP_BODY_MAXLENGTH = 2;
2097 public const int HTTP_VERIFY_CERT = 3;
2098
2099 public const int PRIM_MATERIAL = 2;
2100 public const int PRIM_PHYSICS = 3;
2101 public const int PRIM_TEMP_ON_REZ = 4;
2102 public const int PRIM_PHANTOM = 5;
2103 public const int PRIM_POSITION = 6;
2104 public const int PRIM_SIZE = 7;
2105 public const int PRIM_ROTATION = 8;
2106 public const int PRIM_TYPE = 9;
2107 public const int PRIM_TEXTURE = 17;
2108 public const int PRIM_COLOR = 18;
2109 public const int PRIM_BUMP_SHINY = 19;
2110 public const int PRIM_FULLBRIGHT = 20;
2111 public const int PRIM_FLEXIBLE = 21;
2112 public const int PRIM_TEXGEN = 22;
2113 public const int PRIM_CAST_SHADOWS = 24; // Not implemented, here for completeness sake
2114 public const int PRIM_POINT_LIGHT = 23; // Huh?
2115 public const int PRIM_TEXGEN_DEFAULT = 0;
2116 public const int PRIM_TEXGEN_PLANAR = 1;
2117
2118 public const int PRIM_TYPE_BOX = 0;
2119 public const int PRIM_TYPE_CYLINDER = 1;
2120 public const int PRIM_TYPE_PRISM = 2;
2121 public const int PRIM_TYPE_SPHERE = 3;
2122 public const int PRIM_TYPE_TORUS = 4;
2123 public const int PRIM_TYPE_TUBE = 5;
2124 public const int PRIM_TYPE_RING = 6;
2125 public const int PRIM_TYPE_SCULPT = 7;
2126
2127 public const int PRIM_HOLE_DEFAULT = 0;
2128 public const int PRIM_HOLE_CIRCLE = 16;
2129 public const int PRIM_HOLE_SQUARE = 32;
2130 public const int PRIM_HOLE_TRIANGLE = 48;
2131
2132 public const int PRIM_MATERIAL_STONE = 0;
2133 public const int PRIM_MATERIAL_METAL = 1;
2134 public const int PRIM_MATERIAL_GLASS = 2;
2135 public const int PRIM_MATERIAL_WOOD = 3;
2136 public const int PRIM_MATERIAL_FLESH = 4;
2137 public const int PRIM_MATERIAL_PLASTIC = 5;
2138 public const int PRIM_MATERIAL_RUBBER = 6;
2139 public const int PRIM_MATERIAL_LIGHT = 7;
2140
2141 public const int PRIM_SHINY_NONE = 0;
2142 public const int PRIM_SHINY_LOW = 1;
2143 public const int PRIM_SHINY_MEDIUM = 2;
2144 public const int PRIM_SHINY_HIGH = 3;
2145 public const int PRIM_BUMP_NONE = 0;
2146 public const int PRIM_BUMP_BRIGHT = 1;
2147 public const int PRIM_BUMP_DARK = 2;
2148 public const int PRIM_BUMP_WOOD = 3;
2149 public const int PRIM_BUMP_BARK = 4;
2150 public const int PRIM_BUMP_BRICKS = 5;
2151 public const int PRIM_BUMP_CHECKER = 6;
2152 public const int PRIM_BUMP_CONCRETE = 7;
2153 public const int PRIM_BUMP_TILE = 8;
2154 public const int PRIM_BUMP_STONE = 9;
2155 public const int PRIM_BUMP_DISKS = 10;
2156 public const int PRIM_BUMP_GRAVEL = 11;
2157 public const int PRIM_BUMP_BLOBS = 12;
2158 public const int PRIM_BUMP_SIDING = 13;
2159 public const int PRIM_BUMP_LARGETILE = 14;
2160 public const int PRIM_BUMP_STUCCO = 15;
2161 public const int PRIM_BUMP_SUCTION = 16;
2162 public const int PRIM_BUMP_WEAVE = 17;
2163
2164 public const int PRIM_SCULPT_TYPE_SPHERE = 1;
2165 public const int PRIM_SCULPT_TYPE_TORUS = 2;
2166 public const int PRIM_SCULPT_TYPE_PLANE = 3;
2167 public const int PRIM_SCULPT_TYPE_CYLINDER = 4;
2168
2169 public const int MASK_BASE = 0;
2170 public const int MASK_OWNER = 1;
2171 public const int MASK_GROUP = 2;
2172 public const int MASK_EVERYONE = 3;
2173 public const int MASK_NEXT = 4;
2174
2175 public const int PERM_TRANSFER = 8192;
2176 public const int PERM_MODIFY = 16384;
2177 public const int PERM_COPY = 32768;
2178 public const int PERM_MOVE = 524288;
2179 public const int PERM_ALL = 2147483647;
2180
2181 public const int PARCEL_MEDIA_COMMAND_STOP = 0;
2182 public const int PARCEL_MEDIA_COMMAND_PAUSE = 1;
2183 public const int PARCEL_MEDIA_COMMAND_PLAY = 2;
2184 public const int PARCEL_MEDIA_COMMAND_LOOP = 3;
2185 public const int PARCEL_MEDIA_COMMAND_TEXTURE = 4;
2186 public const int PARCEL_MEDIA_COMMAND_URL = 5;
2187 public const int PARCEL_MEDIA_COMMAND_TIME = 6;
2188 public const int PARCEL_MEDIA_COMMAND_AGENT = 7;
2189 public const int PARCEL_MEDIA_COMMAND_UNLOAD = 8;
2190 public const int PARCEL_MEDIA_COMMAND_AUTO_ALIGN = 9;
2191
2192 public const int PAY_HIDE = -1;
2193 public const int PAY_DEFAULT = -2;
2194
2195 public const string NULL_KEY = "00000000-0000-0000-0000-000000000000";
2196 public const string EOF = "\n\n\n";
2197 public const double PI = 3.14159274f;
2198 public const double TWO_PI = 6.28318548f;
2199 public const double PI_BY_TWO = 1.57079637f;
2200 public const double DEG_TO_RAD = 0.01745329238f;
2201 public const double RAD_TO_DEG = 57.29578f;
2202 public const double SQRT2 = 1.414213538f;
2203 public const int STRING_TRIM_HEAD = 1;
2204 public const int STRING_TRIM_TAIL = 2;
2205 public const int STRING_TRIM = 3;
2206 public const int LIST_STAT_RANGE = 0;
2207 public const int LIST_STAT_MIN = 1;
2208 public const int LIST_STAT_MAX = 2;
2209 public const int LIST_STAT_MEAN = 3;
2210 public const int LIST_STAT_MEDIAN = 4;
2211 public const int LIST_STAT_STD_DEV = 5;
2212 public const int LIST_STAT_SUM = 6;
2213 public const int LIST_STAT_SUM_SQUARES = 7;
2214 public const int LIST_STAT_NUM_COUNT = 8;
2215 public const int LIST_STAT_GEOMETRIC_MEAN = 9;
2216 public const int LIST_STAT_HARMONIC_MEAN = 100;
2217
2218 //ParcelPrim Categories
2219 public const int PARCEL_COUNT_TOTAL = 0;
2220 public const int PARCEL_COUNT_OWNER = 1;
2221 public const int PARCEL_COUNT_GROUP = 2;
2222 public const int PARCEL_COUNT_OTHER = 3;
2223 public const int PARCEL_COUNT_SELECTED = 4;
2224 public const int PARCEL_COUNT_TEMP = 5;
2225
2226 public const int DEBUG_CHANNEL = 0x7FFFFFFF;
2227 public const int PUBLIC_CHANNEL = 0x00000000;
2228
2229 public const int OBJECT_NAME = 1;
2230 public const int OBJECT_DESC = 2;
2231 public const int OBJECT_POS = 3;
2232 public const int OBJECT_ROT = 4;
2233 public const int OBJECT_VELOCITY = 5;
2234 public const int OBJECT_OWNER = 6;
2235 public const int OBJECT_GROUP = 7;
2236 public const int OBJECT_CREATOR = 8;
2237
2238 // Can not be public const?
2239 public vector ZERO_VECTOR = new vector(0.0, 0.0, 0.0);
2240 public rotation ZERO_ROTATION = new rotation(0.0, 0, 0.0, 1.0);
2241
2242
2243 //
2244 // OSSL
2245 //
2246 // FIXME: Refactor so we don't need to pull the script engine
2247 // into the app domain
2248 //
2249
2250 public void osSetRegionWaterHeight(double height)
2251 {
2252 m_OSSL_Functions.osSetRegionWaterHeight(height);
2253 }
2254
2255 public double osList2Double(LSL_Types.list src, int index)
2256 {
2257 return m_OSSL_Functions.osList2Double(src, index);
2258 }
2259
2260 public string osSetDynamicTextureURL(string dynamicID, string contentType, string url, string extraParams,
2261 int timer)
2262 {
2263 return m_OSSL_Functions.osSetDynamicTextureURL(dynamicID, contentType, url, extraParams, timer);
2264 }
2265
2266 public string osSetDynamicTextureData(string dynamicID, string contentType, string data, string extraParams,
2267 int timer)
2268 {
2269 return m_OSSL_Functions.osSetDynamicTextureData(dynamicID, contentType, data, extraParams, timer);
2270 }
2271
2272 public string osSetDynamicTextureURLBlend(string dynamicID, string contentType, string url, string extraParams,
2273 int timer, int alpha)
2274 {
2275 return m_OSSL_Functions.osSetDynamicTextureURLBlend(dynamicID, contentType, url, extraParams, timer, alpha);
2276 }
2277
2278 public string osSetDynamicTextureDataBlend(string dynamicID, string contentType, string data, string extraParams,
2279 int timer, int alpha)
2280 {
2281 return m_OSSL_Functions.osSetDynamicTextureDataBlend(dynamicID, contentType, data, extraParams, timer, alpha);
2282 }
2283
2284 public double osTerrainGetHeight(int x, int y)
2285 {
2286 return m_OSSL_Functions.osTerrainGetHeight(x, y);
2287 }
2288
2289 public int osTerrainSetHeight(int x, int y, double val)
2290 {
2291 return m_OSSL_Functions.osTerrainSetHeight(x, y, val);
2292 }
2293
2294 public int osRegionRestart(double seconds)
2295 {
2296 return m_OSSL_Functions.osRegionRestart(seconds);
2297 }
2298
2299 public void osRegionNotice(string msg)
2300 {
2301 m_OSSL_Functions.osRegionNotice(msg);
2302 }
2303
2304 public bool osConsoleCommand(string Command)
2305 {
2306 return m_OSSL_Functions.osConsoleCommand(Command);
2307 }
2308
2309 public void osSetParcelMediaURL(string url)
2310 {
2311 m_OSSL_Functions.osSetParcelMediaURL(url);
2312 }
2313
2314 public void osSetPrimFloatOnWater(int floatYN)
2315 {
2316 m_OSSL_Functions.osSetPrimFloatOnWater(floatYN);
2317 }
2318
2319 // Animation Functions
2320
2321 public void osAvatarPlayAnimation(string avatar, string animation)
2322 {
2323 m_OSSL_Functions.osAvatarPlayAnimation(avatar, animation);
2324 }
2325
2326 public void osAvatarStopAnimation(string avatar, string animation)
2327 {
2328 m_OSSL_Functions.osAvatarStopAnimation(avatar, animation);
2329 }
2330
2331
2332 //Texture Draw functions
2333
2334 public string osMovePen(string drawList, int x, int y)
2335 {
2336 return m_OSSL_Functions.osMovePen(drawList, x, y);
2337 }
2338
2339 public string osDrawLine(string drawList, int startX, int startY, int endX, int endY)
2340 {
2341 return m_OSSL_Functions.osDrawLine(drawList, startX, startY, endX, endY);
2342 }
2343
2344 public string osDrawLine(string drawList, int endX, int endY)
2345 {
2346 return m_OSSL_Functions.osDrawLine(drawList, endX, endY);
2347 }
2348
2349 public string osDrawText(string drawList, string text)
2350 {
2351 return m_OSSL_Functions.osDrawText(drawList, text);
2352 }
2353
2354 public string osDrawEllipse(string drawList, int width, int height)
2355 {
2356 return m_OSSL_Functions.osDrawEllipse(drawList, width, height);
2357 }
2358
2359 public string osDrawRectangle(string drawList, int width, int height)
2360 {
2361 return m_OSSL_Functions.osDrawRectangle(drawList, width, height);
2362 }
2363
2364 public string osDrawFilledRectangle(string drawList, int width, int height)
2365 {
2366 return m_OSSL_Functions.osDrawFilledRectangle(drawList, width, height);
2367 }
2368
2369 public string osSetFontSize(string drawList, int fontSize)
2370 {
2371 return m_OSSL_Functions.osSetFontSize(drawList, fontSize);
2372 }
2373
2374 public string osSetPenSize(string drawList, int penSize)
2375 {
2376 return m_OSSL_Functions.osSetPenSize(drawList, penSize);
2377 }
2378
2379 public string osSetPenColour(string drawList, string colour)
2380 {
2381 return m_OSSL_Functions.osSetPenColour(drawList, colour);
2382 }
2383
2384 public string osDrawImage(string drawList, int width, int height, string imageUrl)
2385 {
2386 return m_OSSL_Functions.osDrawImage(drawList, width, height, imageUrl);
2387 }
2388 public void osSetStateEvents(int events)
2389 {
2390 m_OSSL_Functions.osSetStateEvents(events);
2391 }
2392 }
2393}
diff --git a/OpenSim/Region/ScriptEngine/XEngine/Script/ILSL_ScriptCommands.cs b/OpenSim/Region/ScriptEngine/XEngine/Script/ILSL_ScriptCommands.cs
new file mode 100644
index 0000000..9e8965c
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/XEngine/Script/ILSL_ScriptCommands.cs
@@ -0,0 +1,653 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using OpenSim.Region.Environment.Interfaces;
29
30namespace OpenSim.Region.ScriptEngine.XEngine.Script
31{
32 public interface ILSL_ScriptCommands
33 {
34 // Interface used for loading and executing scripts
35
36 string State { get; set ; }
37
38 void state(string newState);
39
40 ICommander GetCommander(string name);
41
42 void llSay(int channelID, string text);
43 double llSin(double f);
44 double llCos(double f);
45 double llTan(double f);
46 double llAtan2(double x, double y);
47 double llSqrt(double f);
48 double llPow(double fbase, double fexponent);
49 LSL_Types.LSLInteger llAbs(int i);
50 double llFabs(double f);
51 double llFrand(double mag);
52 LSL_Types.LSLInteger llFloor(double f);
53 LSL_Types.LSLInteger llCeil(double f);
54 LSL_Types.LSLInteger llRound(double f);
55 double llVecMag(LSL_Types.Vector3 v);
56 LSL_Types.Vector3 llVecNorm(LSL_Types.Vector3 v);
57 double llVecDist(LSL_Types.Vector3 a, LSL_Types.Vector3 b);
58 LSL_Types.Vector3 llRot2Euler(LSL_Types.Quaternion r);
59 LSL_Types.Quaternion llEuler2Rot(LSL_Types.Vector3 v);
60 LSL_Types.Quaternion llAxes2Rot(LSL_Types.Vector3 fwd, LSL_Types.Vector3 left, LSL_Types.Vector3 up);
61 LSL_Types.Vector3 llRot2Fwd(LSL_Types.Quaternion r);
62 LSL_Types.Vector3 llRot2Left(LSL_Types.Quaternion r);
63 LSL_Types.Vector3 llRot2Up(LSL_Types.Quaternion r);
64 LSL_Types.Quaternion llRotBetween(LSL_Types.Vector3 start, LSL_Types.Vector3 end);
65 void llWhisper(int channelID, string text);
66 //void llSay(int channelID, string text);
67 void llShout(int channelID, string text);
68 void llRegionSay(int channelID, string text);
69 LSL_Types.LSLInteger llListen(int channelID, string name, string ID, string msg);
70 void llListenControl(int number, int active);
71 void llListenRemove(int number);
72 void llSensor(string name, string id, int type, double range, double arc);
73 void llSensorRepeat(string name, string id, int type, double range, double arc, double rate);
74 void llSensorRemove();
75 string llDetectedName(int number);
76 string llDetectedKey(int number);
77 string llDetectedOwner(int number);
78 LSL_Types.LSLInteger llDetectedType(int number);
79 LSL_Types.Vector3 llDetectedPos(int number);
80 LSL_Types.Vector3 llDetectedVel(int number);
81 LSL_Types.Vector3 llDetectedGrab(int number);
82 LSL_Types.Quaternion llDetectedRot(int number);
83 LSL_Types.LSLInteger llDetectedGroup(int number);
84 LSL_Types.LSLInteger llDetectedLinkNumber(int number);
85 void llDie();
86 double llGround(LSL_Types.Vector3 offset);
87 double llCloud(LSL_Types.Vector3 offset);
88 LSL_Types.Vector3 llWind(LSL_Types.Vector3 offset);
89 void llSetStatus(int status, int value);
90 LSL_Types.LSLInteger llGetStatus(int status);
91 void llSetScale(LSL_Types.Vector3 scale);
92 LSL_Types.Vector3 llGetScale();
93 void llSetColor(LSL_Types.Vector3 color, int face);
94 double llGetAlpha(int face);
95 void llSetAlpha(double alpha, int face);
96 LSL_Types.Vector3 llGetColor(int face);
97 void llSetTexture(string texture, int face);
98 void llScaleTexture(double u, double v, int face);
99 void llOffsetTexture(double u, double v, int face);
100 void llRotateTexture(double rotation, int face);
101 string llGetTexture(int face);
102 void llSetPos(LSL_Types.Vector3 pos);
103
104 //wiki: vector llGetPos()
105 LSL_Types.Vector3 llGetPos();
106 //wiki: vector llGetLocalPos()
107 LSL_Types.Vector3 llGetLocalPos();
108 //wiki: llSetRot(rotation rot)
109 void llSetRot(LSL_Types.Quaternion rot);
110 //wiki: rotation llGetRot()
111 LSL_Types.Quaternion llGetRot();
112 //wiki: rotation llGetLocalRot()
113 LSL_Types.Quaternion llGetLocalRot();
114 //wiki: llSetForce(vector force, integer local)
115 void llSetForce(LSL_Types.Vector3 force, int local);
116 //wiki: vector llGetForce()
117 LSL_Types.Vector3 llGetForce();
118 //wiki: integer llTarget(vector position, double range)
119 LSL_Types.LSLInteger llTarget(LSL_Types.Vector3 position, double range);
120 //wiki: llTargetRemove(integer number)
121 void llTargetRemove(int number);
122 //wiki: integer llRotTarget(rotation rot, double error)
123 LSL_Types.LSLInteger llRotTarget(LSL_Types.Quaternion rot, double error);
124 //wiki: integer llRotTargetRemove(integer number)
125 void llRotTargetRemove(int number);
126 //wiki: llMoveToTarget(vector target, double tau)
127 void llMoveToTarget(LSL_Types.Vector3 target, double tau);
128 //wiki: llStopMoveToTarget()
129 void llStopMoveToTarget();
130 //wiki: llApplyImpulse(vector force, integer local)
131 void llApplyImpulse(LSL_Types.Vector3 force, int local);
132 //wiki: llapplyRotationalImpulse(vector force, integer local)
133 void llApplyRotationalImpulse(LSL_Types.Vector3 force, int local);
134 //wiki: llSetTorque(vector torque, integer local)
135 void llSetTorque(LSL_Types.Vector3 torque, int local);
136 //wiki: vector llGetTorque()
137 LSL_Types.Vector3 llGetTorque();
138 //wiki: llSeForceAndTorque(vector force, vector torque, integer local)
139 void llSetForceAndTorque(LSL_Types.Vector3 force, LSL_Types.Vector3 torque, int local);
140 //wiki: vector llGetVel()
141 LSL_Types.Vector3 llGetVel();
142 //wiki: vector llGetAccel()
143 LSL_Types.Vector3 llGetAccel();
144 //wiki: vector llGetOmega()
145 LSL_Types.Vector3 llGetOmega();
146 //wiki: double llGetTimeOfDay()
147 double llGetTimeOfDay();
148 //wiki: double llGetWallclock()
149 double llGetWallclock();
150 //wiki: double llGetTime()
151 double llGetTime();
152 //wiki: llResetTime()
153 void llResetTime();
154 //wiki: double llGetAndResetTime()
155 double llGetAndResetTime();
156 //wiki (deprecated) llSound(string sound, double volume, integer queue, integer loop)
157 void llSound();
158 //wiki: llPlaySound(string sound, double volume)
159 void llPlaySound(string sound, double volume);
160 //wiki: llLoopSound(string sound, double volume)
161 void llLoopSound(string sound, double volume);
162 //wiki: llLoopSoundMaster(string sound, double volume)
163 void llLoopSoundMaster(string sound, double volume);
164 //wiki: llLoopSoundSlave(string sound, double volume)
165 void llLoopSoundSlave(string sound, double volume);
166 //wiki llPlaySoundSlave(string sound, double volume)
167 void llPlaySoundSlave(string sound, double volume);
168 //wiki: llTriggerSound(string sound, double volume)
169 void llTriggerSound(string sound, double volume);
170 //wiki: llStopSound()
171 void llStopSound();
172 //wiki: llPreloadSound(string sound)
173 void llPreloadSound(string sound);
174 //wiki: string llGetSubString(string src, integer start, integer end)
175 string llGetSubString(string src, int start, int end);
176 //wiki: string llDeleteSubString(string src, integer start, integer end)
177 string llDeleteSubString(string src, int start, int end);
178 //wiki string llInsertString(string dst, integer position, string src)
179 string llInsertString(string dst, int position, string src);
180 //wiki: string llToUpper(string source)
181 string llToUpper(string source);
182 //wiki: string llToLower(string source)
183 string llToLower(string source);
184 //wiki: integer llGiveMoney(key destination, integer amount)
185 LSL_Types.LSLInteger llGiveMoney(string destination, int amount);
186 //wiki: (deprecated)
187 void llMakeExplosion();
188 //wiki: (deprecated)
189 void llMakeFountain();
190 //wiki: (deprecated)
191 void llMakeSmoke();
192 //wiki: (deprecated)
193 void llMakeFire();
194 //wiki: llRezObject(string inventory, vector pos, vector rel, rotation rot, integer param)
195 void llRezObject(string inventory, LSL_Types.Vector3 pos, LSL_Types.Vector3 vel, LSL_Types.Quaternion rot, int param);
196 //wiki: llLookAt(vector target, double strength, double damping)
197 void llLookAt(LSL_Types.Vector3 target, double strength, double damping);
198 //wiki: llStopLookAt()
199 void llStopLookAt();
200 //wiki: llSetTimerEvent(double sec)
201 void llSetTimerEvent(double sec);
202 //wiki: llSleep(double sec)
203 void llSleep(double sec);
204 //wiki: double llGetMass()
205 double llGetMass();
206 //wiki: llCollisionFilter(string name, key id, integer accept)
207 void llCollisionFilter(string name, string id, int accept);
208 //wiki: llTakeControls(integer controls, integer accept, integer pass_on)
209 void llTakeControls(int controls, int accept, int pass_on);
210 //wiki: llReleaseControls()
211 void llReleaseControls();
212 //wiki: llAttachToAvatar(integer attachment)
213 void llAttachToAvatar(int attachment);
214 //wiki: llDetachFromAvatar()
215 void llDetachFromAvatar();
216 //wiki: (deprecated) llTakeCamera()
217 void llTakeCamera();
218 //wiki: (deprecated) llReleaseCamera()
219 void llReleaseCamera();
220 //wiki: key llGetOwner()
221 string llGetOwner();
222 //wiki: llInstantMessage(key user, string message)
223 void llInstantMessage(string user, string message);
224 //wiki: llEmail(string address, string subject, string message)
225 void llEmail(string address, string subject, string message);
226 //wiki: llGetNextEmail(string address, string subject)
227 void llGetNextEmail(string address, string subject);
228 //wiki: key llGetKey()
229 string llGetKey();
230 //wiki: llSetBuoyancy(double buoyancy)
231 void llSetBuoyancy(double buoyancy);
232 //wiki: llSetHoverHeight(double height, integer water, double tau)
233 void llSetHoverHeight(double height, int water, double tau);
234 //wiki: llStopHover
235 void llStopHover();
236 //wiki: llMinEventDelay(double delay)
237 void llMinEventDelay(double delay);
238 //wiki: (deprecated) llSoundPreload()
239 void llSoundPreload();
240 //wiki: llRotLookAt(rotation target, double strength, double damping)
241 void llRotLookAt(LSL_Types.Quaternion target, double strength, double damping);
242 //wiki: integer llStringLength(string str)
243 LSL_Types.LSLInteger llStringLength(string str);
244 //wiki: llStartAnimation(string anim)
245 void llStartAnimation(string anim);
246 //wiki: llStopAnimation(string anim)
247 void llStopAnimation(string anim);
248 //wiki: (deprecated) llPointAt
249 void llPointAt();
250 //wiki: (deprecated) llStopPointAt
251 void llStopPointAt();
252 //wiki: llTargetOmega(vector axis, double spinrate, double gain)
253 void llTargetOmega(LSL_Types.Vector3 axis, double spinrate, double gain);
254 //wiki: integer llGetStartParameter()
255 LSL_Types.LSLInteger llGetStartParameter();
256 //wiki: llGodLikeRezObject(key inventory, vector pos)
257 void llGodLikeRezObject(string inventory, LSL_Types.Vector3 pos);
258 //wiki: llRequestPermissions(key agent, integer perm)
259 void llRequestPermissions(string agent, int perm);
260 //wiki: key llGetPermissionsKey()
261 string llGetPermissionsKey();
262 //wiki: integer llGetPermissions()
263 LSL_Types.LSLInteger llGetPermissions();
264 //wiki integer llGetLinkNumber()
265 LSL_Types.LSLInteger llGetLinkNumber();
266 //wiki: llSetLinkColor(integer linknumber, vector color, integer face)
267 void llSetLinkColor(int linknumber, LSL_Types.Vector3 color, int face);
268 //wiki: llCreateLink(key target, integer parent)
269 void llCreateLink(string target, int parent);
270 //wiki: llBreakLink(integer linknum)
271 void llBreakLink(int linknum);
272 //wiki: llBreakAllLinks()
273 void llBreakAllLinks();
274 //wiki: key llGetLinkKey(integer linknum)
275 string llGetLinkKey(int linknum);
276 //wiki: llGetLinkName(integer linknum)
277 string llGetLinkName(int linknum);
278 //wiki: integer llGetInventoryNumber(integer type)
279 LSL_Types.LSLInteger llGetInventoryNumber(int type);
280 //wiki: string llGetInventoryName(integer type, integer number)
281 string llGetInventoryName(int type, int number);
282 //wiki: llSetScriptState(string name, integer run)
283 void llSetScriptState(string name, int run);
284 //wiki: double llGetEnergy()
285 double llGetEnergy();
286 //wiki: llGiveInventory(key destination, string inventory)
287 void llGiveInventory(string destination, string inventory);
288 //wiki: llRemoveInventory(string item)
289 void llRemoveInventory(string item);
290 //wiki: llSetText(string text, vector color, double alpha)
291 void llSetText(string text, LSL_Types.Vector3 color, double alpha);
292 //wiki: double llWater(vector offset)
293 double llWater(LSL_Types.Vector3 offset);
294 //wiki: llPassTouches(integer pass)
295 void llPassTouches(int pass);
296 //wiki: key llRequestAgentData(key id, integer data)
297 string llRequestAgentData(string id, int data);
298 //wiki: key llRequestInventoryData(string name)
299 string llRequestInventoryData(string name);
300 //wiki: llSetDamage(double damage)
301 void llSetDamage(double damage);
302 //wiki: llTeleportAgentHome(key agent)
303 void llTeleportAgentHome(string agent);
304 //wiki: llModifyLand(integer action, integer brush)
305 void llModifyLand(int action, int brush);
306 //wiki: llCollisionSound(string impact_sound, double impact_volume)
307 void llCollisionSound(string impact_sound, double impact_volume);
308 //wiki: llCollisionSprite(string impact_sprite)
309 void llCollisionSprite(string impact_sprite);
310 //wiki: string llGetAnimation(key id)
311 string llGetAnimation(string id);
312 //wiki: llResetScript()
313 void llResetScript();
314 //wiki: llMessageLinked(integer linknum, integer num, string str, key id)
315 void llMessageLinked(int linknum, int num, string str, string id);
316 //wiki: llPushObject(key target, vector impulse, vector ang_impulse, integer local)
317 void llPushObject(string target, LSL_Types.Vector3 impulse, LSL_Types.Vector3 ang_impulse, int local);
318 //wiki: llPassCollisions(integer pass)
319 void llPassCollisions(int pass);
320 //wiki: string llGetScriptName()
321 string llGetScriptName();
322 //wiki: integer llGetNumberOfSides()
323 LSL_Types.LSLInteger llGetNumberOfSides();
324 //wiki: rotation llAxisAngle2Rot(vector axis, double angle)
325 LSL_Types.Quaternion llAxisAngle2Rot(LSL_Types.Vector3 axis, double angle);
326 //wiki: vector llRot2Axis(rotation rot)
327 LSL_Types.Vector3 llRot2Axis(LSL_Types.Quaternion rot);
328 //wiki: double llRot2Angle(rotation rot);
329 double llRot2Angle(LSL_Types.Quaternion rot);
330 //wiki: double llAcos(double val)
331 double llAcos(double val);
332 //wiki: double llAsin(double val)
333 double llAsin(double val);
334 //wiki: double llAngleBetween(rotation a, rotation b)
335 double llAngleBetween(LSL_Types.Quaternion a, LSL_Types.Quaternion b);
336 //wiki: string llGetInventoryKey(string name)
337 string llGetInventoryKey(string name);
338 //wiki: llAllowInventoryDrop(integer add)
339 void llAllowInventoryDrop(int add);
340 //wiki: vector llGetSunDirection()
341 LSL_Types.Vector3 llGetSunDirection();
342 //wiki: vector llGetTextureOffset(integer face)
343 LSL_Types.Vector3 llGetTextureOffset(int face);
344 //wiki: vector llGetTextureScale(integer side)
345 LSL_Types.Vector3 llGetTextureScale(int side);
346 //wiki: double llGetTextureRot(integer side)
347 double llGetTextureRot(int side);
348 //wiki: integer llSubStringIndex(string source, string pattern)
349 LSL_Types.LSLInteger llSubStringIndex(string source, string pattern);
350 //wiki: key llGetOwnerKey(key id)
351 string llGetOwnerKey(string id);
352 //wiki: vector llGetCenterOfMass()
353 LSL_Types.Vector3 llGetCenterOfMass();
354 //wiki: list llListSort(list src, integer stride, integer ascending)
355 LSL_Types.list llListSort(LSL_Types.list src, int stride, int ascending);
356 //integer llGetListLength(list src)
357 LSL_Types.LSLInteger llGetListLength(LSL_Types.list src);
358 //wiki: integer llList2Integer(list src, integer index)
359 LSL_Types.LSLInteger llList2Integer(LSL_Types.list src, int index);
360 //wiki: double llList2double(list src, integer index)
361 double llList2Float(LSL_Types.list src, int index);
362 //wiki: string llList2String(list src, integer index)
363 string llList2String(LSL_Types.list src, int index);
364 //wiki: key llList2Key(list src, integer index)
365 string llList2Key(LSL_Types.list src, int index);
366 //wiki: vector llList2Vector(list src, integer index)
367 LSL_Types.Vector3 llList2Vector(LSL_Types.list src, int index);
368 //wiki rotation llList2Rot(list src, integer index)
369 LSL_Types.Quaternion llList2Rot(LSL_Types.list src, int index);
370 //wiki: list llList2List(list src, integer start, integer end)
371 LSL_Types.list llList2List(LSL_Types.list src, int start, int end);
372 //wiki: llDeleteSubList(list src, integer start, integer end)
373 LSL_Types.list llDeleteSubList(LSL_Types.list src, int start, int end);
374 //wiki: integer llGetListEntryType(list src, integer index)
375 LSL_Types.LSLInteger llGetListEntryType(LSL_Types.list src, int index);
376 //wiki: string llList2CSV(list src)
377 string llList2CSV(LSL_Types.list src);
378 //wiki: list llCSV2List(string src)
379 LSL_Types.list llCSV2List(string src);
380 //wiki: list llListRandomize(list src, integer stride)
381 LSL_Types.list llListRandomize(LSL_Types.list src, int stride);
382 //wiki: list llList2ListStrided(list src, integer start, integer end, integer stride)
383 LSL_Types.list llList2ListStrided(LSL_Types.list src, int start, int end, int stride);
384 //wiki: vector llGetRegionCorner()
385 LSL_Types.Vector3 llGetRegionCorner();
386 //wiki: list llListInsertList(list dest, list src, integer start)
387 LSL_Types.list llListInsertList(LSL_Types.list dest, LSL_Types.list src, int start);
388 //wiki: integer llListFindList(list src, list test)
389 LSL_Types.LSLInteger llListFindList(LSL_Types.list src, LSL_Types.list test);
390 //wiki: string llGetObjectName()
391 string llGetObjectName();
392 //wiki: llSetObjectName(string name)
393 void llSetObjectName(string name);
394 //wiki: string llGetDate()
395 string llGetDate();
396 //wiki: integer llEdgeOfWorld(vector pos, vector dir)
397 LSL_Types.LSLInteger llEdgeOfWorld(LSL_Types.Vector3 pos, LSL_Types.Vector3 dir);
398 //wiki: integer llGetAgentInfo(key id)
399 LSL_Types.LSLInteger llGetAgentInfo(string id);
400 //wiki: llAdjustSoundVolume(double volume)
401 void llAdjustSoundVolume(double volume);
402 //wiki: llSetSoundQueueing(integer queue)
403 void llSetSoundQueueing(int queue);
404 //wiki: llSetSoundRadius(double radius)
405 void llSetSoundRadius(double radius);
406 //wiki: string llKey2Name(key id)
407 string llKey2Name(string id);
408 //wiki: llSetTextureAnim(integer mode, integer face, integer sizex, integer sizey, double start, double length, double rate)
409 void llSetTextureAnim(int mode, int face, int sizex, int sizey, double start, double length, double rate);
410 //wiki: llTriggerSoundLimited(string sound, double volume, vector top_north_east, vector bottom_south_west)
411 void llTriggerSoundLimited(string sound, double volume, LSL_Types.Vector3 top_north_east,
412 LSL_Types.Vector3 bottom_south_west);
413
414 //wiki: llEjectFromLand(key pest)
415 void llEjectFromLand(string pest);
416 LSL_Types.list llParseString2List(string str, LSL_Types.list separators, LSL_Types.list spacers);
417 //wiki: integer llOverMyLand(key id)
418 LSL_Types.LSLInteger llOverMyLand(string id);
419 //wiki: key llGetLandOwnerAt(vector pos)
420 string llGetLandOwnerAt(LSL_Types.Vector3 pos);
421 //wiki: key llGetNotecardLine(string name, integer line)
422 string llGetNotecardLine(string name, int line);
423 //wiki: vector llGetAgentSize(key id)
424 LSL_Types.Vector3 llGetAgentSize(string id);
425 //wiki: integer llSameGroup(key agent)
426 LSL_Types.LSLInteger llSameGroup(string agent);
427 //wiki: llUnSit(key id)
428 void llUnSit(string id);
429 //wiki: vector llGroundSlope(vector offset)
430 LSL_Types.Vector3 llGroundSlope(LSL_Types.Vector3 offset);
431 //wiki: vector llGroundNormal(vector offset)
432 LSL_Types.Vector3 llGroundNormal(LSL_Types.Vector3 offset);
433 //wiki: vector llGroundContour(vector offset)
434 LSL_Types.Vector3 llGroundContour(LSL_Types.Vector3 offset);
435 //wiki: integer llGetAttached()
436 LSL_Types.LSLInteger llGetAttached();
437 //wiki: integer llGetFreeMemory()
438 LSL_Types.LSLInteger llGetFreeMemory();
439 //wiki: string llGetRegionName()
440 string llGetRegionName();
441 //wiki: double llGetRegionTimeDilation()
442 double llGetRegionTimeDilation();
443 //wiki: double llGetRegionFPS()
444 double llGetRegionFPS();
445 //wiki: llParticleSystem(List<Object> rules
446 void llParticleSystem(LSL_Types.list rules);
447 //wiki: llGroundRepel(double height, integer water, double tau)
448 void llGroundRepel(double height, int water, double tau);
449 //wiki: llGiveInventoryList(string destination, string category, LSL_Types.list inventory)
450 void llGiveInventoryList(string destination, string category, LSL_Types.list inventory);
451 //wiki: llSetVehicleType(integer type)
452 void llSetVehicleType(int type);
453 //wiki: llSetVehicledoubleParam(integer param, double value)
454 void llSetVehicledoubleParam(int param, double value);
455 // wiki: llSetVehicleFloatParam(integer param, float value)
456 void llSetVehicleFloatParam(int param, float value);
457 //wiki: llSetVehicleVectorParam(integer param, vector vec)
458 void llSetVehicleVectorParam(int param, LSL_Types.Vector3 vec);
459 //wiki: llSetVehicleRotationParam(integer param, rotation rot)
460 void llSetVehicleRotationParam(int param, LSL_Types.Quaternion rot);
461 //wiki: llSetVehicleFlags(integer flags)
462 void llSetVehicleFlags(int flags);
463 //wiki: llRemoveVehicleFlags(integer flags)
464 void llRemoveVehicleFlags(int flags);
465 //wiki: llSitTarget(vector offset, rotation rot)
466 void llSitTarget(LSL_Types.Vector3 offset, LSL_Types.Quaternion rot);
467 //wiki key llAvatarOnSitTarget()
468 string llAvatarOnSitTarget();
469 //wiki: llAddToLandPassList(key avatar, double hours)
470 void llAddToLandPassList(string avatar, double hours);
471 //wiki: llSetTouchText(string text)
472 void llSetTouchText(string text);
473 //wiki: llSetSitText(string text)
474 void llSetSitText(string text);
475 //wiki: llSetCameraEyeOffset(vector offset)
476 void llSetCameraEyeOffset(LSL_Types.Vector3 offset);
477 //wiki: llSeteCameraAtOffset(vector offset)
478 void llSetCameraAtOffset(LSL_Types.Vector3 offset);
479 //
480 string llDumpList2String(LSL_Types.list src, string seperator);
481 //wiki: integer llScriptDanger(vector pos)
482 LSL_Types.LSLInteger llScriptDanger(LSL_Types.Vector3 pos);
483 //wiki: llDialog(key avatar, string message, list buttons, integer chat_channel)
484 void llDialog(string avatar, string message, LSL_Types.list buttons, int chat_channel);
485 //wiki: llVolumeDetect(integer detect)
486 void llVolumeDetect(int detect);
487 //wiki: llResetOtherScript(string name)
488 void llResetOtherScript(string name);
489 //wiki: integer llGetScriptState(string name)
490 LSL_Types.LSLInteger llGetScriptState(string name);
491 //wiki: (deprecated)
492 void llRemoteLoadScript();
493 //wiki: llSetRemoteScriptAccessPin(integer pin)
494 void llSetRemoteScriptAccessPin(int pin);
495 //wiki: llRemoteLoadScriptPin(key target, string name, integer pin, integer running, integer start_param)
496 void llRemoteLoadScriptPin(string target, string name, int pin, int running, int start_param);
497 //wiki: llOpenRemoteDataChannel()
498 void llOpenRemoteDataChannel();
499 //wiki: key llSendRemoteData(key channel, string dest, integer idata, string sdata)
500 string llSendRemoteData(string channel, string dest, int idata, string sdata);
501 //wiki: llRemoteDataReply(key channel, key message_id, string sdata, integer idata)
502 void llRemoteDataReply(string channel, string message_id, string sdata, int idata);
503 //wiki: llCloseRemoteDataChannel(key channel)
504 void llCloseRemoteDataChannel(string channel);
505 //wiki: string llMD5String(string src, integer nonce)
506 string llMD5String(string src, int nonce);
507 //wiki: llSetPrimitiveParams(list rules)
508 void llSetPrimitiveParams(LSL_Types.list rules);
509 //wiki: llSetLinkPrimitiveParams(integer linknumber, list rules)
510 void llSetLinkPrimitiveParams(int linknumber, LSL_Types.list rules);
511 //wiki: string llStringToBase64(string str)
512 string llStringToBase64(string str);
513 //wiki: string llBase64ToString(string str)
514 string llBase64ToString(string str);
515 //wiki: (deprecated)
516 void llXorBase64Strings();
517 //wiki: llRemoteDataSetRegion()
518 void llRemoteDataSetRegion();
519 //wiki: double llLog10(double val)
520 double llLog10(double val);
521 //wiki: double llLog(double val)
522 double llLog(double val);
523 //wiki: list llGetAnimationList(key id)
524 LSL_Types.list llGetAnimationList(string id);
525 //wiki: llSetParcelMusicURL(string url)
526 void llSetParcelMusicURL(string url);
527 //wiki: vector llGetRootPosition()
528 LSL_Types.Vector3 llGetRootPosition();
529 //wiki: rotation llGetRootRotation()
530 LSL_Types.Quaternion llGetRootRotation();
531 //wiki: string llGetObjectDesc()
532 string llGetObjectDesc();
533 //wiki: llSetObjectDesc(string desc)
534 void llSetObjectDesc(string desc);
535 //wiki: key llGetCreator()
536 string llGetCreator();
537 //wiki: string llGetTimestamp()
538 string llGetTimestamp();
539 //wiki: llSetLinkAlpha(integer linknumber, double alpha, integer face)
540 void llSetLinkAlpha(int linknumber, double alpha, int face);
541 //wiki: integer llGetNumberOfPrims()
542 LSL_Types.LSLInteger llGetNumberOfPrims();
543 //wiki: key llGetNumberOfNotecardLines(string name)
544 string llGetNumberOfNotecardLines(string name);
545 //wiki: list llGetBoundingBox(key object)
546 LSL_Types.list llGetBoundingBox(string obj);
547 //wiki: vector llGetGeometricCenter()
548 LSL_Types.Vector3 llGetGeometricCenter();
549 //wiki: list llGetPrimitiveParams(list rules)
550 LSL_Types.list llGetPrimitiveParams(LSL_Types.list rules);
551 //wiki: string llIntegerToBase64(integer number)
552 string llIntegerToBase64(int number);
553 //wiki integer llBase64ToInteger(string str)
554 LSL_Types.LSLInteger llBase64ToInteger(string str);
555 //wiki: double llGetGMTclock()
556 double llGetGMTclock();
557 //wiki: string llGetSimulatorHostname()
558 string llGetSimulatorHostname();
559 //llSetLocalRot(rotation rot)
560 void llSetLocalRot(LSL_Types.Quaternion rot);
561 //wiki: list llParseStringKeepNulls(string src, list separators, list spacers)
562 LSL_Types.list llParseStringKeepNulls(string src, LSL_Types.list seperators, LSL_Types.list spacers);
563 //wiki: llRezAtRoot(string inventory, vector position, vector velocity, rotation rot, integer param)
564 void llRezAtRoot(string inventory, LSL_Types.Vector3 position, LSL_Types.Vector3 velocity,
565 LSL_Types.Quaternion rot, int param);
566
567 //wiki: integer llGetObjectPermMask(integer mask)
568 LSL_Types.LSLInteger llGetObjectPermMask(int mask);
569 //wiki: llSetObjectPermMask(integer mask, integer value)
570 void llSetObjectPermMask(int mask, int value);
571 //wiki integer llGetInventoryPermMask(string item, integer mask)
572 LSL_Types.LSLInteger llGetInventoryPermMask(string item, int mask);
573 //wiki: llSetInventoryPermMask(string item, integer mask, integer value)
574 void llSetInventoryPermMask(string item, int mask, int value);
575 //wiki: key llGetInventoryCreator(string item)
576 string llGetInventoryCreator(string item);
577 //wiki: llOwnerSay(string msg)
578 void llOwnerSay(string msg);
579 //wiki: key llRequestSimulatorData(string simulator, integer data)
580 string llRequestSimulatorData(string simulator, int data);
581 //wiki: llForceMouselook(integer mouselook)
582 void llForceMouselook(int mouselook);
583 //wiki: double llGetObjectMass(key id)
584 double llGetObjectMass(string id);
585 LSL_Types.list llListReplaceList(LSL_Types.list dest, LSL_Types.list src, int start, int end);
586 //wiki: llLoadURL(key avatar_id, string message, string url)
587 void llLoadURL(string avatar_id, string message, string url);
588 //wiki: llParcelMediaCommandList(list commandList)
589 void llParcelMediaCommandList(LSL_Types.list commandList);
590 void llParcelMediaQuery();
591 //wiki integer llModPow(integer a, integer b, integer c)
592 LSL_Types.LSLInteger llModPow(int a, int b, int c);
593 //wiki: integer llGetInventoryType(string name)
594 LSL_Types.LSLInteger llGetInventoryType(string name);
595 //wiki: llSetPayPrice(integer price, list quick_pay_buttons)
596 void llSetPayPrice(int price, LSL_Types.list quick_pay_buttons);
597 //wiki: vector llGetCameraPos()
598 LSL_Types.Vector3 llGetCameraPos();
599 //wiki rotation llGetCameraRot()
600 LSL_Types.Quaternion llGetCameraRot();
601 //wiki: (deprecated)
602 void llSetPrimURL();
603 //wiki: (deprecated)
604 void llRefreshPrimURL();
605 //wiki: string llEscapeURL(string url)
606 string llEscapeURL(string url);
607 //wiki: string llUnescapeURL(string url)
608 string llUnescapeURL(string url);
609 //wiki: llMapDestination(string simname, vector pos, vector look_at)
610 void llMapDestination(string simname, LSL_Types.Vector3 pos, LSL_Types.Vector3 look_at);
611 //wiki: llAddToLandBanList(key avatar, double hours)
612 void llAddToLandBanList(string avatar, double hours);
613 //wiki: llRemoveFromLandPassList(key avatar)
614 void llRemoveFromLandPassList(string avatar);
615 //wiki: llRemoveFromLandBanList(key avatar)
616 void llRemoveFromLandBanList(string avatar);
617 //wiki: llSetCameraParams(list rules)
618 void llSetCameraParams(LSL_Types.list rules);
619 //wiki: llClearCameraParams()
620 void llClearCameraParams();
621 //wiki: double llListStatistics(integer operation, list src)
622 double llListStatistics(int operation, LSL_Types.list src);
623 //wiki: integer llGetUnixTime()
624 LSL_Types.LSLInteger llGetUnixTime();
625 //wiki: integer llGetParcelFlags(vector pos)
626 LSL_Types.LSLInteger llGetParcelFlags(LSL_Types.Vector3 pos);
627 //wiki: integer llGetRegionFlags()
628 LSL_Types.LSLInteger llGetRegionFlags();
629 //wiki: string llXorBase64StringsCorrect(string str1, string str2)
630 string llXorBase64StringsCorrect(string str1, string str2);
631 string llHTTPRequest(string url, LSL_Types.list parameters, string body);
632 //wiki: llResetLandBanList()
633 void llResetLandBanList();
634 //wiki: llResetLandPassList()
635 void llResetLandPassList();
636 //wiki: integer llGetParcelPrimCount(vector pos, integer category, integer sim_wide)
637 LSL_Types.LSLInteger llGetParcelPrimCount(LSL_Types.Vector3 pos, int category, int sim_wide);
638 //wiki: list llGetParcelPrimOwners(vector pos)
639 LSL_Types.list llGetParcelPrimOwners(LSL_Types.Vector3 pos);
640 //wiki: integer llGetObjectPrimCount(key object_id)
641 LSL_Types.LSLInteger llGetObjectPrimCount(string object_id);
642 //wiki: integer llGetParcelMaxPrims(vector pos, integer sim_wide)
643 LSL_Types.LSLInteger llGetParcelMaxPrims(LSL_Types.Vector3 pos, int sim_wide);
644 //wiki: llGetParcelDetails(vector pos, list params)
645 LSL_Types.list llGetParcelDetails(LSL_Types.Vector3 pos, LSL_Types.list param);
646 //wiki: llSetLinkTexture(integer linknumber, string texture, integer face)
647 void llSetLinkTexture(int linknumber, string texture, int face);
648 //wiki: string llStringTrim(string src, int type)
649 string llStringTrim(string src, int type);
650 //wiki: LSL_Types.list llGetObjectDetails(string id, LSL_Types.list args)
651 LSL_Types.list llGetObjectDetails(string id, LSL_Types.list args);
652 }
653}
diff --git a/OpenSim/Region/ScriptEngine/XEngine/Script/IOSSL_ScriptCommands.cs b/OpenSim/Region/ScriptEngine/XEngine/Script/IOSSL_ScriptCommands.cs
new file mode 100644
index 0000000..82d4673
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/XEngine/Script/IOSSL_ScriptCommands.cs
@@ -0,0 +1,68 @@
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
28namespace OpenSim.Region.ScriptEngine.XEngine.Script
29{
30 public interface IOSSL_ScriptCommands
31 {
32 //OpenSim functions
33 string osSetDynamicTextureURL(string dynamicID, string contentType, string url, string extraParams, int timer);
34 string osSetDynamicTextureURLBlend(string dynamicID, string contentType, string url, string extraParams,
35 int timer, int alpha);
36 string osSetDynamicTextureData(string dynamicID, string contentType, string data, string extraParams, int timer);
37 string osSetDynamicTextureDataBlend(string dynamicID, string contentType, string data, string extraParams,
38 int timer, int alpha);
39 double osTerrainGetHeight(int x, int y);
40 int osTerrainSetHeight(int x, int y, double val);
41 int osRegionRestart(double seconds);
42 void osRegionNotice(string msg);
43 bool osConsoleCommand(string Command);
44 void osSetParcelMediaURL(string url);
45 void osSetPrimFloatOnWater(int floatYN);
46
47 // Animation commands
48 void osAvatarPlayAnimation(string avatar, string animation);
49 void osAvatarStopAnimation(string avatar, string animation);
50
51 //texture draw functions
52 string osMovePen(string drawList, int x, int y);
53 string osDrawLine(string drawList, int startX, int startY, int endX, int endY);
54 string osDrawLine(string drawList, int endX, int endY);
55 string osDrawText(string drawList, string text);
56 string osDrawEllipse(string drawList, int width, int height);
57 string osDrawRectangle(string drawList, int width, int height);
58 string osDrawFilledRectangle(string drawList, int width, int height);
59 string osSetFontSize(string drawList, int fontSize);
60 string osSetPenSize(string drawList, int penSize);
61 string osSetPenColour(string drawList, string colour);
62 string osDrawImage(string drawList, int width, int height, string imageUrl);
63 void osSetStateEvents(int events);
64
65 double osList2Double(LSL_Types.list src, int index);
66 void osSetRegionWaterHeight(double height);
67 }
68}
diff --git a/OpenSim/Region/ScriptEngine/XEngine/Script/IScript.cs b/OpenSim/Region/ScriptEngine/XEngine/Script/IScript.cs
new file mode 100644
index 0000000..e5d0b33
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/XEngine/Script/IScript.cs
@@ -0,0 +1,46 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System.Reflection;
29using System;
30using System.Collections;
31using System.Collections.Generic;
32using OpenSim.Region.Environment.Interfaces;
33
34namespace OpenSim.Region.ScriptEngine.XEngine.Script
35{
36 public interface IScript
37 {
38 Type Start(ILSL_ScriptCommands lsl, IOSSL_ScriptCommands ossl);
39
40 Dictionary<string, object> GetVars();
41 void SetVars(Dictionary<string, object> vars);
42 void ResetVars();
43
44 string State { get; set; }
45 }
46}
diff --git a/OpenSim/Region/ScriptEngine/XEngine/Script/LSL_Types.cs b/OpenSim/Region/ScriptEngine/XEngine/Script/LSL_Types.cs
new file mode 100644
index 0000000..2d5d2b8
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/XEngine/Script/LSL_Types.cs
@@ -0,0 +1,1411 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Text.RegularExpressions;
31
32namespace OpenSim.Region.ScriptEngine.XEngine.Script
33{
34 [Serializable]
35 public partial class LSL_Types
36 {
37 // Types are kept is separate .dll to avoid having to add whatever .dll it is in it to script AppDomain
38
39 [Serializable]
40 public struct Vector3
41 {
42 public double x;
43 public double y;
44 public double z;
45
46 #region Constructors
47
48 public Vector3(Vector3 vector)
49 {
50 x = (float)vector.x;
51 y = (float)vector.y;
52 z = (float)vector.z;
53 }
54
55 public Vector3(double X, double Y, double Z)
56 {
57 x = X;
58 y = Y;
59 z = Z;
60 }
61
62 public Vector3(string str)
63 {
64 str = str.Replace('<', ' ');
65 str = str.Replace('>', ' ');
66 string[] tmps = str.Split(new Char[] { ',', '<', '>' });
67 if (tmps.Length < 3)
68 {
69 x=y=z=0;
70 return;
71 }
72 bool res;
73 res = Double.TryParse(tmps[0], out x);
74 res = res & Double.TryParse(tmps[1], out y);
75 res = res & Double.TryParse(tmps[2], out z);
76 }
77
78 #endregion
79
80 #region Overriders
81
82 public override string ToString()
83 {
84 string s=String.Format("<{0:0.000000},{1:0.000000},{2:0.000000}>", x, y, z);
85 return s;
86 }
87
88 public static explicit operator LSLString(Vector3 vec)
89 {
90 string s=String.Format("<{0:0.000000},{1:0.000000},{2:0.000000}>", vec.x, vec.y, vec.z);
91 return new LSLString(s);
92 }
93
94 public static explicit operator string(Vector3 vec)
95 {
96 string s=String.Format("<{0:0.000000},{1:0.000000},{2:0.000000}>", vec.x, vec.y, vec.z);
97 return s;
98 }
99
100 public static explicit operator Vector3(string s)
101 {
102 return new Vector3(s);
103 }
104
105 public static bool operator ==(Vector3 lhs, Vector3 rhs)
106 {
107 return (lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z);
108 }
109
110 public static bool operator !=(Vector3 lhs, Vector3 rhs)
111 {
112 return !(lhs == rhs);
113 }
114
115 public override int GetHashCode()
116 {
117 return (x.GetHashCode() ^ y.GetHashCode() ^ z.GetHashCode());
118 }
119
120 public override bool Equals(object o)
121 {
122 if (!(o is Vector3)) return false;
123
124 Vector3 vector = (Vector3)o;
125
126 return (x == vector.x && x == vector.x && z == vector.z);
127 }
128
129 #endregion
130
131 #region Vector & Vector Math
132
133 // Vector-Vector Math
134 public static Vector3 operator +(Vector3 lhs, Vector3 rhs)
135 {
136 return new Vector3(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z);
137 }
138
139 public static Vector3 operator -(Vector3 lhs, Vector3 rhs)
140 {
141 return new Vector3(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z);
142 }
143
144 public static Vector3 operator *(Vector3 lhs, Vector3 rhs)
145 {
146 return new Vector3(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z);
147 }
148
149 public static Vector3 operator %(Vector3 v1, Vector3 v2)
150 {
151 //Cross product
152 Vector3 tv;
153 tv.x = (v1.y * v2.z) - (v1.z * v2.y);
154 tv.y = (v1.z * v2.x) - (v1.x * v2.z);
155 tv.z = (v1.x * v2.y) - (v1.y * v2.x);
156 return tv;
157 }
158
159 #endregion
160
161 #region Vector & Float Math
162
163 // Vector-Float and Float-Vector Math
164 public static Vector3 operator *(Vector3 vec, float val)
165 {
166 return new Vector3(vec.x * val, vec.y * val, vec.z * val);
167 }
168
169 public static Vector3 operator *(float val, Vector3 vec)
170 {
171 return new Vector3(vec.x * val, vec.y * val, vec.z * val);
172 }
173
174 public static Vector3 operator /(Vector3 v, float f)
175 {
176 v.x = v.x / f;
177 v.y = v.y / f;
178 v.z = v.z / f;
179 return v;
180 }
181
182 #endregion
183
184 #region Vector & Double Math
185
186 public static Vector3 operator *(Vector3 vec, double val)
187 {
188 return new Vector3(vec.x * val, vec.y * val, vec.z * val);
189 }
190
191 public static Vector3 operator *(double val, Vector3 vec)
192 {
193 return new Vector3(vec.x * val, vec.y * val, vec.z * val);
194 }
195
196 public static Vector3 operator /(Vector3 v, double f)
197 {
198 v.x = v.x / f;
199 v.y = v.y / f;
200 v.z = v.z / f;
201 return v;
202 }
203
204 #endregion
205
206 #region Vector & Rotation Math
207
208 // Vector-Rotation Math
209 public static Vector3 operator *(Vector3 v, Quaternion r)
210 {
211 Quaternion vq = new Quaternion(v.x, v.y, v.z, 0);
212 Quaternion nq = new Quaternion(-r.x, -r.y, -r.z, r.s);
213
214 // adapted for operator * computing "b * a"
215 Quaternion result = nq * (vq * r);
216
217 return new Vector3(result.x, result.y, result.z);
218 }
219
220 public static Vector3 operator /(Vector3 v, Quaternion r)
221 {
222 r.s = -r.s;
223 return v * r;
224 }
225
226 #endregion
227
228 #region Static Helper Functions
229
230 public static double Dot(Vector3 v1, Vector3 v2)
231 {
232 return (v1.x * v2.x) + (v1.y * v2.y) + (v1.z * v2.z);
233 }
234
235 public static Vector3 Cross(Vector3 v1, Vector3 v2)
236 {
237 return new Vector3
238 (
239 v1.y * v2.z - v1.z * v2.y,
240 v1.z * v2.x - v1.x * v2.z,
241 v1.x * v2.y - v1.y * v2.x
242 );
243 }
244
245 public static double Mag(Vector3 v)
246 {
247 return Math.Sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
248 }
249
250 public static Vector3 Norm(Vector3 vector)
251 {
252 double mag = Mag(vector);
253 return new Vector3(vector.x / mag, vector.y / mag, vector.z / mag);
254 }
255
256 #endregion
257 }
258
259 [Serializable]
260 public struct Quaternion
261 {
262 public double x;
263 public double y;
264 public double z;
265 public double s;
266
267 #region Constructors
268
269 public Quaternion(Quaternion Quat)
270 {
271 x = (float)Quat.x;
272 y = (float)Quat.y;
273 z = (float)Quat.z;
274 s = (float)Quat.s;
275 if (x == 0 && y == 0 && z == 0 && s == 0)
276 s = 1;
277 }
278
279 public Quaternion(double X, double Y, double Z, double S)
280 {
281 x = X;
282 y = Y;
283 z = Z;
284 s = S;
285 if (x == 0 && y == 0 && z == 0 && s == 0)
286 s = 1;
287 }
288
289 public Quaternion(string str)
290 {
291 str = str.Replace('<', ' ');
292 str = str.Replace('>', ' ');
293 string[] tmps = str.Split(new Char[] { ',', '<', '>' });
294 if (tmps.Length < 4)
295 {
296 x=y=z=s=0;
297 return;
298 }
299 bool res;
300 res = Double.TryParse(tmps[0], out x);
301 res = res & Double.TryParse(tmps[1], out y);
302 res = res & Double.TryParse(tmps[2], out z);
303 res = res & Double.TryParse(tmps[3], out s);
304 if (x == 0 && y == 0 && z == 0 && s == 0)
305 s = 1;
306 }
307
308 #endregion
309
310 #region Overriders
311
312 public override int GetHashCode()
313 {
314 return (x.GetHashCode() ^ y.GetHashCode() ^ z.GetHashCode() ^ s.GetHashCode());
315 }
316
317 public override bool Equals(object o)
318 {
319 if (!(o is Quaternion)) return false;
320
321 Quaternion quaternion = (Quaternion)o;
322
323 return x == quaternion.x && y == quaternion.y && z == quaternion.z && s == quaternion.s;
324 }
325
326 public override string ToString()
327 {
328 string st=String.Format("<{0:0.000000},{1:0.000000},{2:0.000000},{3:0.000000}>", x, y, z, s);
329 return st;
330 }
331
332 public static explicit operator string(Quaternion r)
333 {
334 string s=String.Format("<{0:0.000000},{1:0.000000},{2:0.000000},{3:0.000000}>", r.x, r.y, r.z, r.s);
335 return s;
336 }
337
338 public static explicit operator LSLString(Quaternion r)
339 {
340 string s=String.Format("<{0:0.000000},{1:0.000000},{2:0.000000},{3:0.000000}>", r.x, r.y, r.z, r.s);
341 return new LSLString(s);
342 }
343
344 public static explicit operator Quaternion(string s)
345 {
346 return new Quaternion(s);
347 }
348
349 public static bool operator ==(Quaternion lhs, Quaternion rhs)
350 {
351 // Return true if the fields match:
352 return lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z && lhs.s == rhs.s;
353 }
354
355 public static bool operator !=(Quaternion lhs, Quaternion rhs)
356 {
357 return !(lhs == rhs);
358 }
359
360 #endregion
361
362 public static Quaternion operator +(Quaternion a, Quaternion b)
363 {
364 return new Quaternion(a.x + b.x, a.y + b.y, a.z + b.z, a.s + b.s);
365 }
366
367 public static Quaternion operator /(Quaternion a, Quaternion b)
368 {
369 b.s = -b.s;
370 return a * b;
371 }
372
373 public static Quaternion operator -(Quaternion a, Quaternion b)
374 {
375 return new Quaternion(a.x - b.x, a.y - b.y, a.z - b.z, a.s - b.s);
376 }
377
378 // using the equations below, we need to do "b * a" to be compatible with LSL
379 public static Quaternion operator *(Quaternion b, Quaternion a)
380 {
381 Quaternion c;
382 c.x = a.s * b.x + a.x * b.s + a.y * b.z - a.z * b.y;
383 c.y = a.s * b.y + a.y * b.s + a.z * b.x - a.x * b.z;
384 c.z = a.s * b.z + a.z * b.s + a.x * b.y - a.y * b.x;
385 c.s = a.s * b.s - a.x * b.x - a.y * b.y - a.z * b.z;
386 return c;
387 }
388 }
389
390 [Serializable]
391 public class list
392 {
393 private object[] m_data;
394
395 public list(params object[] args)
396 {
397 m_data = new object[args.Length];
398 m_data = args;
399 }
400
401 public int Length
402 {
403 get {
404 if (m_data == null)
405 m_data=new Object[0];
406 return m_data.Length;
407 }
408 }
409
410 public object[] Data
411 {
412 get {
413 if (m_data == null)
414 m_data=new Object[0];
415 return m_data;
416 }
417 }
418
419 public static list operator +(list a, list b)
420 {
421 object[] tmp;
422 tmp = new object[a.Length + b.Length];
423 a.Data.CopyTo(tmp, 0);
424 b.Data.CopyTo(tmp, a.Length);
425 return new list(tmp);
426 }
427
428 public void Add(object o)
429 {
430 object[] tmp;
431 tmp = new object[m_data.Length + 1];
432 m_data.CopyTo(tmp, 0);
433 tmp[m_data.Length] = o;
434 m_data = tmp;
435 }
436
437 public bool Contains(object o)
438 {
439 bool ret = false;
440 foreach (object i in Data)
441 {
442 if (i == o)
443 {
444 ret = true;
445 break;
446 }
447 }
448 return ret;
449 }
450
451 public list DeleteSublist(int start, int end)
452 {
453 // Not an easy one
454 // If start <= end, remove that part
455 // if either is negative, count from the end of the array
456 // if the resulting start > end, remove all BUT that part
457
458 Object[] ret;
459
460 if (start < 0)
461 start=m_data.Length-start;
462
463 if (start < 0)
464 start=0;
465
466 if (end < 0)
467 end=m_data.Length-end;
468 if (end < 0)
469 end=0;
470
471 if (start > end)
472 {
473 if (end >= m_data.Length)
474 return new list(new Object[0]);
475
476 if (start >= m_data.Length)
477 start=m_data.Length-1;
478
479 return GetSublist(end, start);
480 }
481
482 // start >= 0 && end >= 0 here
483 if (start >= m_data.Length)
484 {
485 ret=new Object[m_data.Length];
486 Array.Copy(m_data, 0, ret, 0, m_data.Length);
487
488 return new list(ret);
489 }
490
491 if (end >= m_data.Length)
492 end=m_data.Length-1;
493
494 // now, this makes the math easier
495 int remove=end+1-start;
496
497 ret=new Object[m_data.Length-remove];
498 if (ret.Length == 0)
499 return new list(ret);
500
501 int src;
502 int dest=0;
503
504 for (src = 0; src < m_data.Length; src++)
505 {
506 if (src < start || src > end)
507 ret[dest++]=m_data[src];
508 }
509
510 return new list(ret);
511 }
512
513 public list GetSublist(int start, int end)
514 {
515
516 object[] ret;
517
518 // Take care of neg start or end's
519 // NOTE that either index may still be negative after
520 // adding the length, so we must take additional
521 // measures to protect against this. Note also that
522 // after normalisation the negative indices are no
523 // longer relative to the end of the list.
524
525 if (start < 0)
526 {
527 start = m_data.Length + start;
528 }
529
530 if (end < 0)
531 {
532 end = m_data.Length + end;
533 }
534
535 // The conventional case is start <= end
536 // NOTE that the case of an empty list is
537 // dealt with by the initial test. Start
538 // less than end is taken to be the most
539 // common case.
540
541 if (start <= end)
542 {
543
544 // Start sublist beyond length
545 // Also deals with start AND end still negative
546 if (start >= m_data.Length || end < 0)
547 {
548 return new list();
549 }
550
551 // Sublist extends beyond the end of the supplied list
552 if (end >= m_data.Length)
553 {
554 end = m_data.Length - 1;
555 }
556
557 // Sublist still starts before the beginning of the list
558 if (start < 0)
559 {
560 start = 0;
561 }
562
563 ret = new object[end - start + 1];
564
565 Array.Copy(m_data, start, ret, 0, end - start + 1);
566
567 return new list(ret);
568
569 }
570
571 // Deal with the segmented case: 0->end + start->EOL
572
573 else
574 {
575
576 list result = null;
577
578 // If end is negative, then prefix list is empty
579 if (end < 0)
580 {
581 result = new list();
582 // If start is still negative, then the whole of
583 // the existing list is returned. This case is
584 // only admitted if end is also still negative.
585 if (start < 0)
586 {
587 return this;
588 }
589
590 }
591 else
592 {
593 result = GetSublist(0,end);
594 }
595
596 // If start is outside of list, then just return
597 // the prefix, whatever it is.
598 if (start >= m_data.Length)
599 {
600 return result;
601 }
602
603 return result + GetSublist(start, Data.Length);
604
605 }
606 }
607
608 public list Sort(int stride, int ascending)
609 {
610 if (Data.Length == 0)
611 return new list(); // Don't even bother
612
613 string[] keys;
614
615 if (stride == 1) // The simple case
616 {
617 Object[] ret=new Object[Data.Length];
618
619 Array.Copy(Data, 0, ret, 0, Data.Length);
620
621 keys=new string[Data.Length];
622
623 for (int k = 0; k < Data.Length; k++)
624 keys[k] = Data[k].ToString();
625
626 Array.Sort(keys, ret);
627
628 if (ascending == 0)
629 Array.Reverse(ret);
630 return new list(ret);
631 }
632
633 int src=0;
634
635 int len=(Data.Length+stride-1)/stride;
636
637 keys=new string[len];
638 Object[][] vals=new Object[len][];
639
640 int i;
641
642 while (src < Data.Length)
643 {
644 Object[] o=new Object[stride];
645
646 for (i = 0; i < stride; i++)
647 {
648 if (src < Data.Length)
649 o[i]=Data[src++];
650 else
651 {
652 o[i]=new Object();
653 src++;
654 }
655 }
656
657 int idx=src/stride-1;
658 keys[idx]=o[0].ToString();
659 vals[idx]=o;
660 }
661
662 Array.Sort(keys, vals);
663 if (ascending == 0)
664 {
665 Array.Reverse(vals);
666 }
667
668 Object[] sorted=new Object[stride*vals.Length];
669
670 for (i = 0; i < vals.Length; i++)
671 for (int j = 0; j < stride; j++)
672 sorted[i*stride+j] = vals[i][j];
673
674 return new list(sorted);
675 }
676
677 #region CSV Methods
678
679 public static list FromCSV(string csv)
680 {
681 return new list(csv.Split(','));
682 }
683
684 public string ToCSV()
685 {
686 string ret = "";
687 foreach (object o in this.Data)
688 {
689 if (ret == "")
690 {
691 ret = o.ToString();
692 }
693 else
694 {
695 ret = ret + ", " + o.ToString();
696 }
697 }
698 return ret;
699 }
700
701 private string ToSoup()
702 {
703 string output;
704 output = String.Empty;
705 if (m_data.Length == 0)
706 {
707 return String.Empty;
708 }
709 foreach (object o in m_data)
710 {
711 output = output + o.ToString();
712 }
713 return output;
714 }
715
716 public static explicit operator String(list l)
717 {
718 return l.ToSoup();
719 }
720
721 public static explicit operator LSLString(list l)
722 {
723 return new LSLString(l.ToSoup());
724 }
725
726 public override string ToString()
727 {
728 return ToSoup();
729 }
730
731 #endregion
732
733 #region Statistic Methods
734
735 public double Min()
736 {
737 double minimum = double.PositiveInfinity;
738 double entry;
739 for (int i = 0; i < Data.Length; i++)
740 {
741 if (double.TryParse(Data[i].ToString(), out entry))
742 {
743 if (entry < minimum) minimum = entry;
744 }
745 }
746 return minimum;
747 }
748
749 public double Max()
750 {
751 double maximum = double.NegativeInfinity;
752 double entry;
753 for (int i = 0; i < Data.Length; i++)
754 {
755 if (double.TryParse(Data[i].ToString(), out entry))
756 {
757 if (entry > maximum) maximum = entry;
758 }
759 }
760 return maximum;
761 }
762
763 public double Range()
764 {
765 return (this.Max() / this.Min());
766 }
767
768 public int NumericLength()
769 {
770 int count = 0;
771 double entry;
772 for (int i = 0; i < Data.Length; i++)
773 {
774 if (double.TryParse(Data[i].ToString(), out entry))
775 {
776 count++;
777 }
778 }
779 return count;
780 }
781
782 public static list ToDoubleList(list src)
783 {
784 list ret = new list();
785 double entry;
786 for (int i = 0; i < src.Data.Length - 1; i++)
787 {
788 if (double.TryParse(src.Data[i].ToString(), out entry))
789 {
790 ret.Add(entry);
791 }
792 }
793 return ret;
794 }
795
796 public double Sum()
797 {
798 double sum = 0;
799 double entry;
800 for (int i = 0; i < Data.Length; i++)
801 {
802 if (double.TryParse(Data[i].ToString(), out entry))
803 {
804 sum = sum + entry;
805 }
806 }
807 return sum;
808 }
809
810 public double SumSqrs()
811 {
812 double sum = 0;
813 double entry;
814 for (int i = 0; i < Data.Length; i++)
815 {
816 if (double.TryParse(Data[i].ToString(), out entry))
817 {
818 sum = sum + Math.Pow(entry, 2);
819 }
820 }
821 return sum;
822 }
823
824 public double Mean()
825 {
826 return (this.Sum() / this.NumericLength());
827 }
828
829 public void NumericSort()
830 {
831 IComparer Numeric = new NumericComparer();
832 Array.Sort(Data, Numeric);
833 }
834
835 public void AlphaSort()
836 {
837 IComparer Alpha = new AlphaCompare();
838 Array.Sort(Data, Alpha);
839 }
840
841 public double Median()
842 {
843 return Qi(0.5);
844 }
845
846 public double GeometricMean()
847 {
848 double ret = 1.0;
849 list nums = ToDoubleList(this);
850 for (int i = 0; i < nums.Data.Length; i++)
851 {
852 ret *= (double)nums.Data[i];
853 }
854 return Math.Exp(Math.Log(ret) / (double)nums.Data.Length);
855 }
856
857 public double HarmonicMean()
858 {
859 double ret = 0.0;
860 list nums = ToDoubleList(this);
861 for (int i = 0; i < nums.Data.Length; i++)
862 {
863 ret += 1.0 / (double)nums.Data[i];
864 }
865 return ((double)nums.Data.Length / ret);
866 }
867
868 public double Variance()
869 {
870 double s = 0;
871 list num = ToDoubleList(this);
872 for (int i = 0; i < num.Data.Length; i++)
873 {
874 s += Math.Pow((double)num.Data[i], 2);
875 }
876 return (s - num.Data.Length * Math.Pow(num.Mean(), 2)) / (num.Data.Length - 1);
877 }
878
879 public double StdDev()
880 {
881 return Math.Sqrt(this.Variance());
882 }
883
884 public double Qi(double i)
885 {
886 list j = this;
887 j.NumericSort();
888
889 if (Math.Ceiling(this.Length * i) == this.Length * i)
890 {
891 return (double)((double)j.Data[(int)(this.Length * i - 1)] + (double)j.Data[(int)(this.Length * i)]) / 2;
892 }
893 else
894 {
895 return (double)j.Data[((int)(Math.Ceiling(this.Length * i))) - 1];
896 }
897 }
898
899 #endregion
900
901 public string ToPrettyString()
902 {
903 string output;
904 if (m_data.Length == 0)
905 {
906 return "[]";
907 }
908 output = "[";
909 foreach (object o in m_data)
910 {
911 if (o is String)
912 {
913 output = output + "\"" + o + "\", ";
914 }
915 else
916 {
917 output = output + o.ToString() + ", ";
918 }
919 }
920 output = output.Substring(0, output.Length - 2);
921 output = output + "]";
922 return output;
923 }
924
925 public class AlphaCompare : IComparer
926 {
927 int IComparer.Compare(object x, object y)
928 {
929 return string.Compare(x.ToString(), y.ToString());
930 }
931 }
932
933 public class NumericComparer : IComparer
934 {
935 int IComparer.Compare(object x, object y)
936 {
937 double a;
938 double b;
939 if (!double.TryParse(x.ToString(), out a))
940 {
941 a = 0.0;
942 }
943 if (!double.TryParse(y.ToString(), out b))
944 {
945 b = 0.0;
946 }
947 if (a < b)
948 {
949 return -1;
950 }
951 else if (a == b)
952 {
953 return 0;
954 }
955 else
956 {
957 return 1;
958 }
959 }
960 }
961
962 }
963
964 //
965 // BELOW IS WORK IN PROGRESS... IT WILL CHANGE, SO DON'T USE YET! :)
966 //
967
968 public struct StringTest
969 {
970 // Our own little string
971 internal string actualString;
972 public static implicit operator bool(StringTest mString)
973 {
974 if (mString.actualString.Length == 0)
975 return true;
976 return false;
977 }
978 public override string ToString()
979 {
980 return actualString;
981 }
982
983 }
984
985 [Serializable]
986 public struct key
987 {
988 public string value;
989
990 #region Constructors
991 public key(string s)
992 {
993 value = s;
994 }
995
996 #endregion
997
998 #region Methods
999
1000 static public bool Parse2Key(string s)
1001 {
1002 Regex isuuid = new Regex(@"^[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}$", RegexOptions.Compiled);
1003 if (isuuid.IsMatch(s))
1004 {
1005 return true;
1006 }
1007 else
1008 {
1009 return false;
1010 }
1011 }
1012
1013 #endregion
1014
1015 #region Operators
1016
1017 static public implicit operator Boolean(key k)
1018 {
1019 if (k.value.Length == 0)
1020 {
1021 return false;
1022 }
1023
1024 if (k.value == "00000000-0000-0000-0000-000000000000")
1025 {
1026 return false;
1027 }
1028 Regex isuuid = new Regex(@"^[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}$", RegexOptions.Compiled);
1029 if (isuuid.IsMatch(k.value))
1030 {
1031 return true;
1032 }
1033 else
1034 {
1035 return false;
1036 }
1037 }
1038
1039 static public implicit operator key(string s)
1040 {
1041 return new key(s);
1042 }
1043
1044 static public implicit operator String(key k)
1045 {
1046 return k.value;
1047 }
1048
1049 public static bool operator ==(key k1, key k2)
1050 {
1051 return k1.value == k2.value;
1052 }
1053 public static bool operator !=(key k1, key k2)
1054 {
1055 return k1.value != k2.value;
1056 }
1057
1058 #endregion
1059
1060 #region Overriders
1061
1062 public override bool Equals(object o)
1063 {
1064 return o.ToString() == value;
1065 }
1066
1067 public override int GetHashCode()
1068 {
1069 return value.GetHashCode();
1070 }
1071
1072 #endregion
1073 }
1074
1075 [Serializable]
1076 public struct LSLString
1077 {
1078 public string m_string;
1079 #region Constructors
1080 public LSLString(string s)
1081 {
1082 m_string = s;
1083 }
1084
1085 public LSLString(int i)
1086 {
1087 m_string=i.ToString();
1088 }
1089
1090 public LSLString(double d)
1091 {
1092 string s=String.Format("{0:0.000000}", d);
1093 m_string=s;
1094 }
1095
1096 #endregion
1097
1098 #region Operators
1099 static public implicit operator Boolean(LSLString s)
1100 {
1101 if (s.m_string.Length == 0)
1102 {
1103 return false;
1104 }
1105 else
1106 {
1107 return true;
1108 }
1109 }
1110
1111
1112
1113 static public implicit operator String(LSLString s)
1114 {
1115 return s.m_string;
1116 }
1117
1118 static public implicit operator LSLString(string s)
1119 {
1120 return new LSLString(s);
1121 }
1122
1123 public static string ToString(LSLString s)
1124 {
1125 return s.m_string;
1126 }
1127
1128 public override string ToString()
1129 {
1130 return m_string;
1131 }
1132
1133 public static bool operator ==(LSLString s1, string s2)
1134 {
1135 return s1.m_string == s2;
1136 }
1137
1138 public static bool operator !=(LSLString s1, string s2)
1139 {
1140 return s1.m_string != s2;
1141 }
1142
1143 public static explicit operator double(LSLString s)
1144 {
1145 return Convert.ToDouble(s.m_string);
1146 }
1147
1148 public static explicit operator LSLInteger(LSLString s)
1149 {
1150 return new LSLInteger(Convert.ToInt32(s.m_string));
1151 }
1152
1153 public static explicit operator LSLString(int i)
1154 {
1155 return new LSLString(i);
1156 }
1157
1158 public static explicit operator LSLString(double d)
1159 {
1160 return new LSLString(d);
1161 }
1162
1163 public static implicit operator Vector3(LSLString s)
1164 {
1165 return new Vector3(s.m_string);
1166 }
1167
1168 #endregion
1169
1170 #region Overriders
1171 public override bool Equals(object o)
1172 {
1173 return m_string == o.ToString();
1174 }
1175
1176 public override int GetHashCode()
1177 {
1178 return m_string.GetHashCode();
1179 }
1180
1181 #endregion
1182
1183 #region " Standard string functions "
1184 //Clone,CompareTo,Contains
1185 //CopyTo,EndsWith,Equals,GetEnumerator,GetHashCode,GetType,GetTypeCode
1186 //IndexOf,IndexOfAny,Insert,IsNormalized,LastIndexOf,LastIndexOfAny
1187 //Length,Normalize,PadLeft,PadRight,Remove,Replace,Split,StartsWith,Substring,ToCharArray,ToLowerInvariant
1188 //ToString,ToUpper,ToUpperInvariant,Trim,TrimEnd,TrimStart
1189 public bool Contains(string value) { return m_string.Contains(value); }
1190 public int IndexOf(string value) { return m_string.IndexOf(value); }
1191 public int Length { get { return m_string.Length; } }
1192
1193
1194 #endregion
1195 }
1196
1197 [Serializable]
1198 public struct LSLInteger
1199 {
1200 public int value;
1201
1202 #region Constructors
1203 public LSLInteger(int i)
1204 {
1205 value = i;
1206 }
1207
1208 public LSLInteger(double d)
1209 {
1210 value = (int)d;
1211 }
1212
1213 public LSLInteger(Object o)
1214 {
1215 if(!(o is Int32))
1216 value=0;
1217 else
1218 value = (int)o;
1219 }
1220
1221 public LSLInteger(string s)
1222 {
1223 value = int.Parse(s);
1224 }
1225
1226 #endregion
1227
1228 static public implicit operator int(LSLInteger i)
1229 {
1230 return i.value;
1231 }
1232
1233 static public implicit operator uint(LSLInteger i)
1234 {
1235 return (uint)i.value;
1236 }
1237
1238 static public explicit operator LSLString(LSLInteger i)
1239 {
1240 return new LSLString(i.ToString());
1241 }
1242
1243 static public explicit operator string(LSLInteger i)
1244 {
1245 return i.ToString();
1246 }
1247
1248 static public implicit operator Boolean(LSLInteger i)
1249 {
1250 if (i.value == 0)
1251 {
1252 return false;
1253 }
1254 else
1255 {
1256 return true;
1257 }
1258 }
1259
1260 static public implicit operator LSLInteger(int i)
1261 {
1262 return new LSLInteger(i);
1263 }
1264
1265 static public explicit operator LSLInteger(string s)
1266 {
1267 return new LSLInteger(int.Parse(s));
1268 }
1269
1270 static public implicit operator LSLInteger(double d)
1271 {
1272 return new LSLInteger(d);
1273 }
1274
1275 static public bool operator ==(LSLInteger i1, LSLInteger i2)
1276 {
1277 bool ret = i1.value == i2.value;
1278 return ret;
1279 }
1280
1281 static public bool operator !=(LSLInteger i1, LSLInteger i2)
1282 {
1283 bool ret = i1.value != i2.value;
1284 return ret;
1285 }
1286
1287 static public LSLInteger operator &(LSLInteger i1, LSLInteger i2)
1288 {
1289 int ret = i1.value & i2.value;
1290 return ret;
1291 }
1292
1293 public static LSLInteger operator ++(LSLInteger i)
1294 {
1295 i.value++;
1296 return i;
1297 }
1298
1299
1300 public static LSLInteger operator --(LSLInteger i)
1301 {
1302 i.value--;
1303 return i;
1304 }
1305
1306 static public implicit operator System.Double(LSLInteger i)
1307 {
1308 return (double)i.value;
1309 }
1310
1311 public static bool operator true(LSLInteger i)
1312 {
1313 return i.value != 0;
1314 }
1315
1316 public static bool operator false(LSLInteger i)
1317 {
1318 return i.value == 0;
1319 }
1320
1321 #region Overriders
1322
1323 public override string ToString()
1324 {
1325 return this.value.ToString();
1326 }
1327
1328 public override bool Equals(object o)
1329 {
1330 if(o is Int32)
1331 {
1332 return value == (Int32)o;
1333 }
1334 if(o is LSLInteger)
1335 {
1336 return value == ((LSLInteger)o).value;
1337 }
1338 return false;
1339 }
1340
1341 public override int GetHashCode()
1342 {
1343 return value.GetHashCode();
1344 }
1345
1346 #endregion
1347 }
1348
1349 [Serializable]
1350 public struct LSLFloat
1351 {
1352 public double value;
1353
1354 #region Constructors
1355 public LSLFloat(int i)
1356 {
1357 this.value = (double)i;
1358 }
1359
1360 public LSLFloat(double d)
1361 {
1362 this.value = d;
1363 }
1364
1365 #endregion
1366
1367 #region Operators
1368
1369 static public implicit operator Double(LSLFloat f)
1370 {
1371 return f.value;
1372 }
1373
1374 //static public implicit operator System.Int32(LSLFloat f)
1375 //{
1376 // return (int)f.value;
1377 //}
1378
1379
1380 static public implicit operator Boolean(LSLFloat f)
1381 {
1382 if (f.value == 0)
1383 {
1384 return false;
1385 }
1386 else
1387 {
1388 return true;
1389 }
1390 }
1391
1392 static public implicit operator LSLFloat(int i)
1393 {
1394 return new LSLFloat(i);
1395 }
1396
1397 static public implicit operator LSLFloat(double d)
1398 {
1399 return new LSLFloat(d);
1400 }
1401 #endregion
1402
1403 #region Overriders
1404 public override string ToString()
1405 {
1406 return this.value.ToString();
1407 }
1408 #endregion
1409 }
1410 }
1411}
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
new file mode 100644
index 0000000..3ca03b2
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
@@ -0,0 +1,1435 @@
1using System;
2using System.IO;
3using System.Threading;
4using System.Collections;
5using System.Collections.Generic;
6using System.Security.Policy;
7using System.Reflection;
8using System.Xml;
9using libsecondlife;
10using log4net;
11using Nini.Config;
12using Amib.Threading;
13using OpenSim.Framework;
14using OpenSim.Region.Environment;
15using OpenSim.Region.Environment.Scenes;
16using OpenSim.Region.Environment.Interfaces;
17using OpenSim.Region.ScriptEngine.XEngine.Script;
18
19namespace OpenSim.Region.ScriptEngine.XEngine
20{
21 public class XEngine : IRegionModule
22 {
23 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
24
25 private SmartThreadPool m_ThreadPool;
26 private int m_MaxScriptQueue;
27 private Scene m_Scene;
28 private IConfig m_ScriptConfig;
29 private Compiler m_Compiler;
30 private EventManager m_EventManager;
31 private int m_EventLimit;
32 private bool m_KillTimedOutScripts;
33
34 private static List<XEngine> m_ScriptEngines =
35 new List<XEngine>();
36 public AsyncCommandManager m_ASYNCLSLCommandManager;
37
38 // Maps the local id to the script inventory items in it
39
40 private Dictionary<uint, List<LLUUID> > m_PrimObjects =
41 new Dictionary<uint, List<LLUUID> >();
42
43 // Maps the LLUUID above to the script instance
44
45 private Dictionary<LLUUID, XScriptInstance> m_Scripts =
46 new Dictionary<LLUUID, XScriptInstance>();
47
48 // Maps the asset ID to the assembly
49
50 private Dictionary<LLUUID, string> m_Assemblies =
51 new Dictionary<LLUUID, string>();
52
53 // This will list AppDomains by script asset
54
55 private Dictionary<LLUUID, AppDomain> m_AppDomains =
56 new Dictionary<LLUUID, AppDomain>();
57
58 // List the scripts running in each appdomain
59
60 private Dictionary<LLUUID, List<LLUUID> > m_DomainScripts =
61 new Dictionary<LLUUID, List<LLUUID> >();
62
63 public string ScriptEngineName
64 {
65 get { return "XEngine"; }
66 }
67
68 public Scene World
69 {
70 get { return m_Scene; }
71 }
72
73 public ILog Log
74 {
75 get { return m_log; }
76 }
77
78 public static List<XEngine> ScriptEngines
79 {
80 get { return m_ScriptEngines; }
81 }
82
83 private struct RezScriptParms
84 {
85 uint LocalID;
86 LLUUID ItemID;
87 string Script;
88 }
89
90 public IConfig ScriptConfigSource
91 {
92 get { return m_ScriptConfig; }
93 }
94
95 //
96 // IRegionModule functions
97 //
98 public void Initialise(Scene scene, IConfigSource configSource)
99 {
100 AppDomain.CurrentDomain.AssemblyResolve +=
101 OnAssemblyResolve;
102
103 m_log.InfoFormat("[XEngine] Initializing scripts in region {0}",
104 scene.RegionInfo.RegionName);
105 m_Scene=scene;
106
107 m_ScriptConfig = configSource.Configs["XEngine"];
108
109 if(m_ScriptConfig == null)
110 {
111 m_log.ErrorFormat("[XEngine] No script configuration found. Scripts disabled");
112 return;
113 }
114
115 int minThreads = m_ScriptConfig.GetInt("MinThreads", 2);
116 int maxThreads = m_ScriptConfig.GetInt("MaxThreads", 2);
117 int idleTimeout = m_ScriptConfig.GetInt("IdleTimeout", 60);
118 string priority = m_ScriptConfig.GetString("Priority", "BelowNormal");
119 int maxScriptQueue = m_ScriptConfig.GetInt("MaxScriptEventQueue",300);
120 int stackSize = m_ScriptConfig.GetInt("ThreadStackSize", 262144);
121 int sleepTime = m_ScriptConfig.GetInt("MaintenanceInterval",
122 10)*1000;
123 m_EventLimit = m_ScriptConfig.GetInt("EventLimit", 30);
124 m_KillTimedOutScripts = m_ScriptConfig.GetBoolean(
125 "KillTimedOutScripts", false);
126 int saveTime = m_ScriptConfig.GetInt("SaveInterval", 300)*1000;
127
128 ThreadPriority prio = ThreadPriority.BelowNormal;
129 switch(priority)
130 {
131 case "Lowest":
132 prio=ThreadPriority.Lowest;
133 break;
134 case "BelowNormal":
135 prio=ThreadPriority.BelowNormal;
136 break;
137 case "Normal":
138 prio=ThreadPriority.Normal;
139 break;
140 case "AboveNormal":
141 prio=ThreadPriority.AboveNormal;
142 break;
143 case "Highest":
144 prio=ThreadPriority.Highest;
145 break;
146 default:
147 m_log.ErrorFormat("[XEngine] Invalid thread priority: '"+
148 priority+"'. Assuming BelowNormal");
149 break;
150 }
151
152 lock(m_ScriptEngines)
153 {
154 m_ScriptEngines.Add(this);
155 }
156
157 m_EventManager = new EventManager(this);
158 m_ASYNCLSLCommandManager = new AsyncCommandManager(this);
159
160 StartEngine(minThreads, maxThreads, idleTimeout, prio,
161 maxScriptQueue, stackSize);
162
163 m_Compiler = new Compiler(this);
164
165 m_Scene.EventManager.OnRezScript += OnRezScript;
166 m_Scene.EventManager.OnRemoveScript += OnRemoveScript;
167 m_Scene.EventManager.OnScriptReset += OnScriptReset;
168
169 if(sleepTime > 0)
170 {
171 m_ThreadPool.QueueWorkItem(new WorkItemCallback(
172 this.DoMaintenance), new Object[]
173 { sleepTime });
174 }
175
176 if(saveTime > 0)
177 {
178 m_ThreadPool.QueueWorkItem(new WorkItemCallback(
179 this.DoBackup), new Object[] { saveTime });
180 }
181 }
182
183 public void PostInitialise()
184 {
185 m_ThreadPool.Start();
186 }
187
188 public void Close()
189 {
190 lock(m_ScriptEngines)
191 {
192 if(m_ScriptEngines.Contains(this))
193 m_ScriptEngines.Remove(this);
194 }
195 }
196
197 public object DoBackup(object o)
198 {
199 Object[] p = (Object[])o;
200 int saveTime = (int)p[0];
201
202 System.Threading.Thread.Sleep(saveTime);
203
204// m_log.Debug("[XEngine] Backing up script states");
205
206 List<XScriptInstance> instances = new List<XScriptInstance>();
207
208 lock(m_Scripts)
209 {
210 foreach (XScriptInstance instance in m_Scripts.Values)
211 instances.Add(instance);
212 }
213
214 foreach (XScriptInstance i in instances)
215 {
216 string assembly = String.Empty;
217
218 lock(m_Scripts)
219 {
220 if(!m_Assemblies.ContainsKey(i.AssetID))
221 continue;
222 assembly = m_Assemblies[i.AssetID];
223 }
224
225 i.SaveState(assembly);
226 }
227
228 instances.Clear();
229
230 m_ThreadPool.QueueWorkItem(new WorkItemCallback(
231 this.DoBackup), new Object[] { saveTime });
232
233 return 0;
234 }
235
236 public object DoMaintenance(object p)
237 {
238 object[] parms = (object[])p;
239 int sleepTime = (int)parms[0];
240
241 foreach (XScriptInstance inst in m_Scripts.Values)
242 {
243 if(inst.EventTime() > m_EventLimit)
244 {
245 inst.Stop(100);
246 if(!m_KillTimedOutScripts)
247 inst.Start();
248 }
249 }
250
251 System.Threading.Thread.Sleep(sleepTime);
252
253 m_ThreadPool.QueueWorkItem(new WorkItemCallback(
254 this.DoMaintenance), new Object[]
255 { sleepTime });
256
257 return 0;
258 }
259
260 public string Name
261 {
262 get { return "XEngine"; }
263 }
264
265 public bool IsSharedModule
266 {
267 get { return false; }
268 }
269
270 //
271 // XEngine functions
272 //
273 public int MaxScriptQueue
274 {
275 get { return m_MaxScriptQueue; }
276 }
277
278 //
279 // Hooks
280 //
281 public void OnRezScript(uint localID, LLUUID itemID, string script)
282 {
283 m_ThreadPool.QueueWorkItem(new WorkItemCallback(
284 this.DoOnRezScript), new Object[]
285 { localID, itemID, script});
286 }
287
288 private object DoOnRezScript(object parm)
289 {
290 Object[] p = (Object[])parm;
291 uint localID = (uint)p[0];
292 LLUUID itemID = (LLUUID)p[1];
293 string script =(string)p[2];
294
295 // Get the asset ID of the script, so we can check if we
296 // already have it.
297
298 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID);
299 if(part == null)
300 return false;
301
302 TaskInventoryItem item = part.GetInventoryItem(itemID);
303 if(item == null)
304 return false;
305
306 LLUUID assetID=item.AssetID;
307
308// m_log.DebugFormat("[XEngine] Compiling script {0} ({1})",
309// item.Name, itemID.ToString());
310
311 string assembly="";
312 try
313 {
314 assembly=m_Compiler.PerformScriptCompile(script,
315 assetID.ToString());
316 m_log.DebugFormat("[XEngine] Loaded script {0}.{1}",
317 part.ParentGroup.RootPart.Name, item.Name);
318 }
319 catch (Exception e)
320 {
321 try
322 {
323 // DISPLAY ERROR INWORLD
324 string text = "Error compiling script:\r\n" + e.Message.ToString();
325 if (text.Length > 1400)
326 text = text.Substring(0, 1400);
327 World.SimChat(Helpers.StringToField(text),
328 ChatTypeEnum.DebugChannel, 2147483647,
329 part.AbsolutePosition,
330 part.Name, part.UUID, false);
331 }
332 catch (Exception e2) // LEGIT: User Scripting
333 {
334 m_log.Error("[XEngine]: "+
335 "Error displaying error in-world: " +
336 e2.ToString());
337 m_log.Error("[XEngine]: " +
338 "Errormessage: Error compiling script:\r\n" +
339 e.Message.ToString());
340 }
341
342 return false;
343 }
344
345 lock(m_Scripts)
346 {
347 // Create the object record
348
349 if(!m_PrimObjects.ContainsKey(localID))
350 m_PrimObjects[localID] = new List<LLUUID>();
351
352 if(!m_PrimObjects[localID].Contains(itemID))
353 m_PrimObjects[localID].Add(itemID);
354
355 if(!m_Assemblies.ContainsKey(assetID))
356 m_Assemblies[assetID] = assembly;
357
358 if((!m_Scripts.ContainsKey(itemID)) ||
359 (m_Scripts[itemID].AssetID != assetID))
360 {
361 LLUUID appDomain=assetID;
362
363 if(part.ParentGroup.RootPart.m_IsAttachment)
364 appDomain=part.ParentGroup.RootPart.UUID;
365
366 if(!m_AppDomains.ContainsKey(appDomain))
367 {
368 try
369 {
370 AppDomainSetup appSetup = new AppDomainSetup();
371// appSetup.ApplicationBase = Path.Combine(
372// "ScriptEngines",
373// m_Scene.RegionInfo.RegionID.ToString());
374
375 Evidence baseEvidence =
376 AppDomain.CurrentDomain.Evidence;
377 Evidence evidence = new Evidence(baseEvidence);
378
379 m_AppDomains[appDomain] =
380 AppDomain.CreateDomain(
381 m_Scene.RegionInfo.RegionID.ToString(),
382 evidence, appSetup);
383
384 m_AppDomains[appDomain].AssemblyResolve +=
385 new ResolveEventHandler(
386 AssemblyResolver.OnAssemblyResolve);
387 m_DomainScripts[appDomain] = new List<LLUUID>();
388 }
389 catch (Exception e)
390 {
391 m_log.Error("[XEngine] Exception creating app domain:\n"+e.ToString());
392 return false;
393 }
394 }
395 m_DomainScripts[appDomain].Add(itemID);
396
397
398 XScriptInstance instance = new XScriptInstance(this,localID,
399 part.UUID, itemID, assetID, assembly,
400 m_AppDomains[appDomain]);
401
402 instance.AppDomain = appDomain;
403
404 m_Scripts[itemID] = instance;
405 }
406 }
407 return true;
408 }
409
410 public void OnRemoveScript(uint localID, LLUUID itemID)
411 {
412 lock(m_Scripts)
413 {
414 // Do we even have it?
415 if(!m_Scripts.ContainsKey(itemID))
416 return;
417
418 m_ASYNCLSLCommandManager.RemoveScript(localID, itemID);
419
420 XScriptInstance instance=m_Scripts[itemID];
421 m_Scripts.Remove(itemID);
422
423 instance.ClearQueue();
424 instance.Stop(0);
425
426 SceneObjectPart part =
427 m_Scene.GetSceneObjectPart(localID);
428
429 if(part != null)
430 part.RemoveScriptEvents(itemID);
431
432 // Remove the script from it's prim
433 if(m_PrimObjects.ContainsKey(localID))
434 {
435 // Remove inventory item record
436 if(m_PrimObjects[localID].Contains(itemID))
437 m_PrimObjects[localID].Remove(itemID);
438
439 // If there are no more scripts, remove prim
440 if(m_PrimObjects[localID].Count == 0)
441 {
442 m_PrimObjects.Remove(localID);
443 }
444 }
445
446 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID);
447 if(m_DomainScripts[instance.AppDomain].Count == 0)
448 {
449 m_DomainScripts.Remove(instance.AppDomain);
450 UnloadAppDomain(instance.AppDomain);
451 }
452
453 instance = null;
454
455 CleanAssemblies();
456 }
457 }
458
459 public void OnScriptReset(uint localID, LLUUID itemID)
460 {
461 ResetScript(itemID);
462 }
463
464 private void CleanAssemblies()
465 {
466 List<LLUUID> assetIDList = new List<LLUUID>(m_Assemblies.Keys);
467
468 foreach (XScriptInstance i in m_Scripts.Values)
469 {
470 if(assetIDList.Contains(i.AssetID))
471 assetIDList.Remove(i.AssetID);
472 }
473
474 foreach (LLUUID assetID in assetIDList)
475 {
476// m_log.DebugFormat("[XEngine] Removing unreferenced assembly {0}", m_Assemblies[assetID]);
477 try
478 {
479 if(File.Exists(m_Assemblies[assetID]))
480 File.Delete(m_Assemblies[assetID]);
481 if(File.Exists(m_Assemblies[assetID]+".state"))
482 File.Delete(m_Assemblies[assetID]+".state");
483 if(File.Exists(m_Assemblies[assetID]+".mdb"))
484 File.Delete(m_Assemblies[assetID]+".mdb");
485 }
486 catch (Exception e)
487 {
488 }
489 m_Assemblies.Remove(assetID);
490 }
491 }
492
493 private void UnloadAppDomain(LLUUID id)
494 {
495 if(m_AppDomains.ContainsKey(id))
496 {
497 AppDomain domain=m_AppDomains[id];
498 m_AppDomains.Remove(id);
499
500 AppDomain.Unload(domain);
501 domain = null;
502// m_log.DebugFormat("[XEngine] Unloaded app domain {0}", id.ToString());
503 }
504 }
505
506 //
507 // Start processing
508 //
509 private void StartEngine(int minThreads, int maxThreads,
510 int idleTimeout, ThreadPriority threadPriority,
511 int maxScriptQueue, int stackSize)
512 {
513 m_MaxScriptQueue=maxScriptQueue;
514
515 STPStartInfo startInfo = new STPStartInfo();
516 startInfo.IdleTimeout = idleTimeout;
517 startInfo.MaxWorkerThreads = maxThreads;
518 startInfo.MinWorkerThreads = minThreads;
519 startInfo.ThreadPriority = threadPriority;
520 startInfo.StackSize = stackSize;
521 startInfo.StartSuspended = true;
522
523 m_ThreadPool = new SmartThreadPool(startInfo);
524 }
525
526 //
527 // Used by script instances to queue event handler jobs
528 //
529 public IWorkItemResult QueueEventHandler(object parms)
530 {
531 return m_ThreadPool.QueueWorkItem(new WorkItemCallback(
532 this.ProcessEventHandler), parms);
533 }
534
535 //
536 // The main script engine worker
537 //
538 private object ProcessEventHandler(object parms)
539 {
540 XScriptInstance instance=(XScriptInstance)parms;
541
542 return instance.EventProcessor();
543 }
544
545 //
546 // Post event to an entire prim
547 //
548 public bool PostObjectEvent(uint localID, XEventParams p)
549 {
550 bool result = false;
551
552 if(!m_PrimObjects.ContainsKey(localID))
553 return false;
554
555 foreach (LLUUID itemID in m_PrimObjects[localID])
556 {
557 if(m_Scripts.ContainsKey(itemID))
558 {
559 XScriptInstance instance = m_Scripts[itemID];
560 if(instance != null)
561 {
562 instance.PostEvent(p);
563 result = true;
564 }
565 }
566 }
567 return result;
568 }
569
570 //
571 // Post an event to a single script
572 //
573 public bool PostScriptEvent(LLUUID itemID, XEventParams p)
574 {
575 if(m_Scripts.ContainsKey(itemID))
576 {
577 XScriptInstance instance = m_Scripts[itemID];
578 if(instance != null)
579 instance.PostEvent(p);
580 return true;
581 }
582 return false;
583 }
584
585 public Assembly OnAssemblyResolve(object sender,
586 ResolveEventArgs args)
587 {
588 if(!(sender is System.AppDomain))
589 return null;
590
591 string[] pathList=new string[] {"bin", "ScriptEngines",
592 Path.Combine("ScriptEngines",
593 m_Scene.RegionInfo.RegionID.ToString())};
594
595 string assemblyName = args.Name;
596 if(assemblyName.IndexOf(",") != -1)
597 assemblyName=args.Name.Substring(0, args.Name.IndexOf(","));
598
599 foreach (string s in pathList)
600 {
601 string path=Path.Combine(Directory.GetCurrentDirectory(),
602 Path.Combine(s, assemblyName))+".dll";
603
604 if(File.Exists(path))
605 return Assembly.LoadFrom(path);
606 }
607
608 return null;
609 }
610
611 private XScriptInstance GetInstance(LLUUID itemID)
612 {
613 XScriptInstance instance;
614 lock(m_Scripts)
615 {
616 if(!m_Scripts.ContainsKey(itemID))
617 return null;
618 instance = m_Scripts[itemID];
619 }
620 return instance;
621 }
622
623 public void SetScriptState(LLUUID itemID, bool running)
624 {
625 XScriptInstance instance = GetInstance(itemID);
626 if(instance != null)
627 {
628 if(running)
629 instance.Start();
630 else
631 instance.Stop(500);
632 }
633 }
634
635 public bool GetScriptState(LLUUID itemID)
636 {
637 XScriptInstance instance = GetInstance(itemID);
638 if(instance != null)
639 return instance.Running;
640 return false;
641 }
642
643 public void ResetScript(LLUUID itemID)
644 {
645 XScriptInstance instance = GetInstance(itemID);
646 if(instance != null)
647 instance.ResetScript();
648 }
649
650 public XDetectParams GetDetectParams(LLUUID itemID, int idx)
651 {
652 XScriptInstance instance = GetInstance(itemID);
653 if(instance != null)
654 return instance.GetDetectParams(idx);
655 return new XDetectParams();
656 }
657
658 public LLUUID GetDetectID(LLUUID itemID, int idx)
659 {
660 XScriptInstance instance = GetInstance(itemID);
661 if(instance != null)
662 return instance.GetDetectID(idx);
663 return LLUUID.Zero;
664 }
665 }
666
667 public struct XDetectParams
668 {
669 public LLUUID Key;
670 public LSL_Types.Vector3 OffsetPos;
671 }
672
673 public class XEventParams
674 {
675 public XEventParams(string eventName, Object[] eventParams, XDetectParams[] detectParams)
676 {
677 EventName=eventName;
678 Params=eventParams;
679 DetectParams=detectParams;
680 }
681
682 public string EventName;
683 public Object[] Params;
684 public XDetectParams[] DetectParams;
685 }
686
687 public class XScriptInstance
688 {
689 private XEngine m_Engine;
690 private IWorkItemResult m_CurrentResult=null;
691 private Queue m_EventQueue=new Queue(32);
692 private bool m_RunEvents=false;
693 private LLUUID m_ItemID;
694 private uint m_LocalID;
695 private LLUUID m_ObjectID;
696 private LLUUID m_AssetID;
697 private IScript m_Script;
698 private LSL_ScriptCommands m_LSLCommands;
699 private OSSL_ScriptCommands m_OSSLCommands;
700 private Executor m_Executor;
701 private LLUUID m_AppDomain;
702 private XDetectParams[] m_DetectParams;
703 private bool m_TimerQueued;
704 private DateTime m_EventStart;
705 private bool m_InEvent;
706
707 // Script state
708 private string m_State="default";
709
710 public Object[] PluginData = new Object[0];
711
712 public bool Running
713 {
714 get { return m_RunEvents; }
715 }
716
717 public string State
718 {
719 get { return m_State; }
720 set { m_State = value; }
721 }
722
723 public XEngine Engine
724 {
725 get { return m_Engine; }
726 }
727
728 public LLUUID AppDomain
729 {
730 get { return m_AppDomain; }
731 set { m_AppDomain = value; }
732 }
733
734 public LLUUID ItemID
735 {
736 get { return m_ItemID; }
737 }
738
739 public LLUUID ObjectID
740 {
741 get { return m_ObjectID; }
742 }
743
744 public uint LocalID
745 {
746 get { return m_LocalID; }
747 }
748
749 public LLUUID AssetID
750 {
751 get { return m_AssetID; }
752 }
753
754 public Queue EventQueue
755 {
756 get { return m_EventQueue; }
757 }
758
759 public void ClearQueue()
760 {
761 m_TimerQueued = false;
762 m_EventQueue.Clear();
763 }
764
765 public XScriptInstance(XEngine engine, uint localID, LLUUID objectID,
766 LLUUID itemID, LLUUID assetID, string assembly, AppDomain dom)
767 {
768 m_Engine=engine;
769
770 m_LocalID = localID;
771 m_ObjectID = objectID;
772 m_ItemID = itemID;
773 m_AssetID = assetID;
774
775 SceneObjectPart part=engine.World.GetSceneObjectPart(localID);
776 if(part == null)
777 {
778 engine.Log.Error("[XEngine] SceneObjectPart unavailable. Script NOT started.");
779 return;
780 }
781
782 m_LSLCommands = new LSL_ScriptCommands(engine, this, part, localID,
783 itemID);
784 m_OSSLCommands = new OSSL_ScriptCommands(engine, this, part,
785 localID, itemID);
786
787 try
788 {
789 m_Script = (IScript)dom.CreateInstanceAndUnwrap(
790 Path.GetFileNameWithoutExtension(assembly),
791 "SecondLife.Script");
792 }
793 catch (Exception e)
794 {
795 m_Engine.Log.ErrorFormat("[XEngine] Error loading assembly {0}\n"+e.ToString(), assembly);
796 }
797
798 try
799 {
800 m_Script.Start(m_LSLCommands, m_OSSLCommands);
801
802 m_Executor = new Executor(m_Script);
803
804// m_Engine.Log.Debug("[XEngine] Script instance created");
805
806 part.SetScriptEvents(m_ItemID,
807 (int)m_Executor.GetStateEventFlags());
808 }
809 catch (Exception e)
810 {
811 m_Engine.Log.Error("Error loading script instance\n"+e.ToString());
812 }
813
814 string savedState = assembly+".state";
815 if(File.Exists(savedState))
816 {
817 string xml = String.Empty;
818
819 try
820 {
821 FileInfo fi = new FileInfo(savedState);
822 int size=(int)fi.Length;
823 if(size < 130000)
824 {
825 using (FileStream fs = File.Open(savedState,
826 FileMode.Open, FileAccess.Read, FileShare.None))
827 {
828 System.Text.ASCIIEncoding enc =
829 new System.Text.ASCIIEncoding();
830
831 Byte[] data=new Byte[size];
832 fs.Read(data, 0, size);
833
834 xml=enc.GetString(data);
835
836 ScriptSerializer.Deserialize(xml, this);
837
838 m_Engine.m_ASYNCLSLCommandManager.CreateFromData(
839 m_LocalID, m_ItemID, m_ObjectID,
840 PluginData);
841 }
842 }
843 else
844 {
845 m_Engine.Log.Error("Unable to load script state: Memory limit exceeded");
846 PostEvent(new XEventParams("state_entry",
847 new Object[0], new XDetectParams[0]));
848 }
849 }
850 catch (Exception e)
851 {
852 m_Engine.Log.ErrorFormat("Unable to load script state from xml: {0}\n"+e.ToString(), xml);
853 PostEvent(new XEventParams("state_entry",
854 new Object[0], new XDetectParams[0]));
855 }
856 }
857 else
858 {
859 PostEvent(new XEventParams("state_entry",
860 new Object[0], new XDetectParams[0]));
861 }
862 Start();
863 }
864
865 public void VarDump(Dictionary<string, object> vars)
866 {
867 Console.WriteLine("Variable dump for script {0}", m_ItemID.ToString());
868 foreach (KeyValuePair<string, object> v in vars)
869 {
870 Console.WriteLine("Variable: {0} = '{1}'", v. Key,
871 v.Value.ToString());
872 }
873 }
874
875 public void Start()
876 {
877 lock(m_EventQueue)
878 {
879 if(Running)
880 return;
881
882 m_RunEvents=true;
883
884 if(m_EventQueue.Count > 0)
885 {
886 if(m_CurrentResult == null)
887 m_CurrentResult=m_Engine.QueueEventHandler(this);
888 }
889 }
890 }
891
892 public bool Stop(int timeout)
893 {
894 IWorkItemResult result;
895
896 lock(m_EventQueue)
897 {
898 if(!Running)
899 return true;
900
901 if(m_CurrentResult == null)
902 {
903 m_RunEvents=false;
904 return true;
905 }
906
907 if(m_CurrentResult.Cancel())
908 {
909 m_CurrentResult=null;
910 m_RunEvents=false;
911 return true;
912 }
913
914 result=m_CurrentResult;
915 m_RunEvents=false;
916 }
917
918 if(SmartThreadPool.WaitAll(new IWorkItemResult[] {result}, new TimeSpan((long)timeout*100000), false))
919 {
920 return true;
921 }
922
923 lock(m_EventQueue)
924 {
925 if(m_CurrentResult != null)
926 m_CurrentResult.Abort();
927 else
928 return true;
929 }
930
931 return true;
932 }
933
934 public void SetState(string state)
935 {
936 PostEvent(new XEventParams("state_exit", new Object[0],
937 new XDetectParams[0]));
938 PostEvent(new XEventParams("state", new Object[] { state },
939 new XDetectParams[0]));
940 PostEvent(new XEventParams("state_entry", new Object[0],
941 new XDetectParams[0]));
942 }
943
944 public void PostEvent(XEventParams data)
945 {
946 lock(m_EventQueue)
947 {
948 if(m_EventQueue.Count >= m_Engine.MaxScriptQueue)
949 return;
950
951 m_EventQueue.Enqueue(data);
952 if(data.EventName == "timer")
953 {
954 if(m_TimerQueued)
955 return;
956 m_TimerQueued = true;
957 }
958
959 if(!m_RunEvents)
960 return;
961
962 if(m_CurrentResult == null)
963 {
964 m_CurrentResult=m_Engine.QueueEventHandler(this);
965 }
966 }
967 }
968
969 public object EventProcessor()
970 {
971 XEventParams data=null;
972
973 lock(m_EventQueue)
974 {
975 data=(XEventParams)m_EventQueue.Dequeue();
976 if(data == null) // Shouldn't happen
977 {
978 m_CurrentResult=null;
979 return 0;
980 }
981 if(data.EventName == "timer")
982 m_TimerQueued = false;
983 }
984
985 m_DetectParams=data.DetectParams;
986
987 if(data.EventName == "state") // Hardcoded state change
988 {
989 m_State=data.Params[0].ToString();
990 m_Engine.m_ASYNCLSLCommandManager.RemoveScript(
991 m_LocalID, m_ItemID);
992
993 SceneObjectPart part=m_Engine.World.GetSceneObjectPart(
994 m_LocalID);
995 if(part != null)
996 {
997 part.SetScriptEvents(m_ItemID,
998 (int)m_Executor.GetStateEventFlags());
999 }
1000 }
1001 else
1002 {
1003// m_Engine.Log.DebugFormat("[XEngine] Processed event {0}", data.EventName);
1004 SceneObjectPart part=m_Engine.World.GetSceneObjectPart(
1005 m_LocalID);
1006 try
1007 {
1008 m_EventStart = DateTime.Now;
1009 m_InEvent = true;
1010 m_Executor.ExecuteEvent(data.EventName, data.Params);
1011 m_InEvent = false;
1012 }
1013 catch (Exception e)
1014 {
1015 m_InEvent = false;
1016 if(e is System.Threading.ThreadAbortException)
1017 {
1018 lock(m_EventQueue)
1019 {
1020 if((m_EventQueue.Count > 0) && m_RunEvents)
1021 {
1022 m_CurrentResult=m_Engine.QueueEventHandler(this);
1023 }
1024 else
1025 {
1026 m_CurrentResult=null;
1027 }
1028 }
1029
1030 m_DetectParams=null;
1031
1032 return 0;
1033 }
1034
1035 try
1036 {
1037 // DISPLAY ERROR INWORLD
1038 string text = "Runtime error:\n" + e.ToString();
1039 if (text.Length > 1400)
1040 text = text.Substring(0, 1400);
1041 m_Engine.World.SimChat(Helpers.StringToField(text),
1042 ChatTypeEnum.DebugChannel, 2147483647,
1043 part.AbsolutePosition,
1044 part.Name, part.UUID, false);
1045 }
1046 catch (Exception e2) // LEGIT: User Scripting
1047 {
1048 m_Engine.Log.Error("[XEngine]: "+
1049 "Error displaying error in-world: " +
1050 e2.ToString());
1051 m_Engine.Log.Error("[XEngine]: " +
1052 "Errormessage: Error compiling script:\r\n" +
1053 e.ToString());
1054 }
1055 }
1056 }
1057
1058 lock(m_EventQueue)
1059 {
1060 if((m_EventQueue.Count > 0) && m_RunEvents)
1061 {
1062 m_CurrentResult=m_Engine.QueueEventHandler(this);
1063 }
1064 else
1065 {
1066 m_CurrentResult=null;
1067 }
1068 }
1069
1070 m_DetectParams=null;
1071
1072 return 0;
1073 }
1074
1075 public int EventTime()
1076 {
1077 if(!m_InEvent)
1078 return 0;
1079
1080 return (DateTime.Now - m_EventStart).Seconds;
1081 }
1082
1083 public void ResetScript()
1084 {
1085 Stop(0);
1086 m_Engine.m_ASYNCLSLCommandManager.RemoveScript(m_LocalID, m_ItemID);
1087 m_EventQueue.Clear();
1088 m_Script.ResetVars();
1089 m_State = "default";
1090 Start();
1091 PostEvent(new XEventParams("state_entry",
1092 new Object[0], new XDetectParams[0]));
1093 }
1094
1095 public Dictionary<string, object> GetVars()
1096 {
1097 return m_Script.GetVars();
1098 }
1099
1100 public void SetVars(Dictionary<string, object> vars)
1101 {
1102 m_Script.SetVars(vars);
1103 }
1104
1105 public XDetectParams GetDetectParams(int idx)
1106 {
1107 if(idx < 0 || idx >= m_DetectParams.Length)
1108 return new XDetectParams();
1109
1110 return m_DetectParams[idx];
1111 }
1112
1113 public LLUUID GetDetectID(int idx)
1114 {
1115 if(idx < 0 || idx >= m_DetectParams.Length)
1116 return LLUUID.Zero;
1117
1118 return m_DetectParams[idx].Key;
1119 }
1120
1121 public void SaveState(string assembly)
1122 {
1123 PluginData =
1124 m_Engine.m_ASYNCLSLCommandManager.GetSerializationData(
1125 m_ItemID);
1126
1127 string xml=ScriptSerializer.Serialize(this);
1128
1129 try
1130 {
1131 FileStream fs = File.Create(assembly+".state");
1132 System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
1133 Byte[] buf=enc.GetBytes(xml);
1134 fs.Write(buf, 0, buf.Length);
1135 fs.Close();
1136 }
1137 catch(Exception)
1138 {
1139 return;
1140 }
1141 }
1142 }
1143
1144 public class ScriptSerializer
1145 {
1146 public static string Serialize(XScriptInstance instance)
1147 {
1148 instance.Stop(50);
1149
1150 XmlDocument xmldoc = new XmlDocument();
1151
1152 XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration,
1153 "", "");
1154 xmldoc.AppendChild(xmlnode);
1155
1156 XmlElement rootElement = xmldoc.CreateElement("", "ScriptState",
1157 "");
1158 xmldoc.AppendChild(rootElement);
1159
1160 XmlElement state = xmldoc.CreateElement("", "State", "");
1161 state.AppendChild(xmldoc.CreateTextNode(instance.State));
1162
1163 rootElement.AppendChild(state);
1164
1165 Dictionary<string, Object> vars = instance.GetVars();
1166
1167 XmlElement variables = xmldoc.CreateElement("", "Variables", "");
1168
1169 foreach (KeyValuePair<string, Object> var in vars)
1170 WriteTypedValue(xmldoc, variables, "Variable", var.Key,
1171 var.Value);
1172
1173 rootElement.AppendChild(variables);
1174
1175 XmlElement queue = xmldoc.CreateElement("", "Queue", "");
1176
1177 int count = instance.EventQueue.Count;
1178
1179 while(count > 0)
1180 {
1181 XEventParams ep = (XEventParams)instance.EventQueue.Dequeue();
1182 instance.EventQueue.Enqueue(ep);
1183 count--;
1184
1185 XmlElement item = xmldoc.CreateElement("", "Item", "");
1186 XmlAttribute itemEvent = xmldoc.CreateAttribute("", "event",
1187 "");
1188 itemEvent.Value=ep.EventName;
1189 item.Attributes.Append(itemEvent);
1190
1191 XmlElement parms = xmldoc.CreateElement("", "Params", "");
1192
1193 foreach (Object o in ep.Params)
1194 WriteTypedValue(xmldoc, parms, "Param", String.Empty, o);
1195
1196 item.AppendChild(parms);
1197
1198 XmlElement detect = xmldoc.CreateElement("", "Detected", "");
1199
1200 foreach (XDetectParams det in ep.DetectParams)
1201 {
1202 XmlElement objectElem = xmldoc.CreateElement("", "Object",
1203 "");
1204 XmlAttribute pos = xmldoc.CreateAttribute("", "pos", "");
1205 pos.Value=det.OffsetPos.ToString();
1206 objectElem.Attributes.Append(pos);
1207 objectElem.AppendChild(
1208 xmldoc.CreateTextNode(det.Key.ToString()));
1209
1210 detect.AppendChild(objectElem);
1211 }
1212
1213 item.AppendChild(detect);
1214
1215 queue.AppendChild(item);
1216 }
1217
1218 rootElement.AppendChild(queue);
1219
1220 XmlNode plugins = xmldoc.CreateElement("", "Plugins", "");
1221 if(instance.PluginData.Length > 0)
1222 DumpList(xmldoc, plugins,
1223 new LSL_Types.list(instance.PluginData));
1224
1225 rootElement.AppendChild(plugins);
1226
1227 instance.Start();
1228
1229 return xmldoc.InnerXml;
1230 }
1231
1232 public static void Deserialize(string xml, XScriptInstance instance)
1233 {
1234 XmlDocument doc = new XmlDocument();
1235
1236 Dictionary<string, object> vars = instance.GetVars();
1237
1238 instance.PluginData = new Object[0];
1239
1240 doc.LoadXml(xml);
1241
1242 XmlNodeList rootL = doc.GetElementsByTagName("ScriptState");
1243 if(rootL.Count != 1)
1244 {
1245 return;
1246 }
1247 XmlNode rootNode = rootL[0];
1248
1249 if(rootNode != null)
1250 {
1251 object varValue;
1252 XmlNodeList partL = rootNode.ChildNodes;
1253
1254 foreach (XmlNode part in partL)
1255 {
1256 switch(part.Name)
1257 {
1258 case "State":
1259 instance.State=part.InnerText;
1260 break;
1261 case "Variables":
1262 XmlNodeList varL = part.ChildNodes;
1263 foreach (XmlNode var in varL)
1264 {
1265 string varName;
1266 varValue=ReadTypedValue(var, out varName);
1267
1268 if(vars.ContainsKey(varName))
1269 vars[varName] = varValue;
1270 }
1271 instance.SetVars(vars);
1272 break;
1273 case "Queue":
1274 XmlNodeList itemL = part.ChildNodes;
1275 foreach (XmlNode item in itemL)
1276 {
1277 List<Object> parms = new List<Object>();
1278 List<XDetectParams> detected =
1279 new List<XDetectParams>();
1280
1281 string eventName =
1282 item.Attributes.GetNamedItem("event").Value;
1283 XmlNodeList eventL = item.ChildNodes;
1284 foreach (XmlNode evt in eventL)
1285 {
1286 switch(evt.Name)
1287 {
1288 case "Params":
1289 XmlNodeList prms = evt.ChildNodes;
1290 foreach (XmlNode pm in prms)
1291 parms.Add(ReadTypedValue(pm));
1292
1293 break;
1294 case "Detected":
1295 XmlNodeList detL = evt.ChildNodes;
1296 foreach (XmlNode det in detL)
1297 {
1298 string vect =
1299 det.Attributes.GetNamedItem(
1300 "pos").Value;
1301 LSL_Types.Vector3 v =
1302 new LSL_Types.Vector3(vect);
1303 LLUUID uuid = new LLUUID();
1304 LLUUID.TryParse(det.InnerText,
1305 out uuid);
1306
1307 XDetectParams d;
1308 d.Key = uuid;
1309 d.OffsetPos = v;
1310
1311 detected.Add(d);
1312 }
1313 break;
1314 }
1315 }
1316 XEventParams ep = new XEventParams(
1317 eventName, parms.ToArray(),
1318 detected.ToArray());
1319 instance.EventQueue.Enqueue(ep);
1320 }
1321 break;
1322 case "Plugins":
1323 instance.PluginData = ReadList(part).Data;
1324 break;
1325 }
1326 }
1327 }
1328 }
1329
1330 private static void DumpList(XmlDocument doc, XmlNode parent,
1331 LSL_Types.list l)
1332 {
1333 foreach (Object o in l.Data)
1334 WriteTypedValue(doc, parent, "ListItem", "", o);
1335 }
1336
1337 private static LSL_Types.list ReadList(XmlNode parent)
1338 {
1339 List<Object> olist = new List<Object>();
1340
1341 XmlNodeList itemL = parent.ChildNodes;
1342 foreach(XmlNode item in itemL)
1343 olist.Add(ReadTypedValue(item));
1344
1345 return new LSL_Types.list(olist.ToArray());
1346 }
1347
1348 private static void WriteTypedValue(XmlDocument doc, XmlNode parent,
1349 string tag, string name, object value)
1350 {
1351 Type t=value.GetType();
1352 XmlAttribute typ = doc.CreateAttribute("", "type", "");
1353 XmlNode n = doc.CreateElement("", tag, "");
1354
1355 if(value is LSL_Types.list)
1356 {
1357 typ.Value = "list";
1358 n.Attributes.Append(typ);
1359
1360 DumpList(doc, n, (LSL_Types.list) value);
1361
1362 if(name != String.Empty)
1363 {
1364 XmlAttribute nam = doc.CreateAttribute("", "name", "");
1365 nam.Value = name;
1366 n.Attributes.Append(nam);
1367 }
1368
1369 parent.AppendChild(n);
1370 return;
1371 }
1372
1373 n.AppendChild(doc.CreateTextNode(value.ToString()));
1374
1375 typ.Value = t.ToString();
1376 n.Attributes.Append(typ);
1377 if(name != String.Empty)
1378 {
1379 XmlAttribute nam = doc.CreateAttribute("", "name", "");
1380 nam.Value = name;
1381 n.Attributes.Append(nam);
1382 }
1383
1384 parent.AppendChild(n);
1385 }
1386
1387 private static object ReadTypedValue(XmlNode tag, out string name)
1388 {
1389 name = tag.Attributes.GetNamedItem("name").Value;
1390
1391 return ReadTypedValue(tag);
1392 }
1393
1394 private static object ReadTypedValue(XmlNode tag)
1395 {
1396 Object varValue;
1397 string assembly;
1398
1399 string itemType = tag.Attributes.GetNamedItem("type").Value;
1400
1401 if(itemType == "list")
1402 return ReadList(tag);
1403
1404 if(itemType == "libsecondlife.LLUUID")
1405 {
1406 LLUUID val = new LLUUID();
1407 LLUUID.TryParse(tag.InnerText, out val);
1408
1409 return val;
1410 }
1411
1412 Type itemT = Type.GetType(itemType);
1413 if(itemT == null)
1414 {
1415 Object[] args =
1416 new Object[] { tag.InnerText };
1417
1418 assembly = itemType+", OpenSim.Region.ScriptEngine.XEngine.Script";
1419 itemT = Type.GetType(assembly);
1420 if(itemT == null)
1421 return null;
1422
1423 varValue = Activator.CreateInstance(itemT, args);
1424
1425 if(varValue == null)
1426 return null;
1427 }
1428 else
1429 {
1430 varValue = Convert.ChangeType(tag.InnerText, itemT);
1431 }
1432 return varValue;
1433 }
1434 }
1435}
diff --git a/ThirdParty/SmartThreadPool/AssemblyInfo.cs b/ThirdParty/SmartThreadPool/AssemblyInfo.cs
new file mode 100644
index 0000000..765bd30
--- /dev/null
+++ b/ThirdParty/SmartThreadPool/AssemblyInfo.cs
@@ -0,0 +1,61 @@
1using System;
2using System.Reflection;
3using System.Runtime.InteropServices;
4
5//
6// General Information about an assembly is controlled through the following
7// set of attributes. Change these attribute values to modify the information
8// associated with an assembly.
9//
10[assembly: AssemblyTitle("")]
11[assembly: AssemblyDescription("")]
12[assembly: AssemblyConfiguration("")]
13[assembly: AssemblyCompany("")]
14[assembly: AssemblyProduct("")]
15[assembly: AssemblyCopyright("")]
16[assembly: AssemblyTrademark("")]
17[assembly: AssemblyCulture("")]
18[assembly: ComVisible(false)]
19[assembly: CLSCompliant(true)]
20
21//
22// Version information for an assembly consists of the following four values:
23//
24// Major Version
25// Minor Version
26// Build Number
27// Revision
28//
29// You can specify all the values or you can default the Revision and Build Numbers
30// by using the '*' as shown below:
31
32[assembly: AssemblyVersion("1.0.*")]
33
34//
35// In order to sign your assembly you must specify a key to use. Refer to the
36// Microsoft .NET Framework documentation for more information on assembly signing.
37//
38// Use the attributes below to control which key is used for signing.
39//
40// Notes:
41// (*) If no key is specified, the assembly is not signed.
42// (*) KeyName refers to a key that has been installed in the Crypto Service
43// Provider (CSP) on your machine. KeyFile refers to a file which contains
44// a key.
45// (*) If the KeyFile and the KeyName values are both specified, the
46// following processing occurs:
47// (1) If the KeyName can be found in the CSP, that key is used.
48// (2) If the KeyName does not exist and the KeyFile does exist, the key
49// in the KeyFile is installed into the CSP and used.
50// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
51// When specifying the KeyFile, the location of the KeyFile should be
52// relative to the project output directory which is
53// %Project Directory%\obj\<configuration>. For example, if your KeyFile is
54// located in the project directory, you would specify the AssemblyKeyFile
55// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
56// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
57// documentation for more information on this.
58//
59[assembly: AssemblyDelaySign(false)]
60[assembly: AssemblyKeyFile("")]
61[assembly: AssemblyKeyName("")]
diff --git a/ThirdParty/SmartThreadPool/CallerThreadContext.cs b/ThirdParty/SmartThreadPool/CallerThreadContext.cs
new file mode 100644
index 0000000..6ea53f6
--- /dev/null
+++ b/ThirdParty/SmartThreadPool/CallerThreadContext.cs
@@ -0,0 +1,223 @@
1using System;
2using System.Diagnostics;
3using System.Threading;
4using System.Reflection;
5using System.Web;
6using System.Runtime.Remoting.Messaging;
7
8
9namespace Amib.Threading
10{
11 #region CallerThreadContext class
12
13 /// <summary>
14 /// This class stores the caller call context in order to restore
15 /// it when the work item is executed in the thread pool environment.
16 /// </summary>
17 internal class CallerThreadContext
18 {
19 #region Prepare reflection information
20
21 // Cached type information.
22 private static MethodInfo getLogicalCallContextMethodInfo =
23 typeof(Thread).GetMethod("GetLogicalCallContext", BindingFlags.Instance | BindingFlags.NonPublic);
24
25 private static MethodInfo setLogicalCallContextMethodInfo =
26 typeof(Thread).GetMethod("SetLogicalCallContext", BindingFlags.Instance | BindingFlags.NonPublic);
27
28 private static string HttpContextSlotName = GetHttpContextSlotName();
29
30 private static string GetHttpContextSlotName()
31 {
32 FieldInfo fi = typeof(HttpContext).GetField("CallContextSlotName", BindingFlags.Static | BindingFlags.NonPublic);
33
34 if( fi != null )
35 return (string)fi.GetValue(null);
36 else // Use the default "HttpContext" slot name
37 return "HttpContext";
38 }
39
40 #endregion
41
42 #region Private fields
43
44 private HttpContext _httpContext = null;
45 private LogicalCallContext _callContext = null;
46
47 #endregion
48
49 /// <summary>
50 /// Constructor
51 /// </summary>
52 private CallerThreadContext()
53 {
54 }
55
56 public bool CapturedCallContext
57 {
58 get
59 {
60 return (null != _callContext);
61 }
62 }
63
64 public bool CapturedHttpContext
65 {
66 get
67 {
68 return (null != _httpContext);
69 }
70 }
71
72 /// <summary>
73 /// Captures the current thread context
74 /// </summary>
75 /// <returns></returns>
76 public static CallerThreadContext Capture(
77 bool captureCallContext,
78 bool captureHttpContext)
79 {
80 Debug.Assert(captureCallContext || captureHttpContext);
81
82 CallerThreadContext callerThreadContext = new CallerThreadContext();
83
84 // TODO: In NET 2.0, redo using the new feature of ExecutionContext class - Capture()
85 // Capture Call Context
86 if(captureCallContext && (getLogicalCallContextMethodInfo != null))
87 {
88 callerThreadContext._callContext = (LogicalCallContext)getLogicalCallContextMethodInfo.Invoke(Thread.CurrentThread, null);
89 if (callerThreadContext._callContext != null)
90 {
91 callerThreadContext._callContext = (LogicalCallContext)callerThreadContext._callContext.Clone();
92 }
93 }
94
95 // Capture httpContext
96 if (captureHttpContext && (null != HttpContext.Current))
97 {
98 callerThreadContext._httpContext = HttpContext.Current;
99 }
100
101 return callerThreadContext;
102 }
103
104 /// <summary>
105 /// Applies the thread context stored earlier
106 /// </summary>
107 /// <param name="callerThreadContext"></param>
108 public static void Apply(CallerThreadContext callerThreadContext)
109 {
110 if (null == callerThreadContext)
111 {
112 throw new ArgumentNullException("callerThreadContext");
113 }
114
115 // Todo: In NET 2.0, redo using the new feature of ExecutionContext class - Run()
116 // Restore call context
117 if ((callerThreadContext._callContext != null) && (setLogicalCallContextMethodInfo != null))
118 {
119 setLogicalCallContextMethodInfo.Invoke(Thread.CurrentThread, new object[] { callerThreadContext._callContext });
120 }
121
122 // Restore HttpContext
123 if (callerThreadContext._httpContext != null)
124 {
125 CallContext.SetData(HttpContextSlotName, callerThreadContext._httpContext);
126 }
127 }
128 }
129
130 #endregion
131
132}
133
134
135/*
136// Ami Bar
137// amibar@gmail.com
138
139using System;
140using System.Threading;
141using System.Globalization;
142using System.Security.Principal;
143using System.Reflection;
144using System.Runtime.Remoting.Contexts;
145
146namespace Amib.Threading.Internal
147{
148 #region CallerThreadContext class
149
150 /// <summary>
151 /// This class stores the caller thread context in order to restore
152 /// it when the work item is executed in the context of the thread
153 /// from the pool.
154 /// Note that we can't store the thread's CompressedStack, because
155 /// it throws a security exception
156 /// </summary>
157 public class CallerThreadContext
158 {
159 private CultureInfo _culture = null;
160 private CultureInfo _cultureUI = null;
161 private IPrincipal _principal;
162 private System.Runtime.Remoting.Contexts.Context _context;
163
164 private static FieldInfo _fieldInfo = GetFieldInfo();
165
166 private static FieldInfo GetFieldInfo()
167 {
168 Type threadType = typeof(Thread);
169 return threadType.GetField(
170 "m_Context",
171 BindingFlags.Instance | BindingFlags.NonPublic);
172 }
173
174 /// <summary>
175 /// Constructor
176 /// </summary>
177 private CallerThreadContext()
178 {
179 }
180
181 /// <summary>
182 /// Captures the current thread context
183 /// </summary>
184 /// <returns></returns>
185 public static CallerThreadContext Capture()
186 {
187 CallerThreadContext callerThreadContext = new CallerThreadContext();
188
189 Thread thread = Thread.CurrentThread;
190 callerThreadContext._culture = thread.CurrentCulture;
191 callerThreadContext._cultureUI = thread.CurrentUICulture;
192 callerThreadContext._principal = Thread.CurrentPrincipal;
193 callerThreadContext._context = Thread.CurrentContext;
194 return callerThreadContext;
195 }
196
197 /// <summary>
198 /// Applies the thread context stored earlier
199 /// </summary>
200 /// <param name="callerThreadContext"></param>
201 public static void Apply(CallerThreadContext callerThreadContext)
202 {
203 Thread thread = Thread.CurrentThread;
204 thread.CurrentCulture = callerThreadContext._culture;
205 thread.CurrentUICulture = callerThreadContext._cultureUI;
206 Thread.CurrentPrincipal = callerThreadContext._principal;
207
208 // Uncomment the following block to enable the Thread.CurrentThread
209/*
210 if (null != _fieldInfo)
211 {
212 _fieldInfo.SetValue(
213 Thread.CurrentThread,
214 callerThreadContext._context);
215 }
216* /
217 }
218 }
219
220 #endregion
221}
222*/
223
diff --git a/ThirdParty/SmartThreadPool/Exceptions.cs b/ThirdParty/SmartThreadPool/Exceptions.cs
new file mode 100644
index 0000000..c454709
--- /dev/null
+++ b/ThirdParty/SmartThreadPool/Exceptions.cs
@@ -0,0 +1,81 @@
1// Ami Bar
2// amibar@gmail.com
3
4using System;
5using System.Runtime.Serialization;
6
7namespace Amib.Threading
8{
9 #region Exceptions
10
11 /// <summary>
12 /// Represents an exception in case IWorkItemResult.GetResult has been canceled
13 /// </summary>
14 [Serializable]
15 public sealed class WorkItemCancelException : ApplicationException
16 {
17 public WorkItemCancelException() : base()
18 {
19 }
20
21 public WorkItemCancelException(string message) : base(message)
22 {
23 }
24
25 public WorkItemCancelException(string message, Exception e) : base(message, e)
26 {
27 }
28
29 public WorkItemCancelException(SerializationInfo si, StreamingContext sc) : base(si, sc)
30 {
31 }
32 }
33
34 /// <summary>
35 /// Represents an exception in case IWorkItemResult.GetResult has been timed out
36 /// </summary>
37 [Serializable]
38 public sealed class WorkItemTimeoutException : ApplicationException
39 {
40 public WorkItemTimeoutException() : base()
41 {
42 }
43
44 public WorkItemTimeoutException(string message) : base(message)
45 {
46 }
47
48 public WorkItemTimeoutException(string message, Exception e) : base(message, e)
49 {
50 }
51
52 public WorkItemTimeoutException(SerializationInfo si, StreamingContext sc) : base(si, sc)
53 {
54 }
55 }
56
57 /// <summary>
58 /// Represents an exception in case IWorkItemResult.GetResult has been timed out
59 /// </summary>
60 [Serializable]
61 public sealed class WorkItemResultException : ApplicationException
62 {
63 public WorkItemResultException() : base()
64 {
65 }
66
67 public WorkItemResultException(string message) : base(message)
68 {
69 }
70
71 public WorkItemResultException(string message, Exception e) : base(message, e)
72 {
73 }
74
75 public WorkItemResultException(SerializationInfo si, StreamingContext sc) : base(si, sc)
76 {
77 }
78 }
79
80 #endregion
81}
diff --git a/ThirdParty/SmartThreadPool/Interfaces.cs b/ThirdParty/SmartThreadPool/Interfaces.cs
new file mode 100644
index 0000000..f1c1fcf
--- /dev/null
+++ b/ThirdParty/SmartThreadPool/Interfaces.cs
@@ -0,0 +1,271 @@
1// Ami Bar
2// amibar@gmail.com
3
4using System;
5using System.Threading;
6
7namespace Amib.Threading
8{
9 #region Delegates
10
11 /// <summary>
12 /// A delegate that represents the method to run as the work item
13 /// </summary>
14 /// <param name="state">A state object for the method to run</param>
15 public delegate object WorkItemCallback(object state);
16
17 /// <summary>
18 /// A delegate to call after the WorkItemCallback completed
19 /// </summary>
20 /// <param name="wir">The work item result object</param>
21 public delegate void PostExecuteWorkItemCallback(IWorkItemResult wir);
22
23 /// <summary>
24 /// A delegate to call when a WorkItemsGroup becomes idle
25 /// </summary>
26 /// <param name="workItemsGroup">A reference to the WorkItemsGroup that became idle</param>
27 public delegate void WorkItemsGroupIdleHandler(IWorkItemsGroup workItemsGroup);
28
29 #endregion
30
31 #region WorkItem Priority
32
33 public enum WorkItemPriority
34 {
35 Lowest,
36 BelowNormal,
37 Normal,
38 AboveNormal,
39 Highest,
40 }
41
42 #endregion
43
44 #region IHasWorkItemPriority interface
45
46 public interface IHasWorkItemPriority
47 {
48 WorkItemPriority WorkItemPriority { get; }
49 }
50
51 #endregion
52
53 #region IWorkItemsGroup interface
54
55 /// <summary>
56 /// IWorkItemsGroup interface
57 /// </summary>
58 public interface IWorkItemsGroup
59 {
60 /// <summary>
61 /// Get/Set the name of the WorkItemsGroup
62 /// </summary>
63 string Name { get; set; }
64
65 IWorkItemResult QueueWorkItem(WorkItemCallback callback);
66 IWorkItemResult QueueWorkItem(WorkItemCallback callback, WorkItemPriority workItemPriority);
67 IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state);
68 IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, WorkItemPriority workItemPriority);
69 IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback);
70 IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback, WorkItemPriority workItemPriority);
71 IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback, CallToPostExecute callToPostExecute);
72 IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback, CallToPostExecute callToPostExecute, WorkItemPriority workItemPriority);
73
74 IWorkItemResult QueueWorkItem(WorkItemInfo workItemInfo, WorkItemCallback callback);
75 IWorkItemResult QueueWorkItem(WorkItemInfo workItemInfo, WorkItemCallback callback, object state);
76
77 void WaitForIdle();
78 bool WaitForIdle(TimeSpan timeout);
79 bool WaitForIdle(int millisecondsTimeout);
80
81 int WaitingCallbacks { get; }
82 event WorkItemsGroupIdleHandler OnIdle;
83
84 void Cancel();
85 void Start();
86 }
87
88 #endregion
89
90 #region CallToPostExecute enumerator
91
92 [Flags]
93 public enum CallToPostExecute
94 {
95 Never = 0x00,
96 WhenWorkItemCanceled = 0x01,
97 WhenWorkItemNotCanceled = 0x02,
98 Always = WhenWorkItemCanceled | WhenWorkItemNotCanceled,
99 }
100
101 #endregion
102
103 #region IWorkItemResult interface
104
105 /// <summary>
106 /// IWorkItemResult interface
107 /// </summary>
108 public interface IWorkItemResult
109 {
110 /// <summary>
111 /// Get the result of the work item.
112 /// If the work item didn't run yet then the caller waits.
113 /// </summary>
114 /// <returns>The result of the work item</returns>
115 object GetResult();
116
117 /// <summary>
118 /// Get the result of the work item.
119 /// If the work item didn't run yet then the caller waits until timeout.
120 /// </summary>
121 /// <returns>The result of the work item</returns>
122 /// On timeout throws WorkItemTimeoutException
123 object GetResult(
124 int millisecondsTimeout,
125 bool exitContext);
126
127 /// <summary>
128 /// Get the result of the work item.
129 /// If the work item didn't run yet then the caller waits until timeout.
130 /// </summary>
131 /// <returns>The result of the work item</returns>
132 /// On timeout throws WorkItemTimeoutException
133 object GetResult(
134 TimeSpan timeout,
135 bool exitContext);
136
137 void Abort();
138
139 /// <summary>
140 /// Get the result of the work item.
141 /// If the work item didn't run yet then the caller waits until timeout or until the cancelWaitHandle is signaled.
142 /// </summary>
143 /// <param name="millisecondsTimeout">Timeout in milliseconds, or -1 for infinite</param>
144 /// <param name="exitContext">
145 /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
146 /// </param>
147 /// <param name="cancelWaitHandle">A cancel wait handle to interrupt the blocking if needed</param>
148 /// <returns>The result of the work item</returns>
149 /// On timeout throws WorkItemTimeoutException
150 /// On cancel throws WorkItemCancelException
151 object GetResult(
152 int millisecondsTimeout,
153 bool exitContext,
154 WaitHandle cancelWaitHandle);
155
156 /// <summary>
157 /// Get the result of the work item.
158 /// If the work item didn't run yet then the caller waits until timeout or until the cancelWaitHandle is signaled.
159 /// </summary>
160 /// <returns>The result of the work item</returns>
161 /// On timeout throws WorkItemTimeoutException
162 /// On cancel throws WorkItemCancelException
163 object GetResult(
164 TimeSpan timeout,
165 bool exitContext,
166 WaitHandle cancelWaitHandle);
167
168 /// <summary>
169 /// Get the result of the work item.
170 /// If the work item didn't run yet then the caller waits.
171 /// </summary>
172 /// <param name="e">Filled with the exception if one was thrown</param>
173 /// <returns>The result of the work item</returns>
174 object GetResult(out Exception e);
175
176 /// <summary>
177 /// Get the result of the work item.
178 /// If the work item didn't run yet then the caller waits until timeout.
179 /// </summary>
180 /// <param name="e">Filled with the exception if one was thrown</param>
181 /// <returns>The result of the work item</returns>
182 /// On timeout throws WorkItemTimeoutException
183 object GetResult(
184 int millisecondsTimeout,
185 bool exitContext,
186 out Exception e);
187
188 /// <summary>
189 /// Get the result of the work item.
190 /// If the work item didn't run yet then the caller waits until timeout.
191 /// </summary>
192 /// <param name="e">Filled with the exception if one was thrown</param>
193 /// <returns>The result of the work item</returns>
194 /// On timeout throws WorkItemTimeoutException
195 object GetResult(
196 TimeSpan timeout,
197 bool exitContext,
198 out Exception e);
199
200 /// <summary>
201 /// Get the result of the work item.
202 /// If the work item didn't run yet then the caller waits until timeout or until the cancelWaitHandle is signaled.
203 /// </summary>
204 /// <param name="millisecondsTimeout">Timeout in milliseconds, or -1 for infinite</param>
205 /// <param name="exitContext">
206 /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
207 /// </param>
208 /// <param name="cancelWaitHandle">A cancel wait handle to interrupt the blocking if needed</param>
209 /// <param name="e">Filled with the exception if one was thrown</param>
210 /// <returns>The result of the work item</returns>
211 /// On timeout throws WorkItemTimeoutException
212 /// On cancel throws WorkItemCancelException
213 object GetResult(
214 int millisecondsTimeout,
215 bool exitContext,
216 WaitHandle cancelWaitHandle,
217 out Exception e);
218
219 /// <summary>
220 /// Get the result of the work item.
221 /// If the work item didn't run yet then the caller waits until timeout or until the cancelWaitHandle is signaled.
222 /// </summary>
223 /// <returns>The result of the work item</returns>
224 /// <param name="e">Filled with the exception if one was thrown</param>
225 /// On timeout throws WorkItemTimeoutException
226 /// On cancel throws WorkItemCancelException
227 object GetResult(
228 TimeSpan timeout,
229 bool exitContext,
230 WaitHandle cancelWaitHandle,
231 out Exception e);
232
233 /// <summary>
234 /// Gets an indication whether the asynchronous operation has completed.
235 /// </summary>
236 bool IsCompleted { get; }
237
238 /// <summary>
239 /// Gets an indication whether the asynchronous operation has been canceled.
240 /// </summary>
241 bool IsCanceled { get; }
242
243 /// <summary>
244 /// Gets a user-defined object that qualifies or contains information about an asynchronous operation.
245 /// </summary>
246 object State { get; }
247
248 /// <summary>
249 /// Cancel the work item if it didn't start running yet.
250 /// </summary>
251 /// <returns>Returns true on success or false if the work item is in progress or already completed</returns>
252 bool Cancel();
253
254 /// <summary>
255 /// Get the work item's priority
256 /// </summary>
257 WorkItemPriority WorkItemPriority { get; }
258
259 /// <summary>
260 /// Return the result, same as GetResult()
261 /// </summary>
262 object Result { get; }
263
264 /// <summary>
265 /// Returns the exception if occured otherwise returns null.
266 /// </summary>
267 object Exception { get; }
268 }
269
270 #endregion
271}
diff --git a/ThirdParty/SmartThreadPool/PriorityQueue.cs b/ThirdParty/SmartThreadPool/PriorityQueue.cs
new file mode 100644
index 0000000..63d5e84
--- /dev/null
+++ b/ThirdParty/SmartThreadPool/PriorityQueue.cs
@@ -0,0 +1,240 @@
1// Ami Bar
2// amibar@gmail.com
3
4using System;
5using System.Collections;
6using System.Diagnostics;
7
8namespace Amib.Threading.Internal
9{
10 #region PriorityQueue class
11
12 /// <summary>
13 /// PriorityQueue class
14 /// This class is not thread safe because we use external lock
15 /// </summary>
16 public sealed class PriorityQueue : IEnumerable
17 {
18 #region Private members
19
20 /// <summary>
21 /// The number of queues, there is one for each type of priority
22 /// </summary>
23 private const int _queuesCount = WorkItemPriority.Highest-WorkItemPriority.Lowest+1;
24
25 /// <summary>
26 /// Work items queues. There is one for each type of priority
27 /// </summary>
28 private Queue [] _queues = new Queue[_queuesCount];
29
30 /// <summary>
31 /// The total number of work items within the queues
32 /// </summary>
33 private int _workItemsCount = 0;
34
35 /// <summary>
36 /// Use with IEnumerable interface
37 /// </summary>
38 private int _version = 0;
39
40 #endregion
41
42 #region Contructor
43
44 public PriorityQueue()
45 {
46 for(int i = 0; i < _queues.Length; ++i)
47 {
48 _queues[i] = new Queue();
49 }
50 }
51
52 #endregion
53
54 #region Methods
55
56 /// <summary>
57 /// Enqueue a work item.
58 /// </summary>
59 /// <param name="workItem">A work item</param>
60 public void Enqueue(IHasWorkItemPriority workItem)
61 {
62 Debug.Assert(null != workItem);
63
64 int queueIndex = _queuesCount-(int)workItem.WorkItemPriority-1;
65 Debug.Assert(queueIndex >= 0);
66 Debug.Assert(queueIndex < _queuesCount);
67
68 _queues[queueIndex].Enqueue(workItem);
69 ++_workItemsCount;
70 ++_version;
71 }
72
73 /// <summary>
74 /// Dequeque a work item.
75 /// </summary>
76 /// <returns>Returns the next work item</returns>
77 public IHasWorkItemPriority Dequeue()
78 {
79 IHasWorkItemPriority workItem = null;
80
81 if(_workItemsCount > 0)
82 {
83 int queueIndex = GetNextNonEmptyQueue(-1);
84 Debug.Assert(queueIndex >= 0);
85 workItem = _queues[queueIndex].Dequeue() as IHasWorkItemPriority;
86 Debug.Assert(null != workItem);
87 --_workItemsCount;
88 ++_version;
89 }
90
91 return workItem;
92 }
93
94 /// <summary>
95 /// Find the next non empty queue starting at queue queueIndex+1
96 /// </summary>
97 /// <param name="queueIndex">The index-1 to start from</param>
98 /// <returns>
99 /// The index of the next non empty queue or -1 if all the queues are empty
100 /// </returns>
101 private int GetNextNonEmptyQueue(int queueIndex)
102 {
103 for(int i = queueIndex+1; i < _queuesCount; ++i)
104 {
105 if(_queues[i].Count > 0)
106 {
107 return i;
108 }
109 }
110 return -1;
111 }
112
113 /// <summary>
114 /// The number of work items
115 /// </summary>
116 public int Count
117 {
118 get
119 {
120 return _workItemsCount;
121 }
122 }
123
124 /// <summary>
125 /// Clear all the work items
126 /// </summary>
127 public void Clear()
128 {
129 if (_workItemsCount > 0)
130 {
131 foreach(Queue queue in _queues)
132 {
133 queue.Clear();
134 }
135 _workItemsCount = 0;
136 ++_version;
137 }
138 }
139
140 #endregion
141
142 #region IEnumerable Members
143
144 /// <summary>
145 /// Returns an enumerator to iterate over the work items
146 /// </summary>
147 /// <returns>Returns an enumerator</returns>
148 public IEnumerator GetEnumerator()
149 {
150 return new PriorityQueueEnumerator(this);
151 }
152
153 #endregion
154
155 #region PriorityQueueEnumerator
156
157 /// <summary>
158 /// The class the implements the enumerator
159 /// </summary>
160 private class PriorityQueueEnumerator : IEnumerator
161 {
162 private PriorityQueue _priorityQueue;
163 private int _version;
164 private int _queueIndex;
165 private IEnumerator _enumerator;
166
167 public PriorityQueueEnumerator(PriorityQueue priorityQueue)
168 {
169 _priorityQueue = priorityQueue;
170 _version = _priorityQueue._version;
171 _queueIndex = _priorityQueue.GetNextNonEmptyQueue(-1);
172 if (_queueIndex >= 0)
173 {
174 _enumerator = _priorityQueue._queues[_queueIndex].GetEnumerator();
175 }
176 else
177 {
178 _enumerator = null;
179 }
180 }
181
182 #region IEnumerator Members
183
184 public void Reset()
185 {
186 _version = _priorityQueue._version;
187 _queueIndex = _priorityQueue.GetNextNonEmptyQueue(-1);
188 if (_queueIndex >= 0)
189 {
190 _enumerator = _priorityQueue._queues[_queueIndex].GetEnumerator();
191 }
192 else
193 {
194 _enumerator = null;
195 }
196 }
197
198 public object Current
199 {
200 get
201 {
202 Debug.Assert(null != _enumerator);
203 return _enumerator.Current;
204 }
205 }
206
207 public bool MoveNext()
208 {
209 if (null == _enumerator)
210 {
211 return false;
212 }
213
214 if(_version != _priorityQueue._version)
215 {
216 throw new InvalidOperationException("The collection has been modified");
217
218 }
219 if (!_enumerator.MoveNext())
220 {
221 _queueIndex = _priorityQueue.GetNextNonEmptyQueue(_queueIndex);
222 if(-1 == _queueIndex)
223 {
224 return false;
225 }
226 _enumerator = _priorityQueue._queues[_queueIndex].GetEnumerator();
227 _enumerator.MoveNext();
228 return true;
229 }
230 return true;
231 }
232
233 #endregion
234 }
235
236 #endregion
237 }
238
239 #endregion
240}
diff --git a/ThirdParty/SmartThreadPool/STPPerformanceCounter.cs b/ThirdParty/SmartThreadPool/STPPerformanceCounter.cs
new file mode 100644
index 0000000..be70aea
--- /dev/null
+++ b/ThirdParty/SmartThreadPool/STPPerformanceCounter.cs
@@ -0,0 +1,352 @@
1using System;
2using System.Diagnostics;
3
4namespace Amib.Threading.Internal
5{
6 internal enum STPPerformanceCounterType
7 {
8 // Fields
9 ActiveThreads = 0,
10 InUseThreads = 1,
11 OverheadThreads = 2,
12 OverheadThreadsPercent = 3,
13 OverheadThreadsPercentBase = 4,
14
15 WorkItems = 5,
16 WorkItemsInQueue = 6,
17 WorkItemsProcessed = 7,
18
19 WorkItemsQueuedPerSecond = 8,
20 WorkItemsProcessedPerSecond = 9,
21
22 AvgWorkItemWaitTime = 10,
23 AvgWorkItemWaitTimeBase = 11,
24
25 AvgWorkItemProcessTime = 12,
26 AvgWorkItemProcessTimeBase = 13,
27
28 WorkItemsGroups = 14,
29
30 LastCounter = 14,
31 }
32
33
34 /// <summary>
35 /// Summary description for STPPerformanceCounter.
36 /// </summary>
37 internal class STPPerformanceCounter
38 {
39 // Fields
40 private PerformanceCounterType _pcType;
41 protected string _counterHelp;
42 protected string _counterName;
43
44 // Methods
45 public STPPerformanceCounter(
46 string counterName,
47 string counterHelp,
48 PerformanceCounterType pcType)
49 {
50 this._counterName = counterName;
51 this._counterHelp = counterHelp;
52 this._pcType = pcType;
53 }
54
55 public void AddCounterToCollection(CounterCreationDataCollection counterData)
56 {
57 CounterCreationData counterCreationData = new CounterCreationData(
58 _counterName,
59 _counterHelp,
60 _pcType);
61
62 counterData.Add(counterCreationData);
63 }
64
65 // Properties
66 public string Name
67 {
68 get
69 {
70 return _counterName;
71 }
72 }
73 }
74
75 internal class STPPerformanceCounters
76 {
77 // Fields
78 internal STPPerformanceCounter[] _stpPerformanceCounters;
79 private static STPPerformanceCounters _instance;
80 internal const string _stpCategoryHelp = "SmartThreadPool performance counters";
81 internal const string _stpCategoryName = "SmartThreadPool";
82
83 // Methods
84 static STPPerformanceCounters()
85 {
86 _instance = new STPPerformanceCounters();
87 }
88
89 private STPPerformanceCounters()
90 {
91 STPPerformanceCounter[] stpPerformanceCounters = new STPPerformanceCounter[]
92 {
93 new STPPerformanceCounter("Active threads", "The current number of available in the thread pool.", PerformanceCounterType.NumberOfItems32),
94 new STPPerformanceCounter("In use threads", "The current number of threads that execute a work item.", PerformanceCounterType.NumberOfItems32),
95 new STPPerformanceCounter("Overhead threads", "The current number of threads that are active, but are not in use.", PerformanceCounterType.NumberOfItems32),
96 new STPPerformanceCounter("% overhead threads", "The current number of threads that are active, but are not in use in percents.", PerformanceCounterType.RawFraction),
97 new STPPerformanceCounter("% overhead threads base", "The current number of threads that are active, but are not in use in percents.", PerformanceCounterType.RawBase),
98
99 new STPPerformanceCounter("Work Items", "The number of work items in the Smart Thread Pool. Both queued and processed.", PerformanceCounterType.NumberOfItems32),
100 new STPPerformanceCounter("Work Items in queue", "The current number of work items in the queue", PerformanceCounterType.NumberOfItems32),
101 new STPPerformanceCounter("Work Items processed", "The number of work items already processed", PerformanceCounterType.NumberOfItems32),
102
103 new STPPerformanceCounter("Work Items queued/sec", "The number of work items queued per second", PerformanceCounterType.RateOfCountsPerSecond32),
104 new STPPerformanceCounter("Work Items processed/sec", "The number of work items processed per second", PerformanceCounterType.RateOfCountsPerSecond32),
105
106 new STPPerformanceCounter("Avg. Work Item wait time/sec", "The average time a work item supends in the queue waiting for its turn to execute.", PerformanceCounterType.AverageCount64),
107 new STPPerformanceCounter("Avg. Work Item wait time base", "The average time a work item supends in the queue waiting for its turn to execute.", PerformanceCounterType.AverageBase),
108
109 new STPPerformanceCounter("Avg. Work Item process time/sec", "The average time it takes to process a work item.", PerformanceCounterType.AverageCount64),
110 new STPPerformanceCounter("Avg. Work Item process time base", "The average time it takes to process a work item.", PerformanceCounterType.AverageBase),
111
112 new STPPerformanceCounter("Work Items Groups", "The current number of work item groups associated with the Smart Thread Pool.", PerformanceCounterType.NumberOfItems32),
113 };
114
115 _stpPerformanceCounters = stpPerformanceCounters;
116 SetupCategory();
117 }
118
119 private void SetupCategory()
120 {
121 if (!PerformanceCounterCategory.Exists(_stpCategoryName))
122 {
123 CounterCreationDataCollection counters = new CounterCreationDataCollection();
124
125 for (int i = 0; i < _stpPerformanceCounters.Length; i++)
126 {
127 _stpPerformanceCounters[i].AddCounterToCollection(counters);
128 }
129
130
131 // *********** Remark for .NET 2.0 ***********
132 // If you are here, it means you got the warning that this overload
133 // of the method is deprecated in .NET 2.0. To use the correct
134 // method overload, uncomment the third argument of the method.
135 PerformanceCounterCategory.Create(
136 _stpCategoryName,
137 _stpCategoryHelp,
138 //PerformanceCounterCategoryType.MultiInstance,
139 counters);
140
141 }
142 }
143
144 // Properties
145 public static STPPerformanceCounters Instance
146 {
147 get
148 {
149 return _instance;
150 }
151 }
152 }
153
154 internal class STPInstancePerformanceCounter : IDisposable
155 {
156 // Fields
157 private PerformanceCounter _pcs;
158
159 // Methods
160 protected STPInstancePerformanceCounter()
161 {
162 }
163
164 public STPInstancePerformanceCounter(
165 string instance,
166 STPPerformanceCounterType spcType)
167 {
168 STPPerformanceCounters counters = STPPerformanceCounters.Instance;
169 _pcs = new PerformanceCounter(
170 STPPerformanceCounters._stpCategoryName,
171 counters._stpPerformanceCounters[(int) spcType].Name,
172 instance,
173 false);
174 _pcs.RawValue = _pcs.RawValue;
175 }
176
177 ~STPInstancePerformanceCounter()
178 {
179 Close();
180 }
181
182 public void Close()
183 {
184 if (_pcs != null)
185 {
186 _pcs.RemoveInstance();
187 _pcs.Close();
188 _pcs = null;
189 }
190 }
191
192 public void Dispose()
193 {
194 Close();
195 GC.SuppressFinalize(this);
196 }
197
198 public virtual void Increment()
199 {
200 _pcs.Increment();
201 }
202
203 public virtual void IncrementBy(long val)
204 {
205 _pcs.IncrementBy(val);
206 }
207
208 public virtual void Set(long val)
209 {
210 _pcs.RawValue = val;
211 }
212 }
213
214 internal class STPInstanceNullPerformanceCounter : STPInstancePerformanceCounter
215 {
216 // Methods
217 public STPInstanceNullPerformanceCounter() {}
218 public override void Increment() {}
219 public override void IncrementBy(long value) {}
220 public override void Set(long val) {}
221 }
222
223 internal interface ISTPInstancePerformanceCounters : IDisposable
224 {
225 void Close();
226 void SampleThreads(long activeThreads, long inUseThreads);
227 void SampleWorkItems(long workItemsQueued, long workItemsProcessed);
228 void SampleWorkItemsWaitTime(TimeSpan workItemWaitTime);
229 void SampleWorkItemsProcessTime(TimeSpan workItemProcessTime);
230 }
231
232
233 internal class STPInstancePerformanceCounters : ISTPInstancePerformanceCounters, IDisposable
234 {
235 // Fields
236 private STPInstancePerformanceCounter[] _pcs;
237 private static STPInstancePerformanceCounter _stpInstanceNullPerformanceCounter;
238
239 // Methods
240 static STPInstancePerformanceCounters()
241 {
242 _stpInstanceNullPerformanceCounter = new STPInstanceNullPerformanceCounter();
243 }
244
245 public STPInstancePerformanceCounters(string instance)
246 {
247 _pcs = new STPInstancePerformanceCounter[(int)STPPerformanceCounterType.LastCounter];
248 STPPerformanceCounters counters = STPPerformanceCounters.Instance;
249 for (int i = 0; i < _pcs.Length; i++)
250 {
251 if (instance != null)
252 {
253 _pcs[i] = new STPInstancePerformanceCounter(
254 instance,
255 (STPPerformanceCounterType) i);
256 }
257 else
258 {
259 _pcs[i] = _stpInstanceNullPerformanceCounter;
260 }
261 }
262 }
263
264
265 public void Close()
266 {
267 if (null != _pcs)
268 {
269 for (int i = 0; i < _pcs.Length; i++)
270 {
271 if (null != _pcs[i])
272 {
273 _pcs[i].Close();
274 }
275 }
276 _pcs = null;
277 }
278 }
279
280 ~STPInstancePerformanceCounters()
281 {
282 Close();
283 }
284
285 public void Dispose()
286 {
287 Close();
288 GC.SuppressFinalize(this);
289 }
290
291 private STPInstancePerformanceCounter GetCounter(STPPerformanceCounterType spcType)
292 {
293 return _pcs[(int) spcType];
294 }
295
296 public void SampleThreads(long activeThreads, long inUseThreads)
297 {
298 GetCounter(STPPerformanceCounterType.ActiveThreads).Set(activeThreads);
299 GetCounter(STPPerformanceCounterType.InUseThreads).Set(inUseThreads);
300 GetCounter(STPPerformanceCounterType.OverheadThreads).Set(activeThreads-inUseThreads);
301
302 GetCounter(STPPerformanceCounterType.OverheadThreadsPercentBase).Set(activeThreads-inUseThreads);
303 GetCounter(STPPerformanceCounterType.OverheadThreadsPercent).Set(inUseThreads);
304 }
305
306 public void SampleWorkItems(long workItemsQueued, long workItemsProcessed)
307 {
308 GetCounter(STPPerformanceCounterType.WorkItems).Set(workItemsQueued+workItemsProcessed);
309 GetCounter(STPPerformanceCounterType.WorkItemsInQueue).Set(workItemsQueued);
310 GetCounter(STPPerformanceCounterType.WorkItemsProcessed).Set(workItemsProcessed);
311
312 GetCounter(STPPerformanceCounterType.WorkItemsQueuedPerSecond).Set(workItemsQueued);
313 GetCounter(STPPerformanceCounterType.WorkItemsProcessedPerSecond).Set(workItemsProcessed);
314 }
315
316 public void SampleWorkItemsWaitTime(TimeSpan workItemWaitTime)
317 {
318 GetCounter(STPPerformanceCounterType.AvgWorkItemWaitTime).IncrementBy((long)workItemWaitTime.TotalMilliseconds);
319 GetCounter(STPPerformanceCounterType.AvgWorkItemWaitTimeBase).Increment();
320 }
321
322 public void SampleWorkItemsProcessTime(TimeSpan workItemProcessTime)
323 {
324 GetCounter(STPPerformanceCounterType.AvgWorkItemProcessTime).IncrementBy((long)workItemProcessTime.TotalMilliseconds);
325 GetCounter(STPPerformanceCounterType.AvgWorkItemProcessTimeBase).Increment();
326 }
327 }
328
329 internal class NullSTPInstancePerformanceCounters : ISTPInstancePerformanceCounters, IDisposable
330 {
331 static NullSTPInstancePerformanceCounters()
332 {
333 }
334
335 private static NullSTPInstancePerformanceCounters _instance = new NullSTPInstancePerformanceCounters(null);
336
337 public static NullSTPInstancePerformanceCounters Instance
338 {
339 get { return _instance; }
340 }
341
342 public NullSTPInstancePerformanceCounters(string instance) {}
343 public void Close() {}
344 public void Dispose() {}
345
346 public void SampleThreads(long activeThreads, long inUseThreads) {}
347 public void SampleWorkItems(long workItemsQueued, long workItemsProcessed) {}
348 public void SampleWorkItemsWaitTime(TimeSpan workItemWaitTime) {}
349 public void SampleWorkItemsProcessTime(TimeSpan workItemProcessTime) {}
350 }
351
352}
diff --git a/ThirdParty/SmartThreadPool/STPStartInfo.cs b/ThirdParty/SmartThreadPool/STPStartInfo.cs
new file mode 100644
index 0000000..d181563
--- /dev/null
+++ b/ThirdParty/SmartThreadPool/STPStartInfo.cs
@@ -0,0 +1,99 @@
1// Ami Bar
2// amibar@gmail.com
3
4using System.Threading;
5
6namespace Amib.Threading
7{
8 /// <summary>
9 /// Summary description for STPStartInfo.
10 /// </summary>
11 public class STPStartInfo : WIGStartInfo
12 {
13 /// <summary>
14 /// Idle timeout in milliseconds.
15 /// If a thread is idle for _idleTimeout milliseconds then
16 /// it may quit.
17 /// </summary>
18 private int _idleTimeout;
19
20 /// <summary>
21 /// The lower limit of threads in the pool.
22 /// </summary>
23 private int _minWorkerThreads;
24
25 /// <summary>
26 /// The upper limit of threads in the pool.
27 /// </summary>
28 private int _maxWorkerThreads;
29
30 /// <summary>
31 /// The priority of the threads in the pool
32 /// </summary>
33 private ThreadPriority _threadPriority;
34
35 /// <summary>
36 /// If this field is not null then the performance counters are enabled
37 /// and use the string as the name of the instance.
38 /// </summary>
39 private string _pcInstanceName;
40
41 private int _stackSize;
42
43 public STPStartInfo() : base()
44 {
45 _idleTimeout = SmartThreadPool.DefaultIdleTimeout;
46 _minWorkerThreads = SmartThreadPool.DefaultMinWorkerThreads;
47 _maxWorkerThreads = SmartThreadPool.DefaultMaxWorkerThreads;
48 _threadPriority = SmartThreadPool.DefaultThreadPriority;
49 _pcInstanceName = SmartThreadPool.DefaultPerformanceCounterInstanceName;
50 _stackSize = SmartThreadPool.DefaultStackSize;
51 }
52
53 public STPStartInfo(STPStartInfo stpStartInfo) : base(stpStartInfo)
54 {
55 _idleTimeout = stpStartInfo._idleTimeout;
56 _minWorkerThreads = stpStartInfo._minWorkerThreads;
57 _maxWorkerThreads = stpStartInfo._maxWorkerThreads;
58 _threadPriority = stpStartInfo._threadPriority;
59 _pcInstanceName = stpStartInfo._pcInstanceName;
60 _stackSize = stpStartInfo._stackSize;
61 }
62
63 public int IdleTimeout
64 {
65 get { return _idleTimeout; }
66 set { _idleTimeout = value; }
67 }
68
69 public int MinWorkerThreads
70 {
71 get { return _minWorkerThreads; }
72 set { _minWorkerThreads = value; }
73 }
74
75 public int MaxWorkerThreads
76 {
77 get { return _maxWorkerThreads; }
78 set { _maxWorkerThreads = value; }
79 }
80
81 public ThreadPriority ThreadPriority
82 {
83 get { return _threadPriority; }
84 set { _threadPriority = value; }
85 }
86
87 public string PerformanceCounterInstanceName
88 {
89 get { return _pcInstanceName; }
90 set { _pcInstanceName = value; }
91 }
92
93 public int StackSize
94 {
95 get { return _stackSize; }
96 set { _stackSize = value; }
97 }
98 }
99}
diff --git a/ThirdParty/SmartThreadPool/SmartThreadPool.cs b/ThirdParty/SmartThreadPool/SmartThreadPool.cs
new file mode 100644
index 0000000..c21984e
--- /dev/null
+++ b/ThirdParty/SmartThreadPool/SmartThreadPool.cs
@@ -0,0 +1,1438 @@
1// Ami Bar
2// amibar@gmail.com
3//
4// Smart thread pool in C#.
5// 7 Aug 2004 - Initial release
6// 14 Sep 2004 - Bug fixes
7// 15 Oct 2004 - Added new features
8// - Work items return result.
9// - Support waiting synchronization for multiple work items.
10// - Work items can be cancelled.
11// - Passage of the caller thread’s context to the thread in the pool.
12// - Minimal usage of WIN32 handles.
13// - Minor bug fixes.
14// 26 Dec 2004 - Changes:
15// - Removed static constructors.
16// - Added finalizers.
17// - Changed Exceptions so they are serializable.
18// - Fixed the bug in one of the SmartThreadPool constructors.
19// - Changed the SmartThreadPool.WaitAll() so it will support any number of waiters.
20// The SmartThreadPool.WaitAny() is still limited by the .NET Framework.
21// - Added PostExecute with options on which cases to call it.
22// - Added option to dispose of the state objects.
23// - Added a WaitForIdle() method that waits until the work items queue is empty.
24// - Added an STPStartInfo class for the initialization of the thread pool.
25// - Changed exception handling so if a work item throws an exception it
26// is rethrown at GetResult(), rather then firing an UnhandledException event.
27// Note that PostExecute exception are always ignored.
28// 25 Mar 2005 - Changes:
29// - Fixed lost of work items bug
30// 3 Jul 2005: Changes.
31// - Fixed bug where Enqueue() throws an exception because PopWaiter() returned null, hardly reconstructed.
32// 16 Aug 2005: Changes.
33// - Fixed bug where the InUseThreads becomes negative when canceling work items.
34//
35// 31 Jan 2006 - Changes:
36// - Added work items priority
37// - Removed support of chained delegates in callbacks and post executes (nobody really use this)
38// - Added work items groups
39// - Added work items groups idle event
40// - Changed SmartThreadPool.WaitAll() behavior so when it gets empty array
41// it returns true rather then throwing an exception.
42// - Added option to start the STP and the WIG as suspended
43// - Exception behavior changed, the real exception is returned by an
44// inner exception
45// - Added option to keep the Http context of the caller thread. (Thanks to Steven T.)
46// - Added performance counters
47// - Added priority to the threads in the pool
48//
49// 13 Feb 2006 - Changes:
50// - Added a call to the dispose of the Performance Counter so
51// their won't be a Performance Counter leak.
52// - Added exception catch in case the Performance Counters cannot
53// be created.
54
55using System;
56using System.Security;
57using System.Threading;
58using System.Collections;
59using System.Diagnostics;
60using System.Runtime.CompilerServices;
61
62using Amib.Threading.Internal;
63
64namespace Amib.Threading
65{
66 #region SmartThreadPool class
67 /// <summary>
68 /// Smart thread pool class.
69 /// </summary>
70 public class SmartThreadPool : IWorkItemsGroup, IDisposable
71 {
72 #region Default Constants
73
74 /// <summary>
75 /// Default minimum number of threads the thread pool contains. (0)
76 /// </summary>
77 public const int DefaultMinWorkerThreads = 0;
78
79 /// <summary>
80 /// Default maximum number of threads the thread pool contains. (25)
81 /// </summary>
82 public const int DefaultMaxWorkerThreads = 25;
83
84 /// <summary>
85 /// Default idle timeout in milliseconds. (One minute)
86 /// </summary>
87 public const int DefaultIdleTimeout = 60*1000; // One minute
88
89 /// <summary>
90 /// Indicate to copy the security context of the caller and then use it in the call. (false)
91 /// </summary>
92 public const bool DefaultUseCallerCallContext = false;
93
94 /// <summary>
95 /// Indicate to copy the HTTP context of the caller and then use it in the call. (false)
96 /// </summary>
97 public const bool DefaultUseCallerHttpContext = false;
98
99 /// <summary>
100 /// Indicate to dispose of the state objects if they support the IDispose interface. (false)
101 /// </summary>
102 public const bool DefaultDisposeOfStateObjects = false;
103
104 /// <summary>
105 /// The default option to run the post execute
106 /// </summary>
107 public const CallToPostExecute DefaultCallToPostExecute = CallToPostExecute.Always;
108
109 /// <summary>
110 /// The default post execute method to run.
111 /// When null it means not to call it.
112 /// </summary>
113 public static readonly PostExecuteWorkItemCallback DefaultPostExecuteWorkItemCallback = null;
114
115 /// <summary>
116 /// The default work item priority
117 /// </summary>
118 public const WorkItemPriority DefaultWorkItemPriority = WorkItemPriority.Normal;
119
120 /// <summary>
121 /// The default is to work on work items as soon as they arrive
122 /// and not to wait for the start.
123 /// </summary>
124 public const bool DefaultStartSuspended = false;
125
126 /// <summary>
127 /// The default is not to use the performance counters
128 /// </summary>
129 public static readonly string DefaultPerformanceCounterInstanceName = null;
130
131 public static readonly int DefaultStackSize = 0;
132
133 /// <summary>
134 /// The default thread priority
135 /// </summary>
136 public const ThreadPriority DefaultThreadPriority = ThreadPriority.Normal;
137
138 #endregion
139
140 #region Member Variables
141
142 /// <summary>
143 /// Contains the name of this instance of SmartThreadPool.
144 /// Can be changed by the user.
145 /// </summary>
146 private string _name = "SmartThreadPool";
147
148 /// <summary>
149 /// Hashtable of all the threads in the thread pool.
150 /// </summary>
151 private Hashtable _workerThreads = Hashtable.Synchronized(new Hashtable());
152
153 /// <summary>
154 /// Queue of work items.
155 /// </summary>
156 private WorkItemsQueue _workItemsQueue = new WorkItemsQueue();
157
158 /// <summary>
159 /// Count the work items handled.
160 /// Used by the performance counter.
161 /// </summary>
162 private long _workItemsProcessed = 0;
163
164 /// <summary>
165 /// Number of threads that currently work (not idle).
166 /// </summary>
167 private int _inUseWorkerThreads = 0;
168
169 /// <summary>
170 /// Start information to use.
171 /// It is simpler than providing many constructors.
172 /// </summary>
173 private STPStartInfo _stpStartInfo = new STPStartInfo();
174
175 /// <summary>
176 /// Total number of work items that are stored in the work items queue
177 /// plus the work items that the threads in the pool are working on.
178 /// </summary>
179 private int _currentWorkItemsCount = 0;
180
181 /// <summary>
182 /// Signaled when the thread pool is idle, i.e. no thread is busy
183 /// and the work items queue is empty
184 /// </summary>
185 private ManualResetEvent _isIdleWaitHandle = new ManualResetEvent(true);
186
187 /// <summary>
188 /// An event to signal all the threads to quit immediately.
189 /// </summary>
190 private ManualResetEvent _shuttingDownEvent = new ManualResetEvent(false);
191
192 /// <summary>
193 /// A flag to indicate the threads to quit.
194 /// </summary>
195 private bool _shutdown = false;
196
197 /// <summary>
198 /// Counts the threads created in the pool.
199 /// It is used to name the threads.
200 /// </summary>
201 private int _threadCounter = 0;
202
203 /// <summary>
204 /// Indicate that the SmartThreadPool has been disposed
205 /// </summary>
206 private bool _isDisposed = false;
207
208 /// <summary>
209 /// Event to send that the thread pool is idle
210 /// </summary>
211 private event EventHandler _stpIdle;
212
213 /// <summary>
214 /// On idle event
215 /// </summary>
216 //private event WorkItemsGroupIdleHandler _onIdle;
217
218 /// <summary>
219 /// Holds all the WorkItemsGroup instaces that have at least one
220 /// work item int the SmartThreadPool
221 /// This variable is used in case of Shutdown
222 /// </summary>
223 private Hashtable _workItemsGroups = Hashtable.Synchronized(new Hashtable());
224
225 /// <summary>
226 /// A reference from each thread in the thread pool to its SmartThreadPool
227 /// object container.
228 /// With this variable a thread can know whatever it belongs to a
229 /// SmartThreadPool.
230 /// </summary>
231 [ThreadStatic]
232 private static SmartThreadPool _smartThreadPool;
233
234 /// <summary>
235 /// A reference to the current work item a thread from the thread pool
236 /// is executing.
237 /// </summary>
238 [ThreadStatic]
239 private static WorkItem _currentWorkItem;
240
241 /// <summary>
242 /// STP performance counters
243 /// </summary>
244 private ISTPInstancePerformanceCounters _pcs = NullSTPInstancePerformanceCounters.Instance;
245
246 #endregion
247
248 #region Construction and Finalization
249
250 /// <summary>
251 /// Constructor
252 /// </summary>
253 public SmartThreadPool()
254 {
255 Initialize();
256 }
257
258 /// <summary>
259 /// Constructor
260 /// </summary>
261 /// <param name="idleTimeout">Idle timeout in milliseconds</param>
262 public SmartThreadPool(int idleTimeout)
263 {
264 _stpStartInfo.IdleTimeout = idleTimeout;
265 Initialize();
266 }
267
268 /// <summary>
269 /// Constructor
270 /// </summary>
271 /// <param name="idleTimeout">Idle timeout in milliseconds</param>
272 /// <param name="maxWorkerThreads">Upper limit of threads in the pool</param>
273 public SmartThreadPool(
274 int idleTimeout,
275 int maxWorkerThreads)
276 {
277 _stpStartInfo.IdleTimeout = idleTimeout;
278 _stpStartInfo.MaxWorkerThreads = maxWorkerThreads;
279 Initialize();
280 }
281
282 /// <summary>
283 /// Constructor
284 /// </summary>
285 /// <param name="idleTimeout">Idle timeout in milliseconds</param>
286 /// <param name="maxWorkerThreads">Upper limit of threads in the pool</param>
287 /// <param name="minWorkerThreads">Lower limit of threads in the pool</param>
288 public SmartThreadPool(
289 int idleTimeout,
290 int maxWorkerThreads,
291 int minWorkerThreads)
292 {
293 _stpStartInfo.IdleTimeout = idleTimeout;
294 _stpStartInfo.MaxWorkerThreads = maxWorkerThreads;
295 _stpStartInfo.MinWorkerThreads = minWorkerThreads;
296 Initialize();
297 }
298
299 /// <summary>
300 /// Constructor
301 /// </summary>
302 public SmartThreadPool(STPStartInfo stpStartInfo)
303 {
304 _stpStartInfo = new STPStartInfo(stpStartInfo);
305 Initialize();
306 }
307
308 private void Initialize()
309 {
310 ValidateSTPStartInfo();
311
312 if (null != _stpStartInfo.PerformanceCounterInstanceName)
313 {
314 try
315 {
316 _pcs = new STPInstancePerformanceCounters(_stpStartInfo.PerformanceCounterInstanceName);
317 }
318 catch(Exception e)
319 {
320 Debug.WriteLine("Unable to create Performance Counters: " + e.ToString());
321 _pcs = NullSTPInstancePerformanceCounters.Instance;
322 }
323 }
324
325 StartOptimalNumberOfThreads();
326 }
327
328 private void StartOptimalNumberOfThreads()
329 {
330 int threadsCount = Math.Max(_workItemsQueue.Count, _stpStartInfo.MinWorkerThreads);
331 threadsCount = Math.Min(threadsCount, _stpStartInfo.MaxWorkerThreads);
332 StartThreads(threadsCount);
333 }
334
335 private void ValidateSTPStartInfo()
336 {
337 if (_stpStartInfo.MinWorkerThreads < 0)
338 {
339 throw new ArgumentOutOfRangeException(
340 "MinWorkerThreads", "MinWorkerThreads cannot be negative");
341 }
342
343 if (_stpStartInfo.MaxWorkerThreads <= 0)
344 {
345 throw new ArgumentOutOfRangeException(
346 "MaxWorkerThreads", "MaxWorkerThreads must be greater than zero");
347 }
348
349 if (_stpStartInfo.MinWorkerThreads > _stpStartInfo.MaxWorkerThreads)
350 {
351 throw new ArgumentOutOfRangeException(
352 "MinWorkerThreads, maxWorkerThreads",
353 "MaxWorkerThreads must be greater or equal to MinWorkerThreads");
354 }
355 }
356
357 private void ValidateCallback(Delegate callback)
358 {
359 if(callback.GetInvocationList().Length > 1)
360 {
361 throw new NotSupportedException("SmartThreadPool doesn't support delegates chains");
362 }
363 }
364
365 #endregion
366
367 #region Thread Processing
368
369 /// <summary>
370 /// Waits on the queue for a work item, shutdown, or timeout.
371 /// </summary>
372 /// <returns>
373 /// Returns the WaitingCallback or null in case of timeout or shutdown.
374 /// </returns>
375 private WorkItem Dequeue()
376 {
377 WorkItem workItem =
378 _workItemsQueue.DequeueWorkItem(_stpStartInfo.IdleTimeout, _shuttingDownEvent);
379
380 return workItem;
381 }
382
383 /// <summary>
384 /// Put a new work item in the queue
385 /// </summary>
386 /// <param name="workItem">A work item to queue</param>
387 private void Enqueue(WorkItem workItem)
388 {
389 Enqueue(workItem, true);
390 }
391
392 /// <summary>
393 /// Put a new work item in the queue
394 /// </summary>
395 /// <param name="workItem">A work item to queue</param>
396 internal void Enqueue(WorkItem workItem, bool incrementWorkItems)
397 {
398 // Make sure the workItem is not null
399 Debug.Assert(null != workItem);
400
401 if (incrementWorkItems)
402 {
403 IncrementWorkItemsCount();
404 }
405
406 _workItemsQueue.EnqueueWorkItem(workItem);
407 workItem.WorkItemIsQueued();
408
409 // If all the threads are busy then try to create a new one
410 if ((InUseThreads + WaitingCallbacks) > _workerThreads.Count)
411 {
412 StartThreads(1);
413 }
414 }
415
416 private void IncrementWorkItemsCount()
417 {
418 _pcs.SampleWorkItems(_workItemsQueue.Count, _workItemsProcessed);
419
420 int count = Interlocked.Increment(ref _currentWorkItemsCount);
421 //Trace.WriteLine("WorkItemsCount = " + _currentWorkItemsCount.ToString());
422 if (count == 1)
423 {
424 //Trace.WriteLine("STP is NOT idle");
425 _isIdleWaitHandle.Reset();
426 }
427 }
428
429 private void DecrementWorkItemsCount()
430 {
431 ++_workItemsProcessed;
432
433 // The counter counts even if the work item was cancelled
434 _pcs.SampleWorkItems(_workItemsQueue.Count, _workItemsProcessed);
435
436 int count = Interlocked.Decrement(ref _currentWorkItemsCount);
437 //Trace.WriteLine("WorkItemsCount = " + _currentWorkItemsCount.ToString());
438 if (count == 0)
439 {
440 //Trace.WriteLine("STP is idle");
441 _isIdleWaitHandle.Set();
442 }
443 }
444
445 internal void RegisterWorkItemsGroup(IWorkItemsGroup workItemsGroup)
446 {
447 _workItemsGroups[workItemsGroup] = workItemsGroup;
448 }
449
450 internal void UnregisterWorkItemsGroup(IWorkItemsGroup workItemsGroup)
451 {
452 if (_workItemsGroups.Contains(workItemsGroup))
453 {
454 _workItemsGroups.Remove(workItemsGroup);
455 }
456 }
457
458 /// <summary>
459 /// Inform that the current thread is about to quit or quiting.
460 /// The same thread may call this method more than once.
461 /// </summary>
462 private void InformCompleted()
463 {
464 // There is no need to lock the two methods together
465 // since only the current thread removes itself
466 // and the _workerThreads is a synchronized hashtable
467 if (_workerThreads.Contains(Thread.CurrentThread))
468 {
469 _workerThreads.Remove(Thread.CurrentThread);
470 _pcs.SampleThreads(_workerThreads.Count, _inUseWorkerThreads);
471 }
472 }
473
474 /// <summary>
475 /// Starts new threads
476 /// </summary>
477 /// <param name="threadsCount">The number of threads to start</param>
478 private void StartThreads(int threadsCount)
479 {
480 if (_stpStartInfo.StartSuspended)
481 {
482 return;
483 }
484
485 lock(_workerThreads.SyncRoot)
486 {
487 // Don't start threads on shut down
488 if (_shutdown)
489 {
490 return;
491 }
492
493 for(int i = 0; i < threadsCount; ++i)
494 {
495 // Don't create more threads then the upper limit
496 if (_workerThreads.Count >= _stpStartInfo.MaxWorkerThreads)
497 {
498 return;
499 }
500
501 // Create a new thread
502 Thread workerThread = new Thread(new ThreadStart(ProcessQueuedItems), _stpStartInfo.StackSize);
503
504 // Configure the new thread and start it
505 workerThread.Name = "STP " + Name + " Thread #" + _threadCounter;
506 workerThread.IsBackground = true;
507 workerThread.Priority = _stpStartInfo.ThreadPriority;
508 workerThread.Start();
509 ++_threadCounter;
510
511 // Add the new thread to the hashtable and update its creation
512 // time.
513 _workerThreads[workerThread] = DateTime.Now;
514 _pcs.SampleThreads(_workerThreads.Count, _inUseWorkerThreads);
515 }
516 }
517 }
518
519 /// <summary>
520 /// A worker thread method that processes work items from the work items queue.
521 /// </summary>
522 private void ProcessQueuedItems()
523 {
524 // Initialize the _smartThreadPool variable
525 _smartThreadPool = this;
526
527 try
528 {
529 bool bInUseWorkerThreadsWasIncremented = false;
530
531 // Process until shutdown.
532 while(!_shutdown)
533 {
534 // Update the last time this thread was seen alive.
535 // It's good for debugging.
536 _workerThreads[Thread.CurrentThread] = DateTime.Now;
537
538 // Wait for a work item, shutdown, or timeout
539 WorkItem workItem = Dequeue();
540
541 // Update the last time this thread was seen alive.
542 // It's good for debugging.
543 _workerThreads[Thread.CurrentThread] = DateTime.Now;
544
545 // On timeout or shut down.
546 if (null == workItem)
547 {
548 // Double lock for quit.
549 if (_workerThreads.Count > _stpStartInfo.MinWorkerThreads)
550 {
551 lock(_workerThreads.SyncRoot)
552 {
553 if (_workerThreads.Count > _stpStartInfo.MinWorkerThreads)
554 {
555 // Inform that the thread is quiting and then quit.
556 // This method must be called within this lock or else
557 // more threads will quit and the thread pool will go
558 // below the lower limit.
559 InformCompleted();
560 break;
561 }
562 }
563 }
564 }
565
566 // If we didn't quit then skip to the next iteration.
567 if (null == workItem)
568 {
569 continue;
570 }
571
572 try
573 {
574 // Initialize the value to false
575 bInUseWorkerThreadsWasIncremented = false;
576
577 // Change the state of the work item to 'in progress' if possible.
578 // We do it here so if the work item has been canceled we won't
579 // increment the _inUseWorkerThreads.
580 // The cancel mechanism doesn't delete items from the queue,
581 // it marks the work item as canceled, and when the work item
582 // is dequeued, we just skip it.
583 // If the post execute of work item is set to always or to
584 // call when the work item is canceled then the StartingWorkItem()
585 // will return true, so the post execute can run.
586 if (!workItem.StartingWorkItem())
587 {
588 continue;
589 }
590
591 // Execute the callback. Make sure to accurately
592 // record how many callbacks are currently executing.
593 int inUseWorkerThreads = Interlocked.Increment(ref _inUseWorkerThreads);
594 _pcs.SampleThreads(_workerThreads.Count, inUseWorkerThreads);
595
596 // Mark that the _inUseWorkerThreads incremented, so in the finally{}
597 // statement we will decrement it correctly.
598 bInUseWorkerThreadsWasIncremented = true;
599
600 // Set the _currentWorkItem to the current work item
601 _currentWorkItem = workItem;
602
603 lock(workItem)
604 {
605 workItem.currentThread = Thread.CurrentThread;
606 }
607
608 ExecuteWorkItem(workItem);
609
610 lock(workItem)
611 {
612 workItem.currentThread = null;
613 }
614
615 }
616 catch(ThreadAbortException ex)
617 {
618 lock(workItem)
619 {
620 workItem.currentThread = null;
621 }
622 ex.GetHashCode();
623 Thread.ResetAbort();
624 }
625 catch(Exception ex)
626 {
627 ex.GetHashCode();
628 // Do nothing
629 }
630 finally
631 {
632 lock(workItem)
633 {
634 workItem.currentThread = null;
635 }
636
637 if (null != workItem)
638 {
639 workItem.DisposeOfState();
640 }
641
642 // Set the _currentWorkItem to null, since we
643 // no longer run user's code.
644 _currentWorkItem = null;
645
646 // Decrement the _inUseWorkerThreads only if we had
647 // incremented it. Note the cancelled work items don't
648 // increment _inUseWorkerThreads.
649 if (bInUseWorkerThreadsWasIncremented)
650 {
651 int inUseWorkerThreads = Interlocked.Decrement(ref _inUseWorkerThreads);
652 _pcs.SampleThreads(_workerThreads.Count, inUseWorkerThreads);
653 }
654
655 // Notify that the work item has been completed.
656 // WorkItemsGroup may enqueue their next work item.
657 workItem.FireWorkItemCompleted();
658
659 // Decrement the number of work items here so the idle
660 // ManualResetEvent won't fluctuate.
661 DecrementWorkItemsCount();
662 }
663 }
664 }
665 catch(ThreadAbortException tae)
666 {
667 tae.GetHashCode();
668 // Handle the abort exception gracfully.
669 Thread.ResetAbort();
670 }
671 catch(Exception e)
672 {
673 Debug.Assert(null != e);
674 }
675 finally
676 {
677 InformCompleted();
678 }
679 }
680
681 private void ExecuteWorkItem(WorkItem workItem)
682 {
683 _pcs.SampleWorkItemsWaitTime(workItem.WaitingTime);
684 try
685 {
686 workItem.Execute();
687 }
688 catch
689 {
690 throw;
691 }
692 finally
693 {
694 _pcs.SampleWorkItemsProcessTime(workItem.ProcessTime);
695 }
696 }
697
698
699 #endregion
700
701 #region Public Methods
702
703 /// <summary>
704 /// Queue a work item
705 /// </summary>
706 /// <param name="callback">A callback to execute</param>
707 /// <returns>Returns a work item result</returns>
708 public IWorkItemResult QueueWorkItem(WorkItemCallback callback)
709 {
710 ValidateNotDisposed();
711 ValidateCallback(callback);
712 WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _stpStartInfo, callback);
713 Enqueue(workItem);
714 return workItem.GetWorkItemResult();
715 }
716
717 /// <summary>
718 /// Queue a work item
719 /// </summary>
720 /// <param name="callback">A callback to execute</param>
721 /// <param name="workItemPriority">The priority of the work item</param>
722 /// <returns>Returns a work item result</returns>
723 public IWorkItemResult QueueWorkItem(WorkItemCallback callback, WorkItemPriority workItemPriority)
724 {
725 ValidateNotDisposed();
726 ValidateCallback(callback);
727 WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _stpStartInfo, callback, workItemPriority);
728 Enqueue(workItem);
729 return workItem.GetWorkItemResult();
730 }
731
732 /// <summary>
733 /// Queue a work item
734 /// </summary>
735 /// <param name="workItemInfo">Work item info</param>
736 /// <param name="callback">A callback to execute</param>
737 /// <returns>Returns a work item result</returns>
738 public IWorkItemResult QueueWorkItem(WorkItemInfo workItemInfo, WorkItemCallback callback)
739 {
740 ValidateNotDisposed();
741 ValidateCallback(callback);
742 WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _stpStartInfo, workItemInfo, callback);
743 Enqueue(workItem);
744 return workItem.GetWorkItemResult();
745 }
746
747 /// <summary>
748 /// Queue a work item
749 /// </summary>
750 /// <param name="callback">A callback to execute</param>
751 /// <param name="state">
752 /// The context object of the work item. Used for passing arguments to the work item.
753 /// </param>
754 /// <returns>Returns a work item result</returns>
755 public IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state)
756 {
757 ValidateNotDisposed();
758 ValidateCallback(callback);
759 WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _stpStartInfo, callback, state);
760 Enqueue(workItem);
761 return workItem.GetWorkItemResult();
762 }
763
764 /// <summary>
765 /// Queue a work item
766 /// </summary>
767 /// <param name="callback">A callback to execute</param>
768 /// <param name="state">
769 /// The context object of the work item. Used for passing arguments to the work item.
770 /// </param>
771 /// <param name="workItemPriority">The work item priority</param>
772 /// <returns>Returns a work item result</returns>
773 public IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, WorkItemPriority workItemPriority)
774 {
775 ValidateNotDisposed();
776 ValidateCallback(callback);
777 WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _stpStartInfo, callback, state, workItemPriority);
778 Enqueue(workItem);
779 return workItem.GetWorkItemResult();
780 }
781
782 /// <summary>
783 /// Queue a work item
784 /// </summary>
785 /// <param name="workItemInfo">Work item information</param>
786 /// <param name="callback">A callback to execute</param>
787 /// <param name="state">
788 /// The context object of the work item. Used for passing arguments to the work item.
789 /// </param>
790 /// <returns>Returns a work item result</returns>
791 public IWorkItemResult QueueWorkItem(WorkItemInfo workItemInfo, WorkItemCallback callback, object state)
792 {
793 ValidateNotDisposed();
794 ValidateCallback(callback);
795 WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _stpStartInfo, workItemInfo, callback, state);
796 Enqueue(workItem);
797 return workItem.GetWorkItemResult();
798 }
799
800 /// <summary>
801 /// Queue a work item
802 /// </summary>
803 /// <param name="callback">A callback to execute</param>
804 /// <param name="state">
805 /// The context object of the work item. Used for passing arguments to the work item.
806 /// </param>
807 /// <param name="postExecuteWorkItemCallback">
808 /// A delegate to call after the callback completion
809 /// </param>
810 /// <returns>Returns a work item result</returns>
811 public IWorkItemResult QueueWorkItem(
812 WorkItemCallback callback,
813 object state,
814 PostExecuteWorkItemCallback postExecuteWorkItemCallback)
815 {
816 ValidateNotDisposed();
817 ValidateCallback(callback);
818 WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _stpStartInfo, callback, state, postExecuteWorkItemCallback);
819 Enqueue(workItem);
820 return workItem.GetWorkItemResult();
821 }
822
823 /// <summary>
824 /// Queue a work item
825 /// </summary>
826 /// <param name="callback">A callback to execute</param>
827 /// <param name="state">
828 /// The context object of the work item. Used for passing arguments to the work item.
829 /// </param>
830 /// <param name="postExecuteWorkItemCallback">
831 /// A delegate to call after the callback completion
832 /// </param>
833 /// <param name="workItemPriority">The work item priority</param>
834 /// <returns>Returns a work item result</returns>
835 public IWorkItemResult QueueWorkItem(
836 WorkItemCallback callback,
837 object state,
838 PostExecuteWorkItemCallback postExecuteWorkItemCallback,
839 WorkItemPriority workItemPriority)
840 {
841 ValidateNotDisposed();
842 ValidateCallback(callback);
843 WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _stpStartInfo, callback, state, postExecuteWorkItemCallback, workItemPriority);
844 Enqueue(workItem);
845 return workItem.GetWorkItemResult();
846 }
847
848 /// <summary>
849 /// Queue a work item
850 /// </summary>
851 /// <param name="callback">A callback to execute</param>
852 /// <param name="state">
853 /// The context object of the work item. Used for passing arguments to the work item.
854 /// </param>
855 /// <param name="postExecuteWorkItemCallback">
856 /// A delegate to call after the callback completion
857 /// </param>
858 /// <param name="callToPostExecute">Indicates on which cases to call to the post execute callback</param>
859 /// <returns>Returns a work item result</returns>
860 public IWorkItemResult QueueWorkItem(
861 WorkItemCallback callback,
862 object state,
863 PostExecuteWorkItemCallback postExecuteWorkItemCallback,
864 CallToPostExecute callToPostExecute)
865 {
866 ValidateNotDisposed();
867 ValidateCallback(callback);
868 WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _stpStartInfo, callback, state, postExecuteWorkItemCallback, callToPostExecute);
869 Enqueue(workItem);
870 return workItem.GetWorkItemResult();
871 }
872
873 /// <summary>
874 /// Queue a work item
875 /// </summary>
876 /// <param name="callback">A callback to execute</param>
877 /// <param name="state">
878 /// The context object of the work item. Used for passing arguments to the work item.
879 /// </param>
880 /// <param name="postExecuteWorkItemCallback">
881 /// A delegate to call after the callback completion
882 /// </param>
883 /// <param name="callToPostExecute">Indicates on which cases to call to the post execute callback</param>
884 /// <param name="workItemPriority">The work item priority</param>
885 /// <returns>Returns a work item result</returns>
886 public IWorkItemResult QueueWorkItem(
887 WorkItemCallback callback,
888 object state,
889 PostExecuteWorkItemCallback postExecuteWorkItemCallback,
890 CallToPostExecute callToPostExecute,
891 WorkItemPriority workItemPriority)
892 {
893 ValidateNotDisposed();
894 ValidateCallback(callback);
895 WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _stpStartInfo, callback, state, postExecuteWorkItemCallback, callToPostExecute, workItemPriority);
896 Enqueue(workItem);
897 return workItem.GetWorkItemResult();
898 }
899
900 /// <summary>
901 /// Wait for the thread pool to be idle
902 /// </summary>
903 public void WaitForIdle()
904 {
905 WaitForIdle(Timeout.Infinite);
906 }
907
908 /// <summary>
909 /// Wait for the thread pool to be idle
910 /// </summary>
911 public bool WaitForIdle(TimeSpan timeout)
912 {
913 return WaitForIdle((int)timeout.TotalMilliseconds);
914 }
915
916 /// <summary>
917 /// Wait for the thread pool to be idle
918 /// </summary>
919 public bool WaitForIdle(int millisecondsTimeout)
920 {
921 ValidateWaitForIdle();
922 return _isIdleWaitHandle.WaitOne(millisecondsTimeout, false);
923 }
924
925 private void ValidateWaitForIdle()
926 {
927 if(_smartThreadPool == this)
928 {
929 throw new NotSupportedException(
930 "WaitForIdle cannot be called from a thread on its SmartThreadPool, it will cause may cause a deadlock");
931 }
932 }
933
934 internal void ValidateWorkItemsGroupWaitForIdle(IWorkItemsGroup workItemsGroup)
935 {
936 ValidateWorkItemsGroupWaitForIdleImpl(workItemsGroup, SmartThreadPool._currentWorkItem);
937 if ((null != workItemsGroup) &&
938 (null != SmartThreadPool._currentWorkItem) &&
939 SmartThreadPool._currentWorkItem.WasQueuedBy(workItemsGroup))
940 {
941 throw new NotSupportedException("WaitForIdle cannot be called from a thread on its SmartThreadPool, it will cause may cause a deadlock");
942 }
943 }
944
945 [MethodImpl(MethodImplOptions.NoInlining)]
946 private void ValidateWorkItemsGroupWaitForIdleImpl(IWorkItemsGroup workItemsGroup, WorkItem workItem)
947 {
948 if ((null != workItemsGroup) &&
949 (null != workItem) &&
950 workItem.WasQueuedBy(workItemsGroup))
951 {
952 throw new NotSupportedException("WaitForIdle cannot be called from a thread on its SmartThreadPool, it will cause may cause a deadlock");
953 }
954 }
955
956
957
958 /// <summary>
959 /// Force the SmartThreadPool to shutdown
960 /// </summary>
961 public void Shutdown()
962 {
963 Shutdown(true, 0);
964 }
965
966 public void Shutdown(bool forceAbort, TimeSpan timeout)
967 {
968 Shutdown(forceAbort, (int)timeout.TotalMilliseconds);
969 }
970
971 /// <summary>
972 /// Empties the queue of work items and abort the threads in the pool.
973 /// </summary>
974 public void Shutdown(bool forceAbort, int millisecondsTimeout)
975 {
976 ValidateNotDisposed();
977
978 ISTPInstancePerformanceCounters pcs = _pcs;
979
980 if (NullSTPInstancePerformanceCounters.Instance != _pcs)
981 {
982 _pcs.Dispose();
983 // Set the _pcs to "null" to stop updating the performance
984 // counters
985 _pcs = NullSTPInstancePerformanceCounters.Instance;
986 }
987
988 Thread [] threads = null;
989 lock(_workerThreads.SyncRoot)
990 {
991 // Shutdown the work items queue
992 _workItemsQueue.Dispose();
993
994 // Signal the threads to exit
995 _shutdown = true;
996 _shuttingDownEvent.Set();
997
998 // Make a copy of the threads' references in the pool
999 threads = new Thread [_workerThreads.Count];
1000 _workerThreads.Keys.CopyTo(threads, 0);
1001 }
1002
1003 int millisecondsLeft = millisecondsTimeout;
1004 DateTime start = DateTime.Now;
1005 bool waitInfinitely = (Timeout.Infinite == millisecondsTimeout);
1006 bool timeout = false;
1007
1008 // Each iteration we update the time left for the timeout.
1009 foreach(Thread thread in threads)
1010 {
1011 // Join don't work with negative numbers
1012 if (!waitInfinitely && (millisecondsLeft < 0))
1013 {
1014 timeout = true;
1015 break;
1016 }
1017
1018 // Wait for the thread to terminate
1019 bool success = thread.Join(millisecondsLeft);
1020 if(!success)
1021 {
1022 timeout = true;
1023 break;
1024 }
1025
1026 if(!waitInfinitely)
1027 {
1028 // Update the time left to wait
1029 TimeSpan ts = DateTime.Now - start;
1030 millisecondsLeft = millisecondsTimeout - (int)ts.TotalMilliseconds;
1031 }
1032 }
1033
1034 if (timeout && forceAbort)
1035 {
1036 // Abort the threads in the pool
1037 foreach(Thread thread in threads)
1038 {
1039 if ((thread != null) && thread.IsAlive)
1040 {
1041 try
1042 {
1043 thread.Abort("Shutdown");
1044 }
1045 catch(SecurityException e)
1046 {
1047 e.GetHashCode();
1048 }
1049 catch(ThreadStateException ex)
1050 {
1051 ex.GetHashCode();
1052 // In case the thread has been terminated
1053 // after the check if it is alive.
1054 }
1055 }
1056 }
1057 }
1058
1059 // Dispose of the performance counters
1060 pcs.Dispose();
1061 }
1062
1063 /// <summary>
1064 /// Wait for all work items to complete
1065 /// </summary>
1066 /// <param name="workItemResults">Array of work item result objects</param>
1067 /// <returns>
1068 /// true when every work item in workItemResults has completed; otherwise false.
1069 /// </returns>
1070 public static bool WaitAll(
1071 IWorkItemResult [] workItemResults)
1072 {
1073 return WaitAll(workItemResults, Timeout.Infinite, true);
1074 }
1075
1076 /// <summary>
1077 /// Wait for all work items to complete
1078 /// </summary>
1079 /// <param name="workItemResults">Array of work item result objects</param>
1080 /// <param name="timeout">The number of milliseconds to wait, or a TimeSpan that represents -1 milliseconds to wait indefinitely. </param>
1081 /// <param name="exitContext">
1082 /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
1083 /// </param>
1084 /// <returns>
1085 /// true when every work item in workItemResults has completed; otherwise false.
1086 /// </returns>
1087 public static bool WaitAll(
1088 IWorkItemResult [] workItemResults,
1089 TimeSpan timeout,
1090 bool exitContext)
1091 {
1092 return WaitAll(workItemResults, (int)timeout.TotalMilliseconds, exitContext);
1093 }
1094
1095 /// <summary>
1096 /// Wait for all work items to complete
1097 /// </summary>
1098 /// <param name="workItemResults">Array of work item result objects</param>
1099 /// <param name="timeout">The number of milliseconds to wait, or a TimeSpan that represents -1 milliseconds to wait indefinitely. </param>
1100 /// <param name="exitContext">
1101 /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
1102 /// </param>
1103 /// <param name="cancelWaitHandle">A cancel wait handle to interrupt the wait if needed</param>
1104 /// <returns>
1105 /// true when every work item in workItemResults has completed; otherwise false.
1106 /// </returns>
1107 public static bool WaitAll(
1108 IWorkItemResult [] workItemResults,
1109 TimeSpan timeout,
1110 bool exitContext,
1111 WaitHandle cancelWaitHandle)
1112 {
1113 return WaitAll(workItemResults, (int)timeout.TotalMilliseconds, exitContext, cancelWaitHandle);
1114 }
1115
1116 /// <summary>
1117 /// Wait for all work items to complete
1118 /// </summary>
1119 /// <param name="workItemResults">Array of work item result objects</param>
1120 /// <param name="millisecondsTimeout">The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely.</param>
1121 /// <param name="exitContext">
1122 /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
1123 /// </param>
1124 /// <returns>
1125 /// true when every work item in workItemResults has completed; otherwise false.
1126 /// </returns>
1127 public static bool WaitAll(
1128 IWorkItemResult [] workItemResults,
1129 int millisecondsTimeout,
1130 bool exitContext)
1131 {
1132 return WorkItem.WaitAll(workItemResults, millisecondsTimeout, exitContext, null);
1133 }
1134
1135 /// <summary>
1136 /// Wait for all work items to complete
1137 /// </summary>
1138 /// <param name="workItemResults">Array of work item result objects</param>
1139 /// <param name="millisecondsTimeout">The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely.</param>
1140 /// <param name="exitContext">
1141 /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
1142 /// </param>
1143 /// <param name="cancelWaitHandle">A cancel wait handle to interrupt the wait if needed</param>
1144 /// <returns>
1145 /// true when every work item in workItemResults has completed; otherwise false.
1146 /// </returns>
1147 public static bool WaitAll(
1148 IWorkItemResult [] workItemResults,
1149 int millisecondsTimeout,
1150 bool exitContext,
1151 WaitHandle cancelWaitHandle)
1152 {
1153 return WorkItem.WaitAll(workItemResults, millisecondsTimeout, exitContext, cancelWaitHandle);
1154 }
1155
1156
1157 /// <summary>
1158 /// Waits for any of the work items in the specified array to complete, cancel, or timeout
1159 /// </summary>
1160 /// <param name="workItemResults">Array of work item result objects</param>
1161 /// <returns>
1162 /// The array index of the work item result that satisfied the wait, or WaitTimeout if any of the work items has been canceled.
1163 /// </returns>
1164 public static int WaitAny(
1165 IWorkItemResult [] workItemResults)
1166 {
1167 return WaitAny(workItemResults, Timeout.Infinite, true);
1168 }
1169
1170 /// <summary>
1171 /// Waits for any of the work items in the specified array to complete, cancel, or timeout
1172 /// </summary>
1173 /// <param name="workItemResults">Array of work item result objects</param>
1174 /// <param name="timeout">The number of milliseconds to wait, or a TimeSpan that represents -1 milliseconds to wait indefinitely. </param>
1175 /// <param name="exitContext">
1176 /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
1177 /// </param>
1178 /// <returns>
1179 /// The array index of the work item result that satisfied the wait, or WaitTimeout if no work item result satisfied the wait and a time interval equivalent to millisecondsTimeout has passed or the work item has been canceled.
1180 /// </returns>
1181 public static int WaitAny(
1182 IWorkItemResult [] workItemResults,
1183 TimeSpan timeout,
1184 bool exitContext)
1185 {
1186 return WaitAny(workItemResults, (int)timeout.TotalMilliseconds, exitContext);
1187 }
1188
1189 /// <summary>
1190 /// Waits for any of the work items in the specified array to complete, cancel, or timeout
1191 /// </summary>
1192 /// <param name="workItemResults">Array of work item result objects</param>
1193 /// <param name="timeout">The number of milliseconds to wait, or a TimeSpan that represents -1 milliseconds to wait indefinitely. </param>
1194 /// <param name="exitContext">
1195 /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
1196 /// </param>
1197 /// <param name="cancelWaitHandle">A cancel wait handle to interrupt the wait if needed</param>
1198 /// <returns>
1199 /// The array index of the work item result that satisfied the wait, or WaitTimeout if no work item result satisfied the wait and a time interval equivalent to millisecondsTimeout has passed or the work item has been canceled.
1200 /// </returns>
1201 public static int WaitAny(
1202 IWorkItemResult [] workItemResults,
1203 TimeSpan timeout,
1204 bool exitContext,
1205 WaitHandle cancelWaitHandle)
1206 {
1207 return WaitAny(workItemResults, (int)timeout.TotalMilliseconds, exitContext, cancelWaitHandle);
1208 }
1209
1210 /// <summary>
1211 /// Waits for any of the work items in the specified array to complete, cancel, or timeout
1212 /// </summary>
1213 /// <param name="workItemResults">Array of work item result objects</param>
1214 /// <param name="millisecondsTimeout">The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely.</param>
1215 /// <param name="exitContext">
1216 /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
1217 /// </param>
1218 /// <returns>
1219 /// The array index of the work item result that satisfied the wait, or WaitTimeout if no work item result satisfied the wait and a time interval equivalent to millisecondsTimeout has passed or the work item has been canceled.
1220 /// </returns>
1221 public static int WaitAny(
1222 IWorkItemResult [] workItemResults,
1223 int millisecondsTimeout,
1224 bool exitContext)
1225 {
1226 return WorkItem.WaitAny(workItemResults, millisecondsTimeout, exitContext, null);
1227 }
1228
1229 /// <summary>
1230 /// Waits for any of the work items in the specified array to complete, cancel, or timeout
1231 /// </summary>
1232 /// <param name="workItemResults">Array of work item result objects</param>
1233 /// <param name="millisecondsTimeout">The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely.</param>
1234 /// <param name="exitContext">
1235 /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
1236 /// </param>
1237 /// <param name="cancelWaitHandle">A cancel wait handle to interrupt the wait if needed</param>
1238 /// <returns>
1239 /// The array index of the work item result that satisfied the wait, or WaitTimeout if no work item result satisfied the wait and a time interval equivalent to millisecondsTimeout has passed or the work item has been canceled.
1240 /// </returns>
1241 public static int WaitAny(
1242 IWorkItemResult [] workItemResults,
1243 int millisecondsTimeout,
1244 bool exitContext,
1245 WaitHandle cancelWaitHandle)
1246 {
1247 return WorkItem.WaitAny(workItemResults, millisecondsTimeout, exitContext, cancelWaitHandle);
1248 }
1249
1250 public IWorkItemsGroup CreateWorkItemsGroup(int concurrency)
1251 {
1252 IWorkItemsGroup workItemsGroup = new WorkItemsGroup(this, concurrency, _stpStartInfo);
1253 return workItemsGroup;
1254 }
1255
1256 public IWorkItemsGroup CreateWorkItemsGroup(int concurrency, WIGStartInfo wigStartInfo)
1257 {
1258 IWorkItemsGroup workItemsGroup = new WorkItemsGroup(this, concurrency, wigStartInfo);
1259 return workItemsGroup;
1260 }
1261
1262 public event WorkItemsGroupIdleHandler OnIdle
1263 {
1264 add
1265 {
1266 throw new NotImplementedException("This event is not implemented in the SmartThreadPool class. Please create a WorkItemsGroup in order to use this feature.");
1267 //_onIdle += value;
1268 }
1269 remove
1270 {
1271 throw new NotImplementedException("This event is not implemented in the SmartThreadPool class. Please create a WorkItemsGroup in order to use this feature.");
1272 //_onIdle -= value;
1273 }
1274 }
1275
1276 public void Cancel()
1277 {
1278 ICollection workItemsGroups = _workItemsGroups.Values;
1279 foreach(WorkItemsGroup workItemsGroup in workItemsGroups)
1280 {
1281 workItemsGroup.Cancel();
1282 }
1283 }
1284
1285 public void Start()
1286 {
1287 lock (this)
1288 {
1289 if (!this._stpStartInfo.StartSuspended)
1290 {
1291 return;
1292 }
1293 _stpStartInfo.StartSuspended = false;
1294 }
1295
1296 ICollection workItemsGroups = _workItemsGroups.Values;
1297 foreach(WorkItemsGroup workItemsGroup in workItemsGroups)
1298 {
1299 workItemsGroup.OnSTPIsStarting();
1300 }
1301
1302 StartOptimalNumberOfThreads();
1303 }
1304
1305 #endregion
1306
1307 #region Properties
1308
1309 /// <summary>
1310 /// Get/Set the name of the SmartThreadPool instance
1311 /// </summary>
1312 public string Name
1313 {
1314 get
1315 {
1316 return _name;
1317 }
1318
1319 set
1320 {
1321 _name = value;
1322 }
1323 }
1324
1325 /// <summary>
1326 /// Get the lower limit of threads in the pool.
1327 /// </summary>
1328 public int MinThreads
1329 {
1330 get
1331 {
1332 ValidateNotDisposed();
1333 return _stpStartInfo.MinWorkerThreads;
1334 }
1335 }
1336
1337 /// <summary>
1338 /// Get the upper limit of threads in the pool.
1339 /// </summary>
1340 public int MaxThreads
1341 {
1342 get
1343 {
1344 ValidateNotDisposed();
1345 return _stpStartInfo.MaxWorkerThreads;
1346 }
1347 }
1348 /// <summary>
1349 /// Get the number of threads in the thread pool.
1350 /// Should be between the lower and the upper limits.
1351 /// </summary>
1352 public int ActiveThreads
1353 {
1354 get
1355 {
1356 ValidateNotDisposed();
1357 return _workerThreads.Count;
1358 }
1359 }
1360
1361 /// <summary>
1362 /// Get the number of busy (not idle) threads in the thread pool.
1363 /// </summary>
1364 public int InUseThreads
1365 {
1366 get
1367 {
1368 ValidateNotDisposed();
1369 return _inUseWorkerThreads;
1370 }
1371 }
1372
1373 /// <summary>
1374 /// Get the number of work items in the queue.
1375 /// </summary>
1376 public int WaitingCallbacks
1377 {
1378 get
1379 {
1380 ValidateNotDisposed();
1381 return _workItemsQueue.Count;
1382 }
1383 }
1384
1385
1386 public event EventHandler Idle
1387 {
1388 add
1389 {
1390 _stpIdle += value;
1391 }
1392
1393 remove
1394 {
1395 _stpIdle -= value;
1396 }
1397 }
1398
1399 #endregion
1400
1401 #region IDisposable Members
1402
1403// ~SmartThreadPool()
1404// {
1405// Dispose();
1406// }
1407
1408 public void Dispose()
1409 {
1410 if (!_isDisposed)
1411 {
1412 if (!_shutdown)
1413 {
1414 Shutdown();
1415 }
1416
1417 if (null != _shuttingDownEvent)
1418 {
1419 _shuttingDownEvent.Close();
1420 _shuttingDownEvent = null;
1421 }
1422 _workerThreads.Clear();
1423 _isDisposed = true;
1424 GC.SuppressFinalize(this);
1425 }
1426 }
1427
1428 private void ValidateNotDisposed()
1429 {
1430 if(_isDisposed)
1431 {
1432 throw new ObjectDisposedException(GetType().ToString(), "The SmartThreadPool has been shutdown");
1433 }
1434 }
1435 #endregion
1436 }
1437 #endregion
1438}
diff --git a/ThirdParty/SmartThreadPool/WIGStartInfo.cs b/ThirdParty/SmartThreadPool/WIGStartInfo.cs
new file mode 100644
index 0000000..150317f
--- /dev/null
+++ b/ThirdParty/SmartThreadPool/WIGStartInfo.cs
@@ -0,0 +1,99 @@
1// Ami Bar
2// amibar@gmail.com
3
4namespace Amib.Threading
5{
6 /// <summary>
7 /// Summary description for WIGStartInfo.
8 /// </summary>
9 public class WIGStartInfo
10 {
11 /// <summary>
12 /// Use the caller's security context
13 /// </summary>
14 private bool _useCallerCallContext;
15
16 /// <summary>
17 /// Use the caller's HTTP context
18 /// </summary>
19 private bool _useCallerHttpContext;
20
21 /// <summary>
22 /// Dispose of the state object of a work item
23 /// </summary>
24 private bool _disposeOfStateObjects;
25
26 /// <summary>
27 /// The option to run the post execute
28 /// </summary>
29 private CallToPostExecute _callToPostExecute;
30
31 /// <summary>
32 /// A post execute callback to call when none is provided in
33 /// the QueueWorkItem method.
34 /// </summary>
35 private PostExecuteWorkItemCallback _postExecuteWorkItemCallback;
36
37 /// <summary>
38 /// Indicate the WorkItemsGroup to suspend the handling of the work items
39 /// until the Start() method is called.
40 /// </summary>
41 private bool _startSuspended;
42
43 public WIGStartInfo()
44 {
45 _useCallerCallContext = SmartThreadPool.DefaultUseCallerCallContext;
46 _useCallerHttpContext = SmartThreadPool.DefaultUseCallerHttpContext;
47 _disposeOfStateObjects = SmartThreadPool.DefaultDisposeOfStateObjects;
48 _callToPostExecute = SmartThreadPool.DefaultCallToPostExecute;
49 _postExecuteWorkItemCallback = SmartThreadPool.DefaultPostExecuteWorkItemCallback;
50 _startSuspended = SmartThreadPool.DefaultStartSuspended;
51 }
52
53 public WIGStartInfo(WIGStartInfo wigStartInfo)
54 {
55 _useCallerCallContext = wigStartInfo._useCallerCallContext;
56 _useCallerHttpContext = wigStartInfo._useCallerHttpContext;
57 _disposeOfStateObjects = wigStartInfo._disposeOfStateObjects;
58 _callToPostExecute = wigStartInfo._callToPostExecute;
59 _postExecuteWorkItemCallback = wigStartInfo._postExecuteWorkItemCallback;
60 _startSuspended = wigStartInfo._startSuspended;
61 }
62
63 public bool UseCallerCallContext
64 {
65 get { return _useCallerCallContext; }
66 set { _useCallerCallContext = value; }
67 }
68
69 public bool UseCallerHttpContext
70 {
71 get { return _useCallerHttpContext; }
72 set { _useCallerHttpContext = value; }
73 }
74
75 public bool DisposeOfStateObjects
76 {
77 get { return _disposeOfStateObjects; }
78 set { _disposeOfStateObjects = value; }
79 }
80
81 public CallToPostExecute CallToPostExecute
82 {
83 get { return _callToPostExecute; }
84 set { _callToPostExecute = value; }
85 }
86
87 public PostExecuteWorkItemCallback PostExecuteWorkItemCallback
88 {
89 get { return _postExecuteWorkItemCallback; }
90 set { _postExecuteWorkItemCallback = value; }
91 }
92
93 public bool StartSuspended
94 {
95 get { return _startSuspended; }
96 set { _startSuspended = value; }
97 }
98 }
99}
diff --git a/ThirdParty/SmartThreadPool/WorkItem.cs b/ThirdParty/SmartThreadPool/WorkItem.cs
new file mode 100644
index 0000000..d0c0524
--- /dev/null
+++ b/ThirdParty/SmartThreadPool/WorkItem.cs
@@ -0,0 +1,1035 @@
1// Ami Bar
2// amibar@gmail.com
3
4using System;
5using System.Threading;
6using System.Diagnostics;
7
8namespace Amib.Threading.Internal
9{
10 #region WorkItem Delegate
11
12 /// <summary>
13 /// An internal delegate to call when the WorkItem starts or completes
14 /// </summary>
15 internal delegate void WorkItemStateCallback(WorkItem workItem);
16
17 #endregion
18
19 #region IInternalWorkItemResult interface
20
21 public class CanceledWorkItemsGroup
22 {
23 public readonly static CanceledWorkItemsGroup NotCanceledWorkItemsGroup = new CanceledWorkItemsGroup();
24
25 private bool _isCanceled = false;
26 public bool IsCanceled
27 {
28 get { return _isCanceled; }
29 set { _isCanceled = value; }
30 }
31 }
32
33 internal interface IInternalWorkItemResult
34 {
35 event WorkItemStateCallback OnWorkItemStarted;
36 event WorkItemStateCallback OnWorkItemCompleted;
37 }
38
39 #endregion
40
41 #region IWorkItem interface
42
43 public interface IWorkItem
44 {
45
46 }
47
48 #endregion
49
50 #region WorkItem class
51
52 /// <summary>
53 /// Holds a callback delegate and the state for that delegate.
54 /// </summary>
55 public class WorkItem : IHasWorkItemPriority, IWorkItem
56 {
57 #region WorkItemState enum
58
59 /// <summary>
60 /// Indicates the state of the work item in the thread pool
61 /// </summary>
62 private enum WorkItemState
63 {
64 InQueue,
65 InProgress,
66 Completed,
67 Canceled,
68 }
69
70 #endregion
71
72 #region Member Variables
73
74 public Thread currentThread;
75
76 /// <summary>
77 /// Callback delegate for the callback.
78 /// </summary>
79 private WorkItemCallback _callback;
80
81 /// <summary>
82 /// State with which to call the callback delegate.
83 /// </summary>
84 private object _state;
85
86 /// <summary>
87 /// Stores the caller's context
88 /// </summary>
89 private CallerThreadContext _callerContext;
90
91 /// <summary>
92 /// Holds the result of the mehtod
93 /// </summary>
94 private object _result;
95
96 /// <summary>
97 /// Hold the exception if the method threw it
98 /// </summary>
99 private Exception _exception;
100
101 /// <summary>
102 /// Hold the state of the work item
103 /// </summary>
104 private WorkItemState _workItemState;
105
106 /// <summary>
107 /// A ManualResetEvent to indicate that the result is ready
108 /// </summary>
109 private ManualResetEvent _workItemCompleted;
110
111 /// <summary>
112 /// A reference count to the _workItemCompleted.
113 /// When it reaches to zero _workItemCompleted is Closed
114 /// </summary>
115 private int _workItemCompletedRefCount;
116
117 /// <summary>
118 /// Represents the result state of the work item
119 /// </summary>
120 private WorkItemResult _workItemResult;
121
122 /// <summary>
123 /// Work item info
124 /// </summary>
125 private WorkItemInfo _workItemInfo;
126
127 /// <summary>
128 /// Called when the WorkItem starts
129 /// </summary>
130 private event WorkItemStateCallback _workItemStartedEvent;
131
132 /// <summary>
133 /// Called when the WorkItem completes
134 /// </summary>
135 private event WorkItemStateCallback _workItemCompletedEvent;
136
137 /// <summary>
138 /// A reference to an object that indicates whatever the
139 /// WorkItemsGroup has been canceled
140 /// </summary>
141 private CanceledWorkItemsGroup _canceledWorkItemsGroup = CanceledWorkItemsGroup.NotCanceledWorkItemsGroup;
142
143 /// <summary>
144 /// The work item group this work item belong to.
145 ///
146 /// </summary>
147 private IWorkItemsGroup _workItemsGroup;
148
149 #region Performance Counter fields
150
151 /// <summary>
152 /// The time when the work items is queued.
153 /// Used with the performance counter.
154 /// </summary>
155 private DateTime _queuedTime;
156
157 /// <summary>
158 /// The time when the work items starts its execution.
159 /// Used with the performance counter.
160 /// </summary>
161 private DateTime _beginProcessTime;
162
163 /// <summary>
164 /// The time when the work items ends its execution.
165 /// Used with the performance counter.
166 /// </summary>
167 private DateTime _endProcessTime;
168
169 #endregion
170
171 #endregion
172
173 #region Properties
174
175 public TimeSpan WaitingTime
176 {
177 get
178 {
179 return (_beginProcessTime - _queuedTime);
180 }
181 }
182
183 public TimeSpan ProcessTime
184 {
185 get
186 {
187 return (_endProcessTime - _beginProcessTime);
188 }
189 }
190
191 #endregion
192
193 #region Construction
194
195 /// <summary>
196 /// Initialize the callback holding object.
197 /// </summary>
198 /// <param name="callback">Callback delegate for the callback.</param>
199 /// <param name="state">State with which to call the callback delegate.</param>
200 ///
201 /// We assume that the WorkItem object is created within the thread
202 /// that meant to run the callback
203 public WorkItem(
204 IWorkItemsGroup workItemsGroup,
205 WorkItemInfo workItemInfo,
206 WorkItemCallback callback,
207 object state)
208 {
209 _workItemsGroup = workItemsGroup;
210 _workItemInfo = workItemInfo;
211
212 if (_workItemInfo.UseCallerCallContext || _workItemInfo.UseCallerHttpContext)
213 {
214 _callerContext = CallerThreadContext.Capture(_workItemInfo.UseCallerCallContext, _workItemInfo.UseCallerHttpContext);
215 }
216
217 _callback = callback;
218 _state = state;
219 _workItemResult = new WorkItemResult(this);
220 Initialize();
221 }
222
223 internal void Initialize()
224 {
225 _workItemState = WorkItemState.InQueue;
226 _workItemCompleted = null;
227 _workItemCompletedRefCount = 0;
228 }
229
230 internal bool WasQueuedBy(IWorkItemsGroup workItemsGroup)
231 {
232 return (workItemsGroup == _workItemsGroup);
233 }
234
235
236 #endregion
237
238 #region Methods
239
240 public CanceledWorkItemsGroup CanceledWorkItemsGroup
241 {
242 get
243 {
244 return _canceledWorkItemsGroup;
245 }
246
247 set
248 {
249 _canceledWorkItemsGroup = value;
250 }
251 }
252
253 /// <summary>
254 /// Change the state of the work item to in progress if it wasn't canceled.
255 /// </summary>
256 /// <returns>
257 /// Return true on success or false in case the work item was canceled.
258 /// If the work item needs to run a post execute then the method will return true.
259 /// </returns>
260 public bool StartingWorkItem()
261 {
262 _beginProcessTime = DateTime.Now;
263
264 lock(this)
265 {
266 if (IsCanceled)
267 {
268 bool result = false;
269 if ((_workItemInfo.PostExecuteWorkItemCallback != null) &&
270 ((_workItemInfo.CallToPostExecute & CallToPostExecute.WhenWorkItemCanceled) == CallToPostExecute.WhenWorkItemCanceled))
271 {
272 result = true;
273 }
274
275 return result;
276 }
277
278 Debug.Assert(WorkItemState.InQueue == GetWorkItemState());
279
280 SetWorkItemState(WorkItemState.InProgress);
281 }
282
283 return true;
284 }
285
286 /// <summary>
287 /// Execute the work item and the post execute
288 /// </summary>
289 public void Execute()
290 {
291 CallToPostExecute currentCallToPostExecute = 0;
292
293 // Execute the work item if we are in the correct state
294 switch(GetWorkItemState())
295 {
296 case WorkItemState.InProgress:
297 currentCallToPostExecute |= CallToPostExecute.WhenWorkItemNotCanceled;
298 ExecuteWorkItem();
299 break;
300 case WorkItemState.Canceled:
301 currentCallToPostExecute |= CallToPostExecute.WhenWorkItemCanceled;
302 break;
303 default:
304 Debug.Assert(false);
305 throw new NotSupportedException();
306 }
307
308 // Run the post execute as needed
309 if ((currentCallToPostExecute & _workItemInfo.CallToPostExecute) != 0)
310 {
311 PostExecute();
312 }
313
314 _endProcessTime = DateTime.Now;
315 }
316
317 internal void FireWorkItemCompleted()
318 {
319 try
320 {
321 if (null != _workItemCompletedEvent)
322 {
323 _workItemCompletedEvent(this);
324 }
325 }
326 catch // Ignore exceptions
327 {}
328 }
329
330 /// <summary>
331 /// Execute the work item
332 /// </summary>
333 private void ExecuteWorkItem()
334 {
335 CallerThreadContext ctc = null;
336 if (null != _callerContext)
337 {
338 ctc = CallerThreadContext.Capture(_callerContext.CapturedCallContext, _callerContext.CapturedHttpContext);
339 CallerThreadContext.Apply(_callerContext);
340 }
341
342 Exception exception = null;
343 object result = null;
344
345 try
346 {
347 result = _callback(_state);
348 }
349 catch (Exception e)
350 {
351 // Save the exception so we can rethrow it later
352 exception = e;
353 }
354
355 if (null != _callerContext)
356 {
357 CallerThreadContext.Apply(ctc);
358 }
359
360 SetResult(result, exception);
361 }
362
363 /// <summary>
364 /// Runs the post execute callback
365 /// </summary>
366 private void PostExecute()
367 {
368 if (null != _workItemInfo.PostExecuteWorkItemCallback)
369 {
370 try
371 {
372 _workItemInfo.PostExecuteWorkItemCallback(this._workItemResult);
373 }
374 catch (Exception e)
375 {
376 Debug.Assert(null != e);
377 }
378 }
379 }
380
381 /// <summary>
382 /// Set the result of the work item to return
383 /// </summary>
384 /// <param name="result">The result of the work item</param>
385 internal void SetResult(object result, Exception exception)
386 {
387 _result = result;
388 _exception = exception;
389 SignalComplete(false);
390 }
391
392 /// <summary>
393 /// Returns the work item result
394 /// </summary>
395 /// <returns>The work item result</returns>
396 internal IWorkItemResult GetWorkItemResult()
397 {
398 return _workItemResult;
399 }
400
401 /// <summary>
402 /// Wait for all work items to complete
403 /// </summary>
404 /// <param name="workItemResults">Array of work item result objects</param>
405 /// <param name="millisecondsTimeout">The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely.</param>
406 /// <param name="exitContext">
407 /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
408 /// </param>
409 /// <param name="cancelWaitHandle">A cancel wait handle to interrupt the wait if needed</param>
410 /// <returns>
411 /// true when every work item in workItemResults has completed; otherwise false.
412 /// </returns>
413 internal static bool WaitAll(
414 IWorkItemResult [] workItemResults,
415 int millisecondsTimeout,
416 bool exitContext,
417 WaitHandle cancelWaitHandle)
418 {
419 if (0 == workItemResults.Length)
420 {
421 return true;
422 }
423
424 bool success;
425 WaitHandle [] waitHandles = new WaitHandle[workItemResults.Length];;
426 GetWaitHandles(workItemResults, waitHandles);
427
428 if ((null == cancelWaitHandle) && (waitHandles.Length <= 64))
429 {
430 success = WaitHandle.WaitAll(waitHandles, millisecondsTimeout, exitContext);
431 }
432 else
433 {
434 success = true;
435 int millisecondsLeft = millisecondsTimeout;
436 DateTime start = DateTime.Now;
437
438 WaitHandle [] whs;
439 if (null != cancelWaitHandle)
440 {
441 whs = new WaitHandle [] { null, cancelWaitHandle };
442 }
443 else
444 {
445 whs = new WaitHandle [] { null };
446 }
447
448 bool waitInfinitely = (Timeout.Infinite == millisecondsTimeout);
449 // Iterate over the wait handles and wait for each one to complete.
450 // We cannot use WaitHandle.WaitAll directly, because the cancelWaitHandle
451 // won't affect it.
452 // Each iteration we update the time left for the timeout.
453 for(int i = 0; i < workItemResults.Length; ++i)
454 {
455 // WaitAny don't work with negative numbers
456 if (!waitInfinitely && (millisecondsLeft < 0))
457 {
458 success = false;
459 break;
460 }
461
462 whs[0] = waitHandles[i];
463 int result = WaitHandle.WaitAny(whs, millisecondsLeft, exitContext);
464 if((result > 0) || (WaitHandle.WaitTimeout == result))
465 {
466 success = false;
467 break;
468 }
469
470 if(!waitInfinitely)
471 {
472 // Update the time left to wait
473 TimeSpan ts = DateTime.Now - start;
474 millisecondsLeft = millisecondsTimeout - (int)ts.TotalMilliseconds;
475 }
476 }
477 }
478 // Release the wait handles
479 ReleaseWaitHandles(workItemResults);
480
481 return success;
482 }
483
484 /// <summary>
485 /// Waits for any of the work items in the specified array to complete, cancel, or timeout
486 /// </summary>
487 /// <param name="workItemResults">Array of work item result objects</param>
488 /// <param name="millisecondsTimeout">The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely.</param>
489 /// <param name="exitContext">
490 /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
491 /// </param>
492 /// <param name="cancelWaitHandle">A cancel wait handle to interrupt the wait if needed</param>
493 /// <returns>
494 /// The array index of the work item result that satisfied the wait, or WaitTimeout if no work item result satisfied the wait and a time interval equivalent to millisecondsTimeout has passed or the work item has been canceled.
495 /// </returns>
496 internal static int WaitAny(
497 IWorkItemResult [] workItemResults,
498 int millisecondsTimeout,
499 bool exitContext,
500 WaitHandle cancelWaitHandle)
501 {
502 WaitHandle [] waitHandles = null;
503
504 if (null != cancelWaitHandle)
505 {
506 waitHandles = new WaitHandle[workItemResults.Length+1];
507 GetWaitHandles(workItemResults, waitHandles);
508 waitHandles[workItemResults.Length] = cancelWaitHandle;
509 }
510 else
511 {
512 waitHandles = new WaitHandle[workItemResults.Length];
513 GetWaitHandles(workItemResults, waitHandles);
514 }
515
516 int result = WaitHandle.WaitAny(waitHandles, millisecondsTimeout, exitContext);
517
518 // Treat cancel as timeout
519 if (null != cancelWaitHandle)
520 {
521 if (result == workItemResults.Length)
522 {
523 result = WaitHandle.WaitTimeout;
524 }
525 }
526
527 ReleaseWaitHandles(workItemResults);
528
529 return result;
530 }
531
532 /// <summary>
533 /// Fill an array of wait handles with the work items wait handles.
534 /// </summary>
535 /// <param name="workItemResults">An array of work item results</param>
536 /// <param name="waitHandles">An array of wait handles to fill</param>
537 private static void GetWaitHandles(
538 IWorkItemResult [] workItemResults,
539 WaitHandle [] waitHandles)
540 {
541 for(int i = 0; i < workItemResults.Length; ++i)
542 {
543 WorkItemResult wir = workItemResults[i] as WorkItemResult;
544 Debug.Assert(null != wir, "All workItemResults must be WorkItemResult objects");
545
546 waitHandles[i] = wir.GetWorkItem().GetWaitHandle();
547 }
548 }
549
550 /// <summary>
551 /// Release the work items' wait handles
552 /// </summary>
553 /// <param name="workItemResults">An array of work item results</param>
554 private static void ReleaseWaitHandles(IWorkItemResult [] workItemResults)
555 {
556 for(int i = 0; i < workItemResults.Length; ++i)
557 {
558 WorkItemResult wir = workItemResults[i] as WorkItemResult;
559
560 wir.GetWorkItem().ReleaseWaitHandle();
561 }
562 }
563
564
565 #endregion
566
567 #region Private Members
568
569 private WorkItemState GetWorkItemState()
570 {
571 if (_canceledWorkItemsGroup.IsCanceled)
572 {
573 return WorkItemState.Canceled;
574 }
575 return _workItemState;
576
577 }
578 /// <summary>
579 /// Sets the work item's state
580 /// </summary>
581 /// <param name="workItemState">The state to set the work item to</param>
582 private void SetWorkItemState(WorkItemState workItemState)
583 {
584 lock(this)
585 {
586 _workItemState = workItemState;
587 }
588 }
589
590 /// <summary>
591 /// Signals that work item has been completed or canceled
592 /// </summary>
593 /// <param name="canceled">Indicates that the work item has been canceled</param>
594 private void SignalComplete(bool canceled)
595 {
596 SetWorkItemState(canceled ? WorkItemState.Canceled : WorkItemState.Completed);
597 lock(this)
598 {
599 // If someone is waiting then signal.
600 if (null != _workItemCompleted)
601 {
602 _workItemCompleted.Set();
603 }
604 }
605 }
606
607 internal void WorkItemIsQueued()
608 {
609 _queuedTime = DateTime.Now;
610 }
611
612 #endregion
613
614 #region Members exposed by WorkItemResult
615
616 /// <summary>
617 /// Cancel the work item if it didn't start running yet.
618 /// </summary>
619 /// <returns>Returns true on success or false if the work item is in progress or already completed</returns>
620 private bool Cancel()
621 {
622 lock(this)
623 {
624 switch(GetWorkItemState())
625 {
626 case WorkItemState.Canceled:
627 //Debug.WriteLine("Work item already canceled");
628 return true;
629 case WorkItemState.Completed:
630 case WorkItemState.InProgress:
631 //Debug.WriteLine("Work item cannot be canceled");
632 return false;
633 case WorkItemState.InQueue:
634 // Signal to the wait for completion that the work
635 // item has been completed (canceled). There is no
636 // reason to wait for it to get out of the queue
637 SignalComplete(true);
638 //Debug.WriteLine("Work item canceled");
639 return true;
640 }
641 }
642 return false;
643 }
644
645 /// <summary>
646 /// Get the result of the work item.
647 /// If the work item didn't run yet then the caller waits for the result, timeout, or cancel.
648 /// In case of error the method throws and exception
649 /// </summary>
650 /// <returns>The result of the work item</returns>
651 private object GetResult(
652 int millisecondsTimeout,
653 bool exitContext,
654 WaitHandle cancelWaitHandle)
655 {
656 Exception e = null;
657 object result = GetResult(millisecondsTimeout, exitContext, cancelWaitHandle, out e);
658 if (null != e)
659 {
660 throw new WorkItemResultException("The work item caused an excpetion, see the inner exception for details", e);
661 }
662 return result;
663 }
664
665 /// <summary>
666 /// Get the result of the work item.
667 /// If the work item didn't run yet then the caller waits for the result, timeout, or cancel.
668 /// In case of error the e argument is filled with the exception
669 /// </summary>
670 /// <returns>The result of the work item</returns>
671 private object GetResult(
672 int millisecondsTimeout,
673 bool exitContext,
674 WaitHandle cancelWaitHandle,
675 out Exception e)
676 {
677 e = null;
678
679 // Check for cancel
680 if (WorkItemState.Canceled == GetWorkItemState())
681 {
682 throw new WorkItemCancelException("Work item canceled");
683 }
684
685 // Check for completion
686 if (IsCompleted)
687 {
688 e = _exception;
689 return _result;
690 }
691
692 // If no cancelWaitHandle is provided
693 if (null == cancelWaitHandle)
694 {
695 WaitHandle wh = GetWaitHandle();
696
697 bool timeout = !wh.WaitOne(millisecondsTimeout, exitContext);
698
699 ReleaseWaitHandle();
700
701 if (timeout)
702 {
703 throw new WorkItemTimeoutException("Work item timeout");
704 }
705 }
706 else
707 {
708 WaitHandle wh = GetWaitHandle();
709 int result = WaitHandle.WaitAny(new WaitHandle[] { wh, cancelWaitHandle });
710 ReleaseWaitHandle();
711
712 switch(result)
713 {
714 case 0:
715 // The work item signaled
716 // Note that the signal could be also as a result of canceling the
717 // work item (not the get result)
718 break;
719 case 1:
720 case WaitHandle.WaitTimeout:
721 throw new WorkItemTimeoutException("Work item timeout");
722 default:
723 Debug.Assert(false);
724 break;
725
726 }
727 }
728
729 // Check for cancel
730 if (WorkItemState.Canceled == GetWorkItemState())
731 {
732 throw new WorkItemCancelException("Work item canceled");
733 }
734
735 Debug.Assert(IsCompleted);
736
737 e = _exception;
738
739 // Return the result
740 return _result;
741 }
742
743 /// <summary>
744 /// A wait handle to wait for completion, cancel, or timeout
745 /// </summary>
746 private WaitHandle GetWaitHandle()
747 {
748 lock(this)
749 {
750 if (null == _workItemCompleted)
751 {
752 _workItemCompleted = new ManualResetEvent(IsCompleted);
753 }
754 ++_workItemCompletedRefCount;
755 }
756 return _workItemCompleted;
757 }
758
759 private void ReleaseWaitHandle()
760 {
761 lock(this)
762 {
763 if (null != _workItemCompleted)
764 {
765 --_workItemCompletedRefCount;
766 if (0 == _workItemCompletedRefCount)
767 {
768 _workItemCompleted.Close();
769 _workItemCompleted = null;
770 }
771 }
772 }
773 }
774
775 /// <summary>
776 /// Returns true when the work item has completed or canceled
777 /// </summary>
778 private bool IsCompleted
779 {
780 get
781 {
782 lock(this)
783 {
784 WorkItemState workItemState = GetWorkItemState();
785 return ((workItemState == WorkItemState.Completed) ||
786 (workItemState == WorkItemState.Canceled));
787 }
788 }
789 }
790
791 /// <summary>
792 /// Returns true when the work item has canceled
793 /// </summary>
794 public bool IsCanceled
795 {
796 get
797 {
798 lock(this)
799 {
800 return (GetWorkItemState() == WorkItemState.Canceled);
801 }
802 }
803 }
804
805 #endregion
806
807 #region IHasWorkItemPriority Members
808
809 /// <summary>
810 /// Returns the priority of the work item
811 /// </summary>
812 public WorkItemPriority WorkItemPriority
813 {
814 get
815 {
816 return _workItemInfo.WorkItemPriority;
817 }
818 }
819
820 #endregion
821
822 internal event WorkItemStateCallback OnWorkItemStarted
823 {
824 add
825 {
826 _workItemStartedEvent += value;
827 }
828 remove
829 {
830 _workItemStartedEvent -= value;
831 }
832 }
833
834 internal event WorkItemStateCallback OnWorkItemCompleted
835 {
836 add
837 {
838 _workItemCompletedEvent += value;
839 }
840 remove
841 {
842 _workItemCompletedEvent -= value;
843 }
844 }
845
846
847 #region WorkItemResult class
848
849 private class WorkItemResult : IWorkItemResult, IInternalWorkItemResult
850 {
851 /// <summary>
852 /// A back reference to the work item
853 /// </summary>
854 private WorkItem _workItem;
855
856 public WorkItemResult(WorkItem workItem)
857 {
858 _workItem = workItem;
859 }
860
861 internal WorkItem GetWorkItem()
862 {
863 return _workItem;
864 }
865
866 #region IWorkItemResult Members
867
868 public bool IsCompleted
869 {
870 get
871 {
872 return _workItem.IsCompleted;
873 }
874 }
875
876 public void Abort()
877 {
878 _workItem.Abort();
879 }
880
881 public bool IsCanceled
882 {
883 get
884 {
885 return _workItem.IsCanceled;
886 }
887 }
888
889 public object GetResult()
890 {
891 return _workItem.GetResult(Timeout.Infinite, true, null);
892 }
893
894 public object GetResult(int millisecondsTimeout, bool exitContext)
895 {
896 return _workItem.GetResult(millisecondsTimeout, exitContext, null);
897 }
898
899 public object GetResult(TimeSpan timeout, bool exitContext)
900 {
901 return _workItem.GetResult((int)timeout.TotalMilliseconds, exitContext, null);
902 }
903
904 public object GetResult(int millisecondsTimeout, bool exitContext, WaitHandle cancelWaitHandle)
905 {
906 return _workItem.GetResult(millisecondsTimeout, exitContext, cancelWaitHandle);
907 }
908
909 public object GetResult(TimeSpan timeout, bool exitContext, WaitHandle cancelWaitHandle)
910 {
911 return _workItem.GetResult((int)timeout.TotalMilliseconds, exitContext, cancelWaitHandle);
912 }
913
914 public object GetResult(out Exception e)
915 {
916 return _workItem.GetResult(Timeout.Infinite, true, null, out e);
917 }
918
919 public object GetResult(int millisecondsTimeout, bool exitContext, out Exception e)
920 {
921 return _workItem.GetResult(millisecondsTimeout, exitContext, null, out e);
922 }
923
924 public object GetResult(TimeSpan timeout, bool exitContext, out Exception e)
925 {
926 return _workItem.GetResult((int)timeout.TotalMilliseconds, exitContext, null, out e);
927 }
928
929 public object GetResult(int millisecondsTimeout, bool exitContext, WaitHandle cancelWaitHandle, out Exception e)
930 {
931 return _workItem.GetResult(millisecondsTimeout, exitContext, cancelWaitHandle, out e);
932 }
933
934 public object GetResult(TimeSpan timeout, bool exitContext, WaitHandle cancelWaitHandle, out Exception e)
935 {
936 return _workItem.GetResult((int)timeout.TotalMilliseconds, exitContext, cancelWaitHandle, out e);
937 }
938
939 public bool Cancel()
940 {
941 return _workItem.Cancel();
942 }
943
944 public object State
945 {
946 get
947 {
948 return _workItem._state;
949 }
950 }
951
952 public WorkItemPriority WorkItemPriority
953 {
954 get
955 {
956 return _workItem._workItemInfo.WorkItemPriority;
957 }
958 }
959
960 /// <summary>
961 /// Return the result, same as GetResult()
962 /// </summary>
963 public object Result
964 {
965 get { return GetResult(); }
966 }
967
968 /// <summary>
969 /// Returns the exception if occured otherwise returns null.
970 /// This value is valid only after the work item completed,
971 /// before that it is always null.
972 /// </summary>
973 public object Exception
974 {
975 get { return _workItem._exception; }
976 }
977
978 #endregion
979
980 #region IInternalWorkItemResult Members
981
982 public event WorkItemStateCallback OnWorkItemStarted
983 {
984 add
985 {
986 _workItem.OnWorkItemStarted += value;
987 }
988 remove
989 {
990 _workItem.OnWorkItemStarted -= value;
991 }
992 }
993
994
995 public event WorkItemStateCallback OnWorkItemCompleted
996 {
997 add
998 {
999 _workItem.OnWorkItemCompleted += value;
1000 }
1001 remove
1002 {
1003 _workItem.OnWorkItemCompleted -= value;
1004 }
1005 }
1006
1007 #endregion
1008 }
1009
1010 #endregion
1011
1012 public void DisposeOfState()
1013 {
1014 if (_workItemInfo.DisposeOfStateObjects)
1015 {
1016 IDisposable disp = _state as IDisposable;
1017 if (null != disp)
1018 {
1019 disp.Dispose();
1020 _state = null;
1021 }
1022 }
1023 }
1024
1025 public void Abort()
1026 {
1027 lock (this)
1028 {
1029 if(currentThread != null)
1030 currentThread.Abort();
1031 }
1032 }
1033 }
1034 #endregion
1035}
diff --git a/ThirdParty/SmartThreadPool/WorkItemFactory.cs b/ThirdParty/SmartThreadPool/WorkItemFactory.cs
new file mode 100644
index 0000000..dfcb54f
--- /dev/null
+++ b/ThirdParty/SmartThreadPool/WorkItemFactory.cs
@@ -0,0 +1,333 @@
1// Ami Bar
2// amibar@gmail.com
3
4using System;
5
6namespace Amib.Threading.Internal
7{
8 #region WorkItemFactory class
9
10 public class WorkItemFactory
11 {
12 /// <summary>
13 /// Create a new work item
14 /// </summary>
15 /// <param name="wigStartInfo">Work item group start information</param>
16 /// <param name="callback">A callback to execute</param>
17 /// <returns>Returns a work item</returns>
18 public static WorkItem CreateWorkItem(
19 IWorkItemsGroup workItemsGroup,
20 WIGStartInfo wigStartInfo,
21 WorkItemCallback callback)
22 {
23 return CreateWorkItem(workItemsGroup, wigStartInfo, callback, null);
24 }
25
26 /// <summary>
27 /// Create a new work item
28 /// </summary>
29 /// <param name="wigStartInfo">Work item group start information</param>
30 /// <param name="callback">A callback to execute</param>
31 /// <param name="workItemPriority">The priority of the work item</param>
32 /// <returns>Returns a work item</returns>
33 public static WorkItem CreateWorkItem(
34 IWorkItemsGroup workItemsGroup,
35 WIGStartInfo wigStartInfo,
36 WorkItemCallback callback,
37 WorkItemPriority workItemPriority)
38 {
39 return CreateWorkItem(workItemsGroup, wigStartInfo, callback, null, workItemPriority);
40 }
41
42 /// <summary>
43 /// Create a new work item
44 /// </summary>
45 /// <param name="wigStartInfo">Work item group start information</param>
46 /// <param name="workItemInfo">Work item info</param>
47 /// <param name="callback">A callback to execute</param>
48 /// <returns>Returns a work item</returns>
49 public static WorkItem CreateWorkItem(
50 IWorkItemsGroup workItemsGroup,
51 WIGStartInfo wigStartInfo,
52 WorkItemInfo workItemInfo,
53 WorkItemCallback callback)
54 {
55 return CreateWorkItem(
56 workItemsGroup,
57 wigStartInfo,
58 workItemInfo,
59 callback,
60 null);
61 }
62
63 /// <summary>
64 /// Create a new work item
65 /// </summary>
66 /// <param name="wigStartInfo">Work item group start information</param>
67 /// <param name="callback">A callback to execute</param>
68 /// <param name="state">
69 /// The context object of the work item. Used for passing arguments to the work item.
70 /// </param>
71 /// <returns>Returns a work item</returns>
72 public static WorkItem CreateWorkItem(
73 IWorkItemsGroup workItemsGroup,
74 WIGStartInfo wigStartInfo,
75 WorkItemCallback callback,
76 object state)
77 {
78 ValidateCallback(callback);
79
80 WorkItemInfo workItemInfo = new WorkItemInfo();
81 workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext;
82 workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext;
83 workItemInfo.PostExecuteWorkItemCallback = wigStartInfo.PostExecuteWorkItemCallback;
84 workItemInfo.CallToPostExecute = wigStartInfo.CallToPostExecute;
85 workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
86
87 WorkItem workItem = new WorkItem(
88 workItemsGroup,
89 workItemInfo,
90 callback,
91 state);
92 return workItem;
93 }
94
95 /// <summary>
96 /// Create a new work item
97 /// </summary>
98 /// <param name="wigStartInfo">Work item group start information</param>
99 /// <param name="callback">A callback to execute</param>
100 /// <param name="state">
101 /// The context object of the work item. Used for passing arguments to the work item.
102 /// </param>
103 /// <param name="workItemPriority">The work item priority</param>
104 /// <returns>Returns a work item</returns>
105 public static WorkItem CreateWorkItem(
106 IWorkItemsGroup workItemsGroup,
107 WIGStartInfo wigStartInfo,
108 WorkItemCallback callback,
109 object state,
110 WorkItemPriority workItemPriority)
111 {
112 ValidateCallback(callback);
113
114 WorkItemInfo workItemInfo = new WorkItemInfo();
115 workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext;
116 workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext;
117 workItemInfo.PostExecuteWorkItemCallback = wigStartInfo.PostExecuteWorkItemCallback;
118 workItemInfo.CallToPostExecute = wigStartInfo.CallToPostExecute;
119 workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
120 workItemInfo.WorkItemPriority = workItemPriority;
121
122 WorkItem workItem = new WorkItem(
123 workItemsGroup,
124 workItemInfo,
125 callback,
126 state);
127
128 return workItem;
129 }
130
131 /// <summary>
132 /// Create a new work item
133 /// </summary>
134 /// <param name="wigStartInfo">Work item group start information</param>
135 /// <param name="workItemInfo">Work item information</param>
136 /// <param name="callback">A callback to execute</param>
137 /// <param name="state">
138 /// The context object of the work item. Used for passing arguments to the work item.
139 /// </param>
140 /// <returns>Returns a work item</returns>
141 public static WorkItem CreateWorkItem(
142 IWorkItemsGroup workItemsGroup,
143 WIGStartInfo wigStartInfo,
144 WorkItemInfo workItemInfo,
145 WorkItemCallback callback,
146 object state)
147 {
148 ValidateCallback(callback);
149 ValidateCallback(workItemInfo.PostExecuteWorkItemCallback);
150
151 WorkItem workItem = new WorkItem(
152 workItemsGroup,
153 new WorkItemInfo(workItemInfo),
154 callback,
155 state);
156
157 return workItem;
158 }
159
160 /// <summary>
161 /// Create a new work item
162 /// </summary>
163 /// <param name="wigStartInfo">Work item group start information</param>
164 /// <param name="callback">A callback to execute</param>
165 /// <param name="state">
166 /// The context object of the work item. Used for passing arguments to the work item.
167 /// </param>
168 /// <param name="postExecuteWorkItemCallback">
169 /// A delegate to call after the callback completion
170 /// </param>
171 /// <returns>Returns a work item</returns>
172 public static WorkItem CreateWorkItem(
173 IWorkItemsGroup workItemsGroup,
174 WIGStartInfo wigStartInfo,
175 WorkItemCallback callback,
176 object state,
177 PostExecuteWorkItemCallback postExecuteWorkItemCallback)
178 {
179 ValidateCallback(callback);
180 ValidateCallback(postExecuteWorkItemCallback);
181
182 WorkItemInfo workItemInfo = new WorkItemInfo();
183 workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext;
184 workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext;
185 workItemInfo.PostExecuteWorkItemCallback = postExecuteWorkItemCallback;
186 workItemInfo.CallToPostExecute = wigStartInfo.CallToPostExecute;
187 workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
188
189 WorkItem workItem = new WorkItem(
190 workItemsGroup,
191 workItemInfo,
192 callback,
193 state);
194
195 return workItem;
196 }
197
198 /// <summary>
199 /// Create a new work item
200 /// </summary>
201 /// <param name="wigStartInfo">Work item group start information</param>
202 /// <param name="callback">A callback to execute</param>
203 /// <param name="state">
204 /// The context object of the work item. Used for passing arguments to the work item.
205 /// </param>
206 /// <param name="postExecuteWorkItemCallback">
207 /// A delegate to call after the callback completion
208 /// </param>
209 /// <param name="workItemPriority">The work item priority</param>
210 /// <returns>Returns a work item</returns>
211 public static WorkItem CreateWorkItem(
212 IWorkItemsGroup workItemsGroup,
213 WIGStartInfo wigStartInfo,
214 WorkItemCallback callback,
215 object state,
216 PostExecuteWorkItemCallback postExecuteWorkItemCallback,
217 WorkItemPriority workItemPriority)
218 {
219 ValidateCallback(callback);
220 ValidateCallback(postExecuteWorkItemCallback);
221
222 WorkItemInfo workItemInfo = new WorkItemInfo();
223 workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext;
224 workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext;
225 workItemInfo.PostExecuteWorkItemCallback = postExecuteWorkItemCallback;
226 workItemInfo.CallToPostExecute = wigStartInfo.CallToPostExecute;
227 workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
228 workItemInfo.WorkItemPriority = workItemPriority;
229
230 WorkItem workItem = new WorkItem(
231 workItemsGroup,
232 workItemInfo,
233 callback,
234 state);
235
236 return workItem;
237 }
238
239 /// <summary>
240 /// Create a new work item
241 /// </summary>
242 /// <param name="wigStartInfo">Work item group start information</param>
243 /// <param name="callback">A callback to execute</param>
244 /// <param name="state">
245 /// The context object of the work item. Used for passing arguments to the work item.
246 /// </param>
247 /// <param name="postExecuteWorkItemCallback">
248 /// A delegate to call after the callback completion
249 /// </param>
250 /// <param name="callToPostExecute">Indicates on which cases to call to the post execute callback</param>
251 /// <returns>Returns a work item</returns>
252 public static WorkItem CreateWorkItem(
253 IWorkItemsGroup workItemsGroup,
254 WIGStartInfo wigStartInfo,
255 WorkItemCallback callback,
256 object state,
257 PostExecuteWorkItemCallback postExecuteWorkItemCallback,
258 CallToPostExecute callToPostExecute)
259 {
260 ValidateCallback(callback);
261 ValidateCallback(postExecuteWorkItemCallback);
262
263 WorkItemInfo workItemInfo = new WorkItemInfo();
264 workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext;
265 workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext;
266 workItemInfo.PostExecuteWorkItemCallback = postExecuteWorkItemCallback;
267 workItemInfo.CallToPostExecute = callToPostExecute;
268 workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
269
270 WorkItem workItem = new WorkItem(
271 workItemsGroup,
272 workItemInfo,
273 callback,
274 state);
275
276 return workItem;
277 }
278
279 /// <summary>
280 /// Create a new work item
281 /// </summary>
282 /// <param name="wigStartInfo">Work item group start information</param>
283 /// <param name="callback">A callback to execute</param>
284 /// <param name="state">
285 /// The context object of the work item. Used for passing arguments to the work item.
286 /// </param>
287 /// <param name="postExecuteWorkItemCallback">
288 /// A delegate to call after the callback completion
289 /// </param>
290 /// <param name="callToPostExecute">Indicates on which cases to call to the post execute callback</param>
291 /// <param name="workItemPriority">The work item priority</param>
292 /// <returns>Returns a work item</returns>
293 public static WorkItem CreateWorkItem(
294 IWorkItemsGroup workItemsGroup,
295 WIGStartInfo wigStartInfo,
296 WorkItemCallback callback,
297 object state,
298 PostExecuteWorkItemCallback postExecuteWorkItemCallback,
299 CallToPostExecute callToPostExecute,
300 WorkItemPriority workItemPriority)
301 {
302
303 ValidateCallback(callback);
304 ValidateCallback(postExecuteWorkItemCallback);
305
306 WorkItemInfo workItemInfo = new WorkItemInfo();
307 workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext;
308 workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext;
309 workItemInfo.PostExecuteWorkItemCallback = postExecuteWorkItemCallback;
310 workItemInfo.CallToPostExecute = callToPostExecute;
311 workItemInfo.WorkItemPriority = workItemPriority;
312 workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
313
314 WorkItem workItem = new WorkItem(
315 workItemsGroup,
316 workItemInfo,
317 callback,
318 state);
319
320 return workItem;
321 }
322
323 private static void ValidateCallback(Delegate callback)
324 {
325 if(callback.GetInvocationList().Length > 1)
326 {
327 throw new NotSupportedException("SmartThreadPool doesn't support delegates chains");
328 }
329 }
330 }
331
332 #endregion
333}
diff --git a/ThirdParty/SmartThreadPool/WorkItemInfo.cs b/ThirdParty/SmartThreadPool/WorkItemInfo.cs
new file mode 100644
index 0000000..c259339
--- /dev/null
+++ b/ThirdParty/SmartThreadPool/WorkItemInfo.cs
@@ -0,0 +1,102 @@
1// Ami Bar
2// amibar@gmail.com
3
4namespace Amib.Threading
5{
6 #region WorkItemInfo class
7
8 /// <summary>
9 /// Summary description for WorkItemInfo.
10 /// </summary>
11 public class WorkItemInfo
12 {
13 /// <summary>
14 /// Use the caller's security context
15 /// </summary>
16 private bool _useCallerCallContext;
17
18 /// <summary>
19 /// Use the caller's security context
20 /// </summary>
21 private bool _useCallerHttpContext;
22
23 /// <summary>
24 /// Dispose of the state object of a work item
25 /// </summary>
26 private bool _disposeOfStateObjects;
27
28 /// <summary>
29 /// The option to run the post execute
30 /// </summary>
31 private CallToPostExecute _callToPostExecute;
32
33 /// <summary>
34 /// A post execute callback to call when none is provided in
35 /// the QueueWorkItem method.
36 /// </summary>
37 private PostExecuteWorkItemCallback _postExecuteWorkItemCallback;
38
39 /// <summary>
40 /// The priority of the work item
41 /// </summary>
42 private WorkItemPriority _workItemPriority;
43
44 public WorkItemInfo()
45 {
46 _useCallerCallContext = SmartThreadPool.DefaultUseCallerCallContext;
47 _useCallerHttpContext = SmartThreadPool.DefaultUseCallerHttpContext;
48 _disposeOfStateObjects = SmartThreadPool.DefaultDisposeOfStateObjects;
49 _callToPostExecute = SmartThreadPool.DefaultCallToPostExecute;
50 _postExecuteWorkItemCallback = SmartThreadPool.DefaultPostExecuteWorkItemCallback;
51 _workItemPriority = SmartThreadPool.DefaultWorkItemPriority;
52 }
53
54 public WorkItemInfo(WorkItemInfo workItemInfo)
55 {
56 _useCallerCallContext = workItemInfo._useCallerCallContext;
57 _useCallerHttpContext = workItemInfo._useCallerHttpContext;
58 _disposeOfStateObjects = workItemInfo._disposeOfStateObjects;
59 _callToPostExecute = workItemInfo._callToPostExecute;
60 _postExecuteWorkItemCallback = workItemInfo._postExecuteWorkItemCallback;
61 _workItemPriority = workItemInfo._workItemPriority;
62 }
63
64 public bool UseCallerCallContext
65 {
66 get { return _useCallerCallContext; }
67 set { _useCallerCallContext = value; }
68 }
69
70 public bool UseCallerHttpContext
71 {
72 get { return _useCallerHttpContext; }
73 set { _useCallerHttpContext = value; }
74 }
75
76 public bool DisposeOfStateObjects
77 {
78 get { return _disposeOfStateObjects; }
79 set { _disposeOfStateObjects = value; }
80 }
81
82 public CallToPostExecute CallToPostExecute
83 {
84 get { return _callToPostExecute; }
85 set { _callToPostExecute = value; }
86 }
87
88 public PostExecuteWorkItemCallback PostExecuteWorkItemCallback
89 {
90 get { return _postExecuteWorkItemCallback; }
91 set { _postExecuteWorkItemCallback = value; }
92 }
93
94 public WorkItemPriority WorkItemPriority
95 {
96 get { return _workItemPriority; }
97 set { _workItemPriority = value; }
98 }
99 }
100
101 #endregion
102}
diff --git a/ThirdParty/SmartThreadPool/WorkItemsGroup.cs b/ThirdParty/SmartThreadPool/WorkItemsGroup.cs
new file mode 100644
index 0000000..01ac8dd
--- /dev/null
+++ b/ThirdParty/SmartThreadPool/WorkItemsGroup.cs
@@ -0,0 +1,512 @@
1// Ami Bar
2// amibar@gmail.com
3
4using System;
5using System.Threading;
6using System.Runtime.CompilerServices;
7using System.Diagnostics;
8
9namespace Amib.Threading.Internal
10{
11 #region WorkItemsGroup class
12
13 /// <summary>
14 /// Summary description for WorkItemsGroup.
15 /// </summary>
16 public class WorkItemsGroup : IWorkItemsGroup
17 {
18 #region Private members
19
20 private object _lock = new object();
21 /// <summary>
22 /// Contains the name of this instance of SmartThreadPool.
23 /// Can be changed by the user.
24 /// </summary>
25 private string _name = "WorkItemsGroup";
26
27 /// <summary>
28 /// A reference to the SmartThreadPool instance that created this
29 /// WorkItemsGroup.
30 /// </summary>
31 private SmartThreadPool _stp;
32
33 /// <summary>
34 /// The OnIdle event
35 /// </summary>
36 private event WorkItemsGroupIdleHandler _onIdle;
37
38 /// <summary>
39 /// Defines how many work items of this WorkItemsGroup can run at once.
40 /// </summary>
41 private int _concurrency;
42
43 /// <summary>
44 /// Priority queue to hold work items before they are passed
45 /// to the SmartThreadPool.
46 /// </summary>
47 private PriorityQueue _workItemsQueue;
48
49 /// <summary>
50 /// Indicate how many work items are waiting in the SmartThreadPool
51 /// queue.
52 /// This value is used to apply the concurrency.
53 /// </summary>
54 private int _workItemsInStpQueue;
55
56 /// <summary>
57 /// Indicate how many work items are currently running in the SmartThreadPool.
58 /// This value is used with the Cancel, to calculate if we can send new
59 /// work items to the STP.
60 /// </summary>
61 private int _workItemsExecutingInStp = 0;
62
63 /// <summary>
64 /// WorkItemsGroup start information
65 /// </summary>
66 private WIGStartInfo _workItemsGroupStartInfo;
67
68 /// <summary>
69 /// Signaled when all of the WorkItemsGroup's work item completed.
70 /// </summary>
71 private ManualResetEvent _isIdleWaitHandle = new ManualResetEvent(true);
72
73 /// <summary>
74 /// A common object for all the work items that this work items group
75 /// generate so we can mark them to cancel in O(1)
76 /// </summary>
77 private CanceledWorkItemsGroup _canceledWorkItemsGroup = new CanceledWorkItemsGroup();
78
79 #endregion
80
81 #region Construction
82
83 public WorkItemsGroup(
84 SmartThreadPool stp,
85 int concurrency,
86 WIGStartInfo wigStartInfo)
87 {
88 if (concurrency <= 0)
89 {
90 throw new ArgumentOutOfRangeException("concurrency", concurrency, "concurrency must be greater than zero");
91 }
92 _stp = stp;
93 _concurrency = concurrency;
94 _workItemsGroupStartInfo = new WIGStartInfo(wigStartInfo);
95 _workItemsQueue = new PriorityQueue();
96
97 // The _workItemsInStpQueue gets the number of currently executing work items,
98 // because once a work item is executing, it cannot be cancelled.
99 _workItemsInStpQueue = _workItemsExecutingInStp;
100 }
101
102 #endregion
103
104 #region IWorkItemsGroup implementation
105
106 /// <summary>
107 /// Get/Set the name of the SmartThreadPool instance
108 /// </summary>
109 public string Name
110 {
111 get
112 {
113 return _name;
114 }
115
116 set
117 {
118 _name = value;
119 }
120 }
121
122 /// <summary>
123 /// Queue a work item
124 /// </summary>
125 /// <param name="callback">A callback to execute</param>
126 /// <returns>Returns a work item result</returns>
127 public IWorkItemResult QueueWorkItem(WorkItemCallback callback)
128 {
129 WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, callback);
130 EnqueueToSTPNextWorkItem(workItem);
131 return workItem.GetWorkItemResult();
132 }
133
134 /// <summary>
135 /// Queue a work item
136 /// </summary>
137 /// <param name="callback">A callback to execute</param>
138 /// <param name="workItemPriority">The priority of the work item</param>
139 /// <returns>Returns a work item result</returns>
140 public IWorkItemResult QueueWorkItem(WorkItemCallback callback, WorkItemPriority workItemPriority)
141 {
142 WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, callback, workItemPriority);
143 EnqueueToSTPNextWorkItem(workItem);
144 return workItem.GetWorkItemResult();
145 }
146
147 /// <summary>
148 /// Queue a work item
149 /// </summary>
150 /// <param name="workItemInfo">Work item info</param>
151 /// <param name="callback">A callback to execute</param>
152 /// <returns>Returns a work item result</returns>
153 public IWorkItemResult QueueWorkItem(WorkItemInfo workItemInfo, WorkItemCallback callback)
154 {
155 WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, workItemInfo, callback);
156 EnqueueToSTPNextWorkItem(workItem);
157 return workItem.GetWorkItemResult();
158 }
159
160 /// <summary>
161 /// Queue a work item
162 /// </summary>
163 /// <param name="callback">A callback to execute</param>
164 /// <param name="state">
165 /// The context object of the work item. Used for passing arguments to the work item.
166 /// </param>
167 /// <returns>Returns a work item result</returns>
168 public IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state)
169 {
170 WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, callback, state);
171 EnqueueToSTPNextWorkItem(workItem);
172 return workItem.GetWorkItemResult();
173 }
174
175 /// <summary>
176 /// Queue a work item
177 /// </summary>
178 /// <param name="callback">A callback to execute</param>
179 /// <param name="state">
180 /// The context object of the work item. Used for passing arguments to the work item.
181 /// </param>
182 /// <param name="workItemPriority">The work item priority</param>
183 /// <returns>Returns a work item result</returns>
184 public IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, WorkItemPriority workItemPriority)
185 {
186 WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, callback, state, workItemPriority);
187 EnqueueToSTPNextWorkItem(workItem);
188 return workItem.GetWorkItemResult();
189 }
190
191 /// <summary>
192 /// Queue a work item
193 /// </summary>
194 /// <param name="workItemInfo">Work item information</param>
195 /// <param name="callback">A callback to execute</param>
196 /// <param name="state">
197 /// The context object of the work item. Used for passing arguments to the work item.
198 /// </param>
199 /// <returns>Returns a work item result</returns>
200 public IWorkItemResult QueueWorkItem(WorkItemInfo workItemInfo, WorkItemCallback callback, object state)
201 {
202 WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, workItemInfo, callback, state);
203 EnqueueToSTPNextWorkItem(workItem);
204 return workItem.GetWorkItemResult();
205 }
206
207 /// <summary>
208 /// Queue a work item
209 /// </summary>
210 /// <param name="callback">A callback to execute</param>
211 /// <param name="state">
212 /// The context object of the work item. Used for passing arguments to the work item.
213 /// </param>
214 /// <param name="postExecuteWorkItemCallback">
215 /// A delegate to call after the callback completion
216 /// </param>
217 /// <returns>Returns a work item result</returns>
218 public IWorkItemResult QueueWorkItem(
219 WorkItemCallback callback,
220 object state,
221 PostExecuteWorkItemCallback postExecuteWorkItemCallback)
222 {
223 WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, callback, state, postExecuteWorkItemCallback);
224 EnqueueToSTPNextWorkItem(workItem);
225 return workItem.GetWorkItemResult();
226 }
227
228 /// <summary>
229 /// Queue a work item
230 /// </summary>
231 /// <param name="callback">A callback to execute</param>
232 /// <param name="state">
233 /// The context object of the work item. Used for passing arguments to the work item.
234 /// </param>
235 /// <param name="postExecuteWorkItemCallback">
236 /// A delegate to call after the callback completion
237 /// </param>
238 /// <param name="workItemPriority">The work item priority</param>
239 /// <returns>Returns a work item result</returns>
240 public IWorkItemResult QueueWorkItem(
241 WorkItemCallback callback,
242 object state,
243 PostExecuteWorkItemCallback postExecuteWorkItemCallback,
244 WorkItemPriority workItemPriority)
245 {
246 WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, callback, state, postExecuteWorkItemCallback, workItemPriority);
247 EnqueueToSTPNextWorkItem(workItem);
248 return workItem.GetWorkItemResult();
249 }
250
251 /// <summary>
252 /// Queue a work item
253 /// </summary>
254 /// <param name="callback">A callback to execute</param>
255 /// <param name="state">
256 /// The context object of the work item. Used for passing arguments to the work item.
257 /// </param>
258 /// <param name="postExecuteWorkItemCallback">
259 /// A delegate to call after the callback completion
260 /// </param>
261 /// <param name="callToPostExecute">Indicates on which cases to call to the post execute callback</param>
262 /// <returns>Returns a work item result</returns>
263 public IWorkItemResult QueueWorkItem(
264 WorkItemCallback callback,
265 object state,
266 PostExecuteWorkItemCallback postExecuteWorkItemCallback,
267 CallToPostExecute callToPostExecute)
268 {
269 WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, callback, state, postExecuteWorkItemCallback, callToPostExecute);
270 EnqueueToSTPNextWorkItem(workItem);
271 return workItem.GetWorkItemResult();
272 }
273
274 /// <summary>
275 /// Queue a work item
276 /// </summary>
277 /// <param name="callback">A callback to execute</param>
278 /// <param name="state">
279 /// The context object of the work item. Used for passing arguments to the work item.
280 /// </param>
281 /// <param name="postExecuteWorkItemCallback">
282 /// A delegate to call after the callback completion
283 /// </param>
284 /// <param name="callToPostExecute">Indicates on which cases to call to the post execute callback</param>
285 /// <param name="workItemPriority">The work item priority</param>
286 /// <returns>Returns a work item result</returns>
287 public IWorkItemResult QueueWorkItem(
288 WorkItemCallback callback,
289 object state,
290 PostExecuteWorkItemCallback postExecuteWorkItemCallback,
291 CallToPostExecute callToPostExecute,
292 WorkItemPriority workItemPriority)
293 {
294 WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, callback, state, postExecuteWorkItemCallback, callToPostExecute, workItemPriority);
295 EnqueueToSTPNextWorkItem(workItem);
296 return workItem.GetWorkItemResult();
297 }
298
299 /// <summary>
300 /// Wait for the thread pool to be idle
301 /// </summary>
302 public void WaitForIdle()
303 {
304 WaitForIdle(Timeout.Infinite);
305 }
306
307 /// <summary>
308 /// Wait for the thread pool to be idle
309 /// </summary>
310 public bool WaitForIdle(TimeSpan timeout)
311 {
312 return WaitForIdle((int)timeout.TotalMilliseconds);
313 }
314
315 /// <summary>
316 /// Wait for the thread pool to be idle
317 /// </summary>
318 public bool WaitForIdle(int millisecondsTimeout)
319 {
320 _stp.ValidateWorkItemsGroupWaitForIdle(this);
321 return _isIdleWaitHandle.WaitOne(millisecondsTimeout, false);
322 }
323
324 public int WaitingCallbacks
325 {
326 get
327 {
328 return _workItemsQueue.Count;
329 }
330 }
331
332 public event WorkItemsGroupIdleHandler OnIdle
333 {
334 add
335 {
336 _onIdle += value;
337 }
338 remove
339 {
340 _onIdle -= value;
341 }
342 }
343
344 public void Cancel()
345 {
346 lock(_lock)
347 {
348 _canceledWorkItemsGroup.IsCanceled = true;
349 _workItemsQueue.Clear();
350 _workItemsInStpQueue = 0;
351 _canceledWorkItemsGroup = new CanceledWorkItemsGroup();
352 }
353 }
354
355 public void Start()
356 {
357 lock (this)
358 {
359 if (!_workItemsGroupStartInfo.StartSuspended)
360 {
361 return;
362 }
363 _workItemsGroupStartInfo.StartSuspended = false;
364 }
365
366 for(int i = 0; i < _concurrency; ++i)
367 {
368 EnqueueToSTPNextWorkItem(null, false);
369 }
370 }
371
372 #endregion
373
374 #region Private methods
375
376 private void RegisterToWorkItemCompletion(IWorkItemResult wir)
377 {
378 IInternalWorkItemResult iwir = wir as IInternalWorkItemResult;
379 iwir.OnWorkItemStarted += new WorkItemStateCallback(OnWorkItemStartedCallback);
380 iwir.OnWorkItemCompleted += new WorkItemStateCallback(OnWorkItemCompletedCallback);
381 }
382
383 public void OnSTPIsStarting()
384 {
385 lock (this)
386 {
387 if (_workItemsGroupStartInfo.StartSuspended)
388 {
389 return;
390 }
391 }
392
393 for(int i = 0; i < _concurrency; ++i)
394 {
395 EnqueueToSTPNextWorkItem(null, false);
396 }
397 }
398
399 private object FireOnIdle(object state)
400 {
401 FireOnIdleImpl(_onIdle);
402 return null;
403 }
404
405 [MethodImpl(MethodImplOptions.NoInlining)]
406 private void FireOnIdleImpl(WorkItemsGroupIdleHandler onIdle)
407 {
408 if(null == onIdle)
409 {
410 return;
411 }
412
413 Delegate[] delegates = onIdle.GetInvocationList();
414 foreach(WorkItemsGroupIdleHandler eh in delegates)
415 {
416 try
417 {
418 eh(this);
419 }
420 // Ignore exceptions
421 catch{}
422 }
423 }
424
425 private void OnWorkItemStartedCallback(WorkItem workItem)
426 {
427 lock(_lock)
428 {
429 ++_workItemsExecutingInStp;
430 }
431 }
432
433 private void OnWorkItemCompletedCallback(WorkItem workItem)
434 {
435 EnqueueToSTPNextWorkItem(null, true);
436 }
437
438 private void EnqueueToSTPNextWorkItem(WorkItem workItem)
439 {
440 EnqueueToSTPNextWorkItem(workItem, false);
441 }
442
443 private void EnqueueToSTPNextWorkItem(WorkItem workItem, bool decrementWorkItemsInStpQueue)
444 {
445 lock(_lock)
446 {
447 // Got here from OnWorkItemCompletedCallback()
448 if (decrementWorkItemsInStpQueue)
449 {
450 --_workItemsInStpQueue;
451
452 if(_workItemsInStpQueue < 0)
453 {
454 _workItemsInStpQueue = 0;
455 }
456
457 --_workItemsExecutingInStp;
458
459 if(_workItemsExecutingInStp < 0)
460 {
461 _workItemsExecutingInStp = 0;
462 }
463 }
464
465 // If the work item is not null then enqueue it
466 if (null != workItem)
467 {
468 workItem.CanceledWorkItemsGroup = _canceledWorkItemsGroup;
469
470 RegisterToWorkItemCompletion(workItem.GetWorkItemResult());
471 _workItemsQueue.Enqueue(workItem);
472 //_stp.IncrementWorkItemsCount();
473
474 if ((1 == _workItemsQueue.Count) &&
475 (0 == _workItemsInStpQueue))
476 {
477 _stp.RegisterWorkItemsGroup(this);
478 Trace.WriteLine("WorkItemsGroup " + Name + " is NOT idle");
479 _isIdleWaitHandle.Reset();
480 }
481 }
482
483 // If the work items queue of the group is empty than quit
484 if (0 == _workItemsQueue.Count)
485 {
486 if (0 == _workItemsInStpQueue)
487 {
488 _stp.UnregisterWorkItemsGroup(this);
489 Trace.WriteLine("WorkItemsGroup " + Name + " is idle");
490 _isIdleWaitHandle.Set();
491 _stp.QueueWorkItem(new WorkItemCallback(this.FireOnIdle));
492 }
493 return;
494 }
495
496 if (!_workItemsGroupStartInfo.StartSuspended)
497 {
498 if (_workItemsInStpQueue < _concurrency)
499 {
500 WorkItem nextWorkItem = _workItemsQueue.Dequeue() as WorkItem;
501 _stp.Enqueue(nextWorkItem, true);
502 ++_workItemsInStpQueue;
503 }
504 }
505 }
506 }
507
508 #endregion
509 }
510
511 #endregion
512}
diff --git a/ThirdParty/SmartThreadPool/WorkItemsQueue.cs b/ThirdParty/SmartThreadPool/WorkItemsQueue.cs
new file mode 100644
index 0000000..af5af07
--- /dev/null
+++ b/ThirdParty/SmartThreadPool/WorkItemsQueue.cs
@@ -0,0 +1,600 @@
1// Ami Bar
2// amibar@gmail.com
3
4using System;
5using System.Threading;
6
7namespace Amib.Threading.Internal
8{
9 #region WorkItemsQueue class
10
11 /// <summary>
12 /// WorkItemsQueue class.
13 /// </summary>
14 public class WorkItemsQueue : IDisposable
15 {
16 #region Member variables
17
18 /// <summary>
19 /// Waiters queue (implemented as stack).
20 /// </summary>
21 private WaiterEntry _headWaiterEntry = new WaiterEntry();
22
23 /// <summary>
24 /// Waiters count
25 /// </summary>
26 private int _waitersCount = 0;
27
28 /// <summary>
29 /// Work items queue
30 /// </summary>
31 private PriorityQueue _workItems = new PriorityQueue();
32
33 /// <summary>
34 /// Indicate that work items are allowed to be queued
35 /// </summary>
36 private bool _isWorkItemsQueueActive = true;
37
38 /// <summary>
39 /// Each thread in the thread pool keeps its own waiter entry.
40 /// </summary>
41 [ThreadStatic]
42 private static WaiterEntry _waiterEntry;
43
44 /// <summary>
45 /// A flag that indicates if the WorkItemsQueue has been disposed.
46 /// </summary>
47 private bool _isDisposed = false;
48
49 #endregion
50
51 #region Public properties
52
53 /// <summary>
54 /// Returns the current number of work items in the queue
55 /// </summary>
56 public int Count
57 {
58 get
59 {
60 lock(this)
61 {
62 ValidateNotDisposed();
63 return _workItems.Count;
64 }
65 }
66 }
67
68 /// <summary>
69 /// Returns the current number of waiters
70 /// </summary>
71 public int WaitersCount
72 {
73 get
74 {
75 lock(this)
76 {
77 ValidateNotDisposed();
78 return _waitersCount;
79 }
80 }
81 }
82
83
84 #endregion
85
86 #region Public methods
87
88 /// <summary>
89 /// Enqueue a work item to the queue.
90 /// </summary>
91 public bool EnqueueWorkItem(WorkItem workItem)
92 {
93 // A work item cannot be null, since null is used in the
94 // WaitForWorkItem() method to indicate timeout or cancel
95 if (null == workItem)
96 {
97 throw new ArgumentNullException("workItem" , "workItem cannot be null");
98 }
99
100 bool enqueue = true;
101
102 // First check if there is a waiter waiting for work item. During
103 // the check, timed out waiters are ignored. If there is no
104 // waiter then the work item is queued.
105 lock(this)
106 {
107 ValidateNotDisposed();
108
109 if (!_isWorkItemsQueueActive)
110 {
111 return false;
112 }
113
114 while(_waitersCount > 0)
115 {
116 // Dequeue a waiter.
117 WaiterEntry waiterEntry = PopWaiter();
118
119 // Signal the waiter. On success break the loop
120 if (waiterEntry.Signal(workItem))
121 {
122 enqueue = false;
123 break;
124 }
125 }
126
127 if (enqueue)
128 {
129 // Enqueue the work item
130 _workItems.Enqueue(workItem);
131 }
132 }
133 return true;
134 }
135
136
137 /// <summary>
138 /// Waits for a work item or exits on timeout or cancel
139 /// </summary>
140 /// <param name="millisecondsTimeout">Timeout in milliseconds</param>
141 /// <param name="cancelEvent">Cancel wait handle</param>
142 /// <returns>Returns true if the resource was granted</returns>
143 public WorkItem DequeueWorkItem(
144 int millisecondsTimeout,
145 WaitHandle cancelEvent)
146 {
147 /// This method cause the caller to wait for a work item.
148 /// If there is at least one waiting work item then the
149 /// method returns immidiately with true.
150 ///
151 /// If there are no waiting work items then the caller
152 /// is queued between other waiters for a work item to arrive.
153 ///
154 /// If a work item didn't come within millisecondsTimeout or
155 /// the user canceled the wait by signaling the cancelEvent
156 /// then the method returns false to indicate that the caller
157 /// didn't get a work item.
158
159 WaiterEntry waiterEntry = null;
160 WorkItem workItem = null;
161
162 lock(this)
163 {
164 ValidateNotDisposed();
165
166 // If there are waiting work items then take one and return.
167 if (_workItems.Count > 0)
168 {
169 workItem = _workItems.Dequeue() as WorkItem;
170 return workItem;
171 }
172 // No waiting work items ...
173 else
174 {
175 // Get the wait entry for the waiters queue
176 waiterEntry = GetThreadWaiterEntry();
177
178 // Put the waiter with the other waiters
179 PushWaiter(waiterEntry);
180 }
181 }
182
183 // Prepare array of wait handle for the WaitHandle.WaitAny()
184 WaitHandle [] waitHandles = new WaitHandle [] {
185 waiterEntry.WaitHandle,
186 cancelEvent };
187
188 // Wait for an available resource, cancel event, or timeout.
189
190 // During the wait we are supposes to exit the synchronization
191 // domain. (Placing true as the third argument of the WaitAny())
192 // It just doesn't work, I don't know why, so I have lock(this)
193 // statments insted of one.
194
195 int index = WaitHandle.WaitAny(
196 waitHandles,
197 millisecondsTimeout,
198 true);
199
200 lock(this)
201 {
202 // success is true if it got a work item.
203 bool success = (0 == index);
204
205 // The timeout variable is used only for readability.
206 // (We treat cancel as timeout)
207 bool timeout = !success;
208
209 // On timeout update the waiterEntry that it is timed out
210 if (timeout)
211 {
212 // The Timeout() fails if the waiter has already been signaled
213 timeout = waiterEntry.Timeout();
214
215 // On timeout remove the waiter from the queue.
216 // Note that the complexity is O(1).
217 if(timeout)
218 {
219 RemoveWaiter(waiterEntry, false);
220 }
221
222 // Again readability
223 success = !timeout;
224 }
225
226 // On success return the work item
227 if (success)
228 {
229 workItem = waiterEntry.WorkItem;
230
231 if (null == workItem)
232 {
233 workItem = _workItems.Dequeue() as WorkItem;
234 }
235 }
236 }
237 // On failure return null.
238 return workItem;
239 }
240
241 /// <summary>
242 /// Cleanup the work items queue, hence no more work
243 /// items are allowed to be queue
244 /// </summary>
245 protected virtual void Cleanup()
246 {
247 lock(this)
248 {
249 // Deactivate only once
250 if (!_isWorkItemsQueueActive)
251 {
252 return;
253 }
254
255 // Don't queue more work items
256 _isWorkItemsQueueActive = false;
257
258 foreach(WorkItem workItem in _workItems)
259 {
260 workItem.DisposeOfState();
261 }
262
263 // Clear the work items that are already queued
264 _workItems.Clear();
265
266 // Note:
267 // I don't iterate over the queue and dispose of work items's states,
268 // since if a work item has a state object that is still in use in the
269 // application then I must not dispose it.
270
271 // Tell the waiters that they were timed out.
272 // It won't signal them to exit, but to ignore their
273 // next work item.
274 while(_waitersCount > 0)
275 {
276 WaiterEntry waiterEntry = PopWaiter();
277 waiterEntry.Timeout();
278 }
279 }
280 }
281
282 #endregion
283
284 #region Private methods
285
286 /// <summary>
287 /// Returns the WaiterEntry of the current thread
288 /// </summary>
289 /// <returns></returns>
290 /// In order to avoid creation and destuction of WaiterEntry
291 /// objects each thread has its own WaiterEntry object.
292 private WaiterEntry GetThreadWaiterEntry()
293 {
294 if (null == _waiterEntry)
295 {
296 _waiterEntry = new WaiterEntry();
297 }
298 _waiterEntry.Reset();
299 return _waiterEntry;
300 }
301
302 #region Waiters stack methods
303
304 /// <summary>
305 /// Push a new waiter into the waiter's stack
306 /// </summary>
307 /// <param name="newWaiterEntry">A waiter to put in the stack</param>
308 public void PushWaiter(WaiterEntry newWaiterEntry)
309 {
310 // Remove the waiter if it is already in the stack and
311 // update waiter's count as needed
312 RemoveWaiter(newWaiterEntry, false);
313
314 // If the stack is empty then newWaiterEntry is the new head of the stack
315 if (null == _headWaiterEntry._nextWaiterEntry)
316 {
317 _headWaiterEntry._nextWaiterEntry = newWaiterEntry;
318 newWaiterEntry._prevWaiterEntry = _headWaiterEntry;
319
320 }
321 // If the stack is not empty then put newWaiterEntry as the new head
322 // of the stack.
323 else
324 {
325 // Save the old first waiter entry
326 WaiterEntry oldFirstWaiterEntry = _headWaiterEntry._nextWaiterEntry;
327
328 // Update the links
329 _headWaiterEntry._nextWaiterEntry = newWaiterEntry;
330 newWaiterEntry._nextWaiterEntry = oldFirstWaiterEntry;
331 newWaiterEntry._prevWaiterEntry = _headWaiterEntry;
332 oldFirstWaiterEntry._prevWaiterEntry = newWaiterEntry;
333 }
334
335 // Increment the number of waiters
336 ++_waitersCount;
337 }
338
339 /// <summary>
340 /// Pop a waiter from the waiter's stack
341 /// </summary>
342 /// <returns>Returns the first waiter in the stack</returns>
343 private WaiterEntry PopWaiter()
344 {
345 // Store the current stack head
346 WaiterEntry oldFirstWaiterEntry = _headWaiterEntry._nextWaiterEntry;
347
348 // Store the new stack head
349 WaiterEntry newHeadWaiterEntry = oldFirstWaiterEntry._nextWaiterEntry;
350
351 // Update the old stack head list links and decrement the number
352 // waiters.
353 RemoveWaiter(oldFirstWaiterEntry, true);
354
355 // Update the new stack head
356 _headWaiterEntry._nextWaiterEntry = newHeadWaiterEntry;
357 if (null != newHeadWaiterEntry)
358 {
359 newHeadWaiterEntry._prevWaiterEntry = _headWaiterEntry;
360 }
361
362 // Return the old stack head
363 return oldFirstWaiterEntry;
364 }
365
366 /// <summary>
367 /// Remove a waiter from the stack
368 /// </summary>
369 /// <param name="waiterEntry">A waiter entry to remove</param>
370 /// <param name="popDecrement">If true the waiter count is always decremented</param>
371 private void RemoveWaiter(WaiterEntry waiterEntry, bool popDecrement)
372 {
373 // Store the prev entry in the list
374 WaiterEntry prevWaiterEntry = waiterEntry._prevWaiterEntry;
375
376 // Store the next entry in the list
377 WaiterEntry nextWaiterEntry = waiterEntry._nextWaiterEntry;
378
379 // A flag to indicate if we need to decrement the waiters count.
380 // If we got here from PopWaiter then we must decrement.
381 // If we got here from PushWaiter then we decrement only if
382 // the waiter was already in the stack.
383 bool decrementCounter = popDecrement;
384
385 // Null the waiter's entry links
386 waiterEntry._prevWaiterEntry = null;
387 waiterEntry._nextWaiterEntry = null;
388
389 // If the waiter entry had a prev link then update it.
390 // It also means that the waiter is already in the list and we
391 // need to decrement the waiters count.
392 if (null != prevWaiterEntry)
393 {
394 prevWaiterEntry._nextWaiterEntry = nextWaiterEntry;
395 decrementCounter = true;
396 }
397
398 // If the waiter entry had a next link then update it.
399 // It also means that the waiter is already in the list and we
400 // need to decrement the waiters count.
401 if (null != nextWaiterEntry)
402 {
403 nextWaiterEntry._prevWaiterEntry = prevWaiterEntry;
404 decrementCounter = true;
405 }
406
407 // Decrement the waiters count if needed
408 if (decrementCounter)
409 {
410 --_waitersCount;
411 }
412 }
413
414 #endregion
415
416 #endregion
417
418 #region WaiterEntry class
419
420 // A waiter entry in the _waiters queue.
421 public class WaiterEntry : IDisposable
422 {
423 #region Member variables
424
425 /// <summary>
426 /// Event to signal the waiter that it got the work item.
427 /// </summary>
428 private AutoResetEvent _waitHandle = new AutoResetEvent(false);
429
430 /// <summary>
431 /// Flag to know if this waiter already quited from the queue
432 /// because of a timeout.
433 /// </summary>
434 private bool _isTimedout = false;
435
436 /// <summary>
437 /// Flag to know if the waiter was signaled and got a work item.
438 /// </summary>
439 private bool _isSignaled = false;
440
441 /// <summary>
442 /// A work item that passed directly to the waiter withou going
443 /// through the queue
444 /// </summary>
445 private WorkItem _workItem = null;
446
447 private bool _isDisposed = false;
448
449 // Linked list members
450 internal WaiterEntry _nextWaiterEntry = null;
451 internal WaiterEntry _prevWaiterEntry = null;
452
453 #endregion
454
455 #region Construction
456
457 public WaiterEntry()
458 {
459 Reset();
460 }
461
462 #endregion
463
464 #region Public methods
465
466 public WaitHandle WaitHandle
467 {
468 get { return _waitHandle; }
469 }
470
471 public WorkItem WorkItem
472 {
473 get
474 {
475 lock(this)
476 {
477 return _workItem;
478 }
479 }
480 }
481
482 /// <summary>
483 /// Signal the waiter that it got a work item.
484 /// </summary>
485 /// <returns>Return true on success</returns>
486 /// The method fails if Timeout() preceded its call
487 public bool Signal(WorkItem workItem)
488 {
489 lock(this)
490 {
491 if (!_isTimedout)
492 {
493 _workItem = workItem;
494 _isSignaled = true;
495 _waitHandle.Set();
496 return true;
497 }
498 }
499 return false;
500 }
501
502 /// <summary>
503 /// Mark the wait entry that it has been timed out
504 /// </summary>
505 /// <returns>Return true on success</returns>
506 /// The method fails if Signal() preceded its call
507 public bool Timeout()
508 {
509 lock(this)
510 {
511 // Time out can happen only if the waiter wasn't marked as
512 // signaled
513 if (!_isSignaled)
514 {
515 // We don't remove the waiter from the queue, the DequeueWorkItem
516 // method skips _waiters that were timed out.
517 _isTimedout = true;
518 return true;
519 }
520 }
521 return false;
522 }
523
524 /// <summary>
525 /// Reset the wait entry so it can be used again
526 /// </summary>
527 public void Reset()
528 {
529 _workItem = null;
530 _isTimedout = false;
531 _isSignaled = false;
532 _waitHandle.Reset();
533 }
534
535 /// <summary>
536 /// Free resources
537 /// </summary>
538 public void Close()
539 {
540 if (null != _waitHandle)
541 {
542 _waitHandle.Close();
543 _waitHandle = null;
544 }
545 }
546
547 #endregion
548
549 #region IDisposable Members
550
551 public void Dispose()
552 {
553 if (!_isDisposed)
554 {
555 Close();
556 _isDisposed = true;
557 }
558 }
559
560 ~WaiterEntry()
561 {
562 Dispose();
563 }
564
565 #endregion
566 }
567
568 #endregion
569
570 #region IDisposable Members
571
572 public void Dispose()
573 {
574 if (!_isDisposed)
575 {
576 Cleanup();
577 _isDisposed = true;
578 GC.SuppressFinalize(this);
579 }
580 }
581
582 ~WorkItemsQueue()
583 {
584 Cleanup();
585 }
586
587 private void ValidateNotDisposed()
588 {
589 if(_isDisposed)
590 {
591 throw new ObjectDisposedException(GetType().ToString(), "The SmartThreadPool has been shutdown");
592 }
593 }
594
595 #endregion
596 }
597
598 #endregion
599}
600
diff --git a/ThirdPartyLicenses/SmartThreadPool.txt b/ThirdPartyLicenses/SmartThreadPool.txt
new file mode 100644
index 0000000..7bfc997
--- /dev/null
+++ b/ThirdPartyLicenses/SmartThreadPool.txt
@@ -0,0 +1,22 @@
1Microsoft Public License (Ms-PL)
2
3This license governs use of the accompanying software. If you use the software, you
4accept this license. If you do not accept the license, do not use the software.
5
61. Definitions
7The terms "reproduce," "reproduction," "derivative works," and "distribution" have the
8same meaning here as under U.S. copyright law.
9A "contribution" is the original software, or any additions or changes to the software.
10A "contributor" is any person that distributes its contribution under this license.
11"Licensed patents" are a contributor's patent claims that read directly on its contribution.
12
132. Grant of Rights
14(A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create.
15(B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software.
16
173. Conditions and Limitations
18(A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks.
19(B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically.
20(C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software.
21(D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license.
22(E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement.
diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example
index 817441d..d88018a 100644
--- a/bin/OpenSim.ini.example
+++ b/bin/OpenSim.ini.example
@@ -535,3 +535,40 @@ Password = "password"
535ImportOnStartup = false 535ImportOnStartup = false
536Autosave = false 536Autosave = false
537AutoSavePeriod = 15 ; Number of minutes between autosave backups 537AutoSavePeriod = 15 ; Number of minutes between autosave backups
538
539
540[XEngine]
541; How many threads to keep alive even if nothing is happening
542MinThreads = 2
543; How many threads to start at maximum load
544MaxThreads = 100
545; Time a thread must be idle (in seconds) before it dies
546IdleTimeout = 60
547; Thread priority ("Lowest", "BelowNormal", "Normal", "AboveNormal", "Highest")
548Priority = "BelowNormal"
549; Maximum number of events to queue for a script (excluding timers)
550MaxScriptEventQueue = 300
551; Stack size per thread created
552ThreadStackSize = 262144
553; Rate to poll for asynchronous command replies (ms)
554AsyncLLCommandLoopms = 50
555; Save the source of all compiled scripts
556WriteScriptSourceToDebugFile = false
557; Default language for scripts
558DefaultCompileLanguage = lsl
559; List of allowed languages (lsl,vb,js,cs)
560AllowedCompilers = lsl
561; Compile debug info (line numbers) into the script assemblies
562CompileWithDebugInformation = true
563; Allow the use of os* functions (some are dangerous)
564AllowOSFunctions = false
565; Interval (s) between background save of script states
566SaveInterval = 120
567; Interval (s) between maintenance runs (0 = disable)
568MaintenanceInterval = 10
569; Time a script can spend in an event handler before it is interrupted
570EventLimit = 30
571; If a script overruns it's event limit, kill the script?
572KillTimedOutScripts = false
573; Allow OS console command functionality (VERY DANGEROUS!!)
574AllowosConsoleCommand = false \ No newline at end of file
diff --git a/prebuild.xml b/prebuild.xml
index 2122d9e..2320a94 100644
--- a/prebuild.xml
+++ b/prebuild.xml
@@ -1345,6 +1345,63 @@
1345 </Files> 1345 </Files>
1346 </Project> 1346 </Project>
1347 1347
1348 <Project name="OpenSim.Region.ScriptEngine.XEngine.Script" path="OpenSim/Region/ScriptEngine/XEngine/Script" type="Library">
1349 <Configuration name="Debug">
1350 <Options>
1351 <OutputPath>../../../../../bin/</OutputPath>
1352 </Options>
1353 </Configuration>
1354 <Configuration name="Release">
1355 <Options>
1356 <OutputPath>../../../../../bin/</OutputPath>
1357 </Options>
1358 </Configuration>
1359
1360 <ReferencePath>../../../../../bin/</ReferencePath>
1361 <Reference name="System" localCopy="false"/>
1362 <Reference name="System.Data" localCopy="false"/>
1363 <Reference name="System.Web" localCopy="false"/>
1364 <Reference name="System.Xml" localCopy="false"/>
1365 <Reference name="libsecondlife.dll"/>
1366 <Reference name="OpenSim" />
1367 <Reference name="OpenSim.Framework"/>
1368 <Reference name="OpenSim.Framework.Communications"/>
1369 <Reference name="OpenSim.Region.Environment" />
1370 <Reference name="OpenSim.Framework.Console"/>
1371 <Reference name="Axiom.MathLib.dll" localCopy="false"/>
1372 <Reference name="Nini.dll" />
1373 <Reference name="RAIL.dll"/>
1374 <Reference name="Nini.dll" />
1375 <Reference name="log4net"/>
1376
1377 <Files>
1378 <Match pattern="*.cs" recurse="true"/>
1379 </Files>
1380 </Project>
1381
1382 <Project name="SmartThreadPool" path="ThirdParty/SmartThreadPool" type="Library">
1383 <Configuration name="Debug">
1384 <Options>
1385 <OutputPath>../../bin/</OutputPath>
1386 </Options>
1387 </Configuration>
1388 <Configuration name="Release">
1389 <Options>
1390 <OutputPath>../../bin/</OutputPath>
1391 </Options>
1392 </Configuration>
1393
1394 <ReferencePath>../../bin/</ReferencePath>
1395 <Reference name="System" localCopy="false"/>
1396 <Reference name="System.Xml"/>
1397 <Reference name="System.Data"/>
1398 <Reference name="System.Web"/>
1399 <Files>
1400 <Match pattern="*.cs" recurse="false"/>
1401 </Files>
1402 </Project>
1403
1404
1348 1405
1349 <!-- OGS projects --> 1406 <!-- OGS projects -->
1350 1407
@@ -1571,6 +1628,43 @@
1571 </Files> 1628 </Files>
1572 </Project> 1629 </Project>
1573 1630
1631 <Project name="OpenSim.Region.ScriptEngine.XEngine" path="OpenSim/Region/ScriptEngine/XEngine" type="Library">
1632 <Configuration name="Debug">
1633 <Options>
1634 <OutputPath>../../../../bin/ScriptEngines/</OutputPath>
1635 </Options>
1636 </Configuration>
1637 <Configuration name="Release">
1638 <Options>
1639 <OutputPath>../../../../bin/ScriptEngines/</OutputPath>
1640 </Options>
1641 </Configuration>
1642
1643 <ReferencePath>../../../../bin/</ReferencePath>
1644 <Reference name="System" localCopy="false"/>
1645 <Reference name="System.Data" localCopy="false"/>
1646 <Reference name="System.Xml" localCopy="false"/>
1647 <Reference name="System.Runtime.Remoting" localCopy="false"/>
1648 <Reference name="libsecondlife.dll"/>
1649 <Reference name="RAIL.dll"/>
1650 <Reference name="OpenSim.Framework"/>
1651 <Reference name="OpenSim.Framework.Console"/>
1652 <Reference name="OpenSim.Framework.Communications"/>
1653 <Reference name="OpenSim.Region.Environment" />
1654 <Reference name="OpenSim.Region.ScriptEngine.XEngine.Script" />
1655 <Reference name="Microsoft.JScript"/>
1656 <Reference name="Axiom.MathLib.dll" localCopy="false"/>
1657 <Reference name="Nini.dll" />
1658 <Reference name="SmartThreadPool" />
1659 <Reference name="log4net"/>
1660
1661 <Files>
1662 <Match path="AsyncCommandPlugins" pattern="*.cs" recurse="false"/>
1663 <Match pattern="*.cs" recurse="false"/>
1664 </Files>
1665 </Project>
1666
1667
1574 1668
1575 <Project name="OpenSim.Grid.ScriptServer" path="OpenSim/Grid/ScriptServer" type="Exe"> 1669 <Project name="OpenSim.Grid.ScriptServer" path="OpenSim/Grid/ScriptServer" type="Exe">
1576 <Configuration name="Debug"> 1670 <Configuration name="Debug">