clockwerk-opensim – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | vero | 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 OpenSimulator Project nor the |
||
13 | * names of its contributors may be used to endorse or promote products |
||
14 | * derived from this software without specific prior written permission. |
||
15 | * |
||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY |
||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY |
||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||
26 | */ |
||
27 | |||
28 | using System; |
||
29 | using System.Reflection; |
||
30 | using System.Collections; |
||
31 | using System.Collections.Generic; |
||
32 | using System.Runtime.Remoting.Lifetime; |
||
33 | using System.Threading; |
||
34 | using log4net; |
||
35 | using OpenMetaverse; |
||
36 | using Nini.Config; |
||
37 | using OpenSim; |
||
38 | using OpenSim.Framework; |
||
39 | using OpenSim.Region.Framework.Interfaces; |
||
40 | using OpenSim.Region.Framework.Scenes; |
||
41 | using OpenSim.Region.ScriptEngine.Shared; |
||
42 | using OpenSim.Region.ScriptEngine.Shared.Api.Plugins; |
||
43 | using OpenSim.Region.ScriptEngine.Shared.ScriptBase; |
||
44 | using OpenSim.Region.ScriptEngine.Interfaces; |
||
45 | using OpenSim.Region.ScriptEngine.Shared.Api.Interfaces; |
||
46 | |||
47 | using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; |
||
48 | using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; |
||
49 | using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; |
||
50 | using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list; |
||
51 | using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion; |
||
52 | using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; |
||
53 | using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3; |
||
54 | |||
55 | namespace OpenSim.Region.ScriptEngine.Shared.Api |
||
56 | { |
||
57 | [Serializable] |
||
58 | public class MOD_Api : MarshalByRefObject, IMOD_Api, IScriptApi |
||
59 | { |
||
60 | // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
||
61 | |||
62 | internal IScriptEngine m_ScriptEngine; |
||
63 | internal SceneObjectPart m_host; |
||
64 | internal TaskInventoryItem m_item; |
||
65 | internal bool m_MODFunctionsEnabled = false; |
||
66 | internal IScriptModuleComms m_comms = null; |
||
67 | |||
68 | public void Initialize( |
||
69 | IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, WaitHandle coopSleepHandle) |
||
70 | { |
||
71 | m_ScriptEngine = scriptEngine; |
||
72 | m_host = host; |
||
73 | m_item = item; |
||
74 | |||
75 | if (m_ScriptEngine.Config.GetBoolean("AllowMODFunctions", false)) |
||
76 | m_MODFunctionsEnabled = true; |
||
77 | |||
78 | m_comms = m_ScriptEngine.World.RequestModuleInterface<IScriptModuleComms>(); |
||
79 | if (m_comms == null) |
||
80 | m_MODFunctionsEnabled = false; |
||
81 | } |
||
82 | |||
83 | public override Object InitializeLifetimeService() |
||
84 | { |
||
85 | ILease lease = (ILease)base.InitializeLifetimeService(); |
||
86 | |||
87 | if (lease.CurrentState == LeaseState.Initial) |
||
88 | { |
||
89 | lease.InitialLeaseTime = TimeSpan.FromMinutes(0); |
||
90 | // lease.RenewOnCallTime = TimeSpan.FromSeconds(10.0); |
||
91 | // lease.SponsorshipTimeout = TimeSpan.FromMinutes(1.0); |
||
92 | } |
||
93 | return lease; |
||
94 | } |
||
95 | |||
96 | public Scene World |
||
97 | { |
||
98 | get { return m_ScriptEngine.World; } |
||
99 | } |
||
100 | |||
101 | internal void MODError(string msg) |
||
102 | { |
||
103 | throw new ScriptException("MOD Runtime Error: " + msg); |
||
104 | } |
||
105 | |||
106 | /// <summary> |
||
107 | /// Dumps an error message on the debug console. |
||
108 | /// </summary> |
||
109 | /// <param name='message'></param> |
||
110 | internal void MODShoutError(string message) |
||
111 | { |
||
112 | if (message.Length > 1023) |
||
113 | message = message.Substring(0, 1023); |
||
114 | |||
115 | World.SimChat( |
||
116 | Utils.StringToBytes(message), |
||
117 | ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, |
||
118 | m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, false); |
||
119 | |||
120 | IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); |
||
121 | wComm.DeliverMessage(ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.Name, m_host.UUID, message); |
||
122 | } |
||
123 | |||
124 | /// <summary> |
||
125 | /// |
||
126 | /// </summary> |
||
127 | /// <param name="fname">The name of the function to invoke</param> |
||
128 | /// <param name="parms">List of parameters</param> |
||
129 | /// <returns>string result of the invocation</returns> |
||
130 | public void modInvokeN(string fname, params object[] parms) |
||
131 | { |
||
132 | // m_log.DebugFormat( |
||
133 | // "[MOD API]: Invoking dynamic function {0}, args '{1}' with {2} return type", |
||
134 | // fname, |
||
135 | // string.Join(",", Array.ConvertAll<object, string>(parms, o => o.ToString())), |
||
136 | // ((MethodInfo)MethodBase.GetCurrentMethod()).ReturnType); |
||
137 | |||
138 | Type returntype = m_comms.LookupReturnType(fname); |
||
139 | if (returntype != typeof(string)) |
||
140 | MODError(String.Format("return type mismatch for {0}",fname)); |
||
141 | |||
142 | modInvoke(fname,parms); |
||
143 | } |
||
144 | |||
145 | public LSL_String modInvokeS(string fname, params object[] parms) |
||
146 | { |
||
147 | // m_log.DebugFormat( |
||
148 | // "[MOD API]: Invoking dynamic function {0}, args '{1}' with {2} return type", |
||
149 | // fname, |
||
150 | // string.Join(",", Array.ConvertAll<object, string>(parms, o => o.ToString())), |
||
151 | // ((MethodInfo)MethodBase.GetCurrentMethod()).ReturnType); |
||
152 | |||
153 | Type returntype = m_comms.LookupReturnType(fname); |
||
154 | if (returntype != typeof(string)) |
||
155 | MODError(String.Format("return type mismatch for {0}",fname)); |
||
156 | |||
157 | string result = (string)modInvoke(fname,parms); |
||
158 | return new LSL_String(result); |
||
159 | } |
||
160 | |||
161 | public LSL_Integer modInvokeI(string fname, params object[] parms) |
||
162 | { |
||
163 | // m_log.DebugFormat( |
||
164 | // "[MOD API]: Invoking dynamic function {0}, args '{1}' with {2} return type", |
||
165 | // fname, |
||
166 | // string.Join(",", Array.ConvertAll<object, string>(parms, o => o.ToString())), |
||
167 | // ((MethodInfo)MethodBase.GetCurrentMethod()).ReturnType); |
||
168 | |||
169 | Type returntype = m_comms.LookupReturnType(fname); |
||
170 | if (returntype != typeof(int)) |
||
171 | MODError(String.Format("return type mismatch for {0}",fname)); |
||
172 | |||
173 | int result = (int)modInvoke(fname,parms); |
||
174 | return new LSL_Integer(result); |
||
175 | } |
||
176 | |||
177 | public LSL_Float modInvokeF(string fname, params object[] parms) |
||
178 | { |
||
179 | // m_log.DebugFormat( |
||
180 | // "[MOD API]: Invoking dynamic function {0}, args '{1}' with {2} return type", |
||
181 | // fname, |
||
182 | // string.Join(",", Array.ConvertAll<object, string>(parms, o => o.ToString())), |
||
183 | // ((MethodInfo)MethodBase.GetCurrentMethod()).ReturnType); |
||
184 | |||
185 | Type returntype = m_comms.LookupReturnType(fname); |
||
186 | if (returntype != typeof(float)) |
||
187 | MODError(String.Format("return type mismatch for {0}",fname)); |
||
188 | |||
189 | float result = (float)modInvoke(fname,parms); |
||
190 | return new LSL_Float(result); |
||
191 | } |
||
192 | |||
193 | public LSL_Key modInvokeK(string fname, params object[] parms) |
||
194 | { |
||
195 | // m_log.DebugFormat( |
||
196 | // "[MOD API]: Invoking dynamic function {0}, args '{1}' with {2} return type", |
||
197 | // fname, |
||
198 | // string.Join(",", Array.ConvertAll<object, string>(parms, o => o.ToString())), |
||
199 | // ((MethodInfo)MethodBase.GetCurrentMethod()).ReturnType); |
||
200 | |||
201 | Type returntype = m_comms.LookupReturnType(fname); |
||
202 | if (returntype != typeof(UUID)) |
||
203 | MODError(String.Format("return type mismatch for {0}",fname)); |
||
204 | |||
205 | UUID result = (UUID)modInvoke(fname,parms); |
||
206 | return new LSL_Key(result.ToString()); |
||
207 | } |
||
208 | |||
209 | public LSL_Vector modInvokeV(string fname, params object[] parms) |
||
210 | { |
||
211 | // m_log.DebugFormat( |
||
212 | // "[MOD API]: Invoking dynamic function {0}, args '{1}' with {2} return type", |
||
213 | // fname, |
||
214 | // string.Join(",", Array.ConvertAll<object, string>(parms, o => o.ToString())), |
||
215 | // ((MethodInfo)MethodBase.GetCurrentMethod()).ReturnType); |
||
216 | |||
217 | Type returntype = m_comms.LookupReturnType(fname); |
||
218 | if (returntype != typeof(OpenMetaverse.Vector3)) |
||
219 | MODError(String.Format("return type mismatch for {0}",fname)); |
||
220 | |||
221 | OpenMetaverse.Vector3 result = (OpenMetaverse.Vector3)modInvoke(fname,parms); |
||
222 | return new LSL_Vector(result.X,result.Y,result.Z); |
||
223 | } |
||
224 | |||
225 | public LSL_Rotation modInvokeR(string fname, params object[] parms) |
||
226 | { |
||
227 | // m_log.DebugFormat( |
||
228 | // "[MOD API]: Invoking dynamic function {0}, args '{1}' with {2} return type", |
||
229 | // fname, |
||
230 | // string.Join(",", Array.ConvertAll<object, string>(parms, o => o.ToString())), |
||
231 | // ((MethodInfo)MethodBase.GetCurrentMethod()).ReturnType); |
||
232 | |||
233 | Type returntype = m_comms.LookupReturnType(fname); |
||
234 | if (returntype != typeof(OpenMetaverse.Quaternion)) |
||
235 | MODError(String.Format("return type mismatch for {0}",fname)); |
||
236 | |||
237 | OpenMetaverse.Quaternion result = (OpenMetaverse.Quaternion)modInvoke(fname,parms); |
||
238 | return new LSL_Rotation(result.X,result.Y,result.Z,result.W); |
||
239 | } |
||
240 | |||
241 | public LSL_List modInvokeL(string fname, params object[] parms) |
||
242 | { |
||
243 | // m_log.DebugFormat( |
||
244 | // "[MOD API]: Invoking dynamic function {0}, args '{1}' with {2} return type", |
||
245 | // fname, |
||
246 | // string.Join(",", Array.ConvertAll<object, string>(parms, o => o.ToString())), |
||
247 | // ((MethodInfo)MethodBase.GetCurrentMethod()).ReturnType); |
||
248 | |||
249 | Type returntype = m_comms.LookupReturnType(fname); |
||
250 | if (returntype != typeof(object[])) |
||
251 | MODError(String.Format("return type mismatch for {0}",fname)); |
||
252 | |||
253 | object[] result = (object[])modInvoke(fname,parms); |
||
254 | object[] llist = new object[result.Length]; |
||
255 | for (int i = 0; i < result.Length; i++) |
||
256 | { |
||
257 | if (result[i] is string) |
||
258 | { |
||
259 | llist[i] = new LSL_String((string)result[i]); |
||
260 | } |
||
261 | else if (result[i] is int) |
||
262 | { |
||
263 | llist[i] = new LSL_Integer((int)result[i]); |
||
264 | } |
||
265 | else if (result[i] is float) |
||
266 | { |
||
267 | llist[i] = new LSL_Float((float)result[i]); |
||
268 | } |
||
269 | else if (result[i] is double) |
||
270 | { |
||
271 | llist[i] = new LSL_Float((double)result[i]); |
||
272 | } |
||
273 | else if (result[i] is UUID) |
||
274 | { |
||
275 | llist[i] = new LSL_Key(result[i].ToString()); |
||
276 | } |
||
277 | else if (result[i] is OpenMetaverse.Vector3) |
||
278 | { |
||
279 | OpenMetaverse.Vector3 vresult = (OpenMetaverse.Vector3)result[i]; |
||
280 | llist[i] = new LSL_Vector(vresult.X, vresult.Y, vresult.Z); |
||
281 | } |
||
282 | else if (result[i] is OpenMetaverse.Quaternion) |
||
283 | { |
||
284 | OpenMetaverse.Quaternion qresult = (OpenMetaverse.Quaternion)result[i]; |
||
285 | llist[i] = new LSL_Rotation(qresult.X, qresult.Y, qresult.Z, qresult.W); |
||
286 | } |
||
287 | else |
||
288 | { |
||
289 | MODError(String.Format("unknown list element {1} returned by {0}", fname, result[i].GetType().Name)); |
||
290 | } |
||
291 | } |
||
292 | |||
293 | return new LSL_List(llist); |
||
294 | } |
||
295 | |||
296 | /// <summary> |
||
297 | /// Invokes a preregistered function through the ScriptModuleComms class |
||
298 | /// </summary> |
||
299 | /// <param name="fname">The name of the function to invoke</param> |
||
300 | /// <param name="fname">List of parameters</param> |
||
301 | /// <returns>string result of the invocation</returns> |
||
302 | protected object modInvoke(string fname, params object[] parms) |
||
303 | { |
||
304 | if (!m_MODFunctionsEnabled) |
||
305 | { |
||
306 | MODShoutError("Module command functions not enabled"); |
||
307 | return ""; |
||
308 | } |
||
309 | |||
310 | // m_log.DebugFormat( |
||
311 | // "[MOD API]: Invoking dynamic function {0}, args '{1}' with {2} return type", |
||
312 | // fname, |
||
313 | // string.Join(",", Array.ConvertAll<object, string>(parms, o => o.ToString())), |
||
314 | // ((MethodInfo)MethodBase.GetCurrentMethod()).ReturnType); |
||
315 | |||
316 | Type[] signature = m_comms.LookupTypeSignature(fname); |
||
317 | if (signature.Length != parms.Length) |
||
318 | MODError(String.Format("wrong number of parameters to function {0}",fname)); |
||
319 | |||
320 | object[] convertedParms = new object[parms.Length]; |
||
321 | for (int i = 0; i < parms.Length; i++) |
||
322 | convertedParms[i] = ConvertFromLSL(parms[i], signature[i], fname); |
||
323 | |||
324 | // now call the function, the contract with the function is that it will always return |
||
325 | // non-null but don't trust it completely |
||
326 | try |
||
327 | { |
||
328 | object result = m_comms.InvokeOperation(m_host.UUID, m_item.ItemID, fname, convertedParms); |
||
329 | if (result != null) |
||
330 | return result; |
||
331 | |||
332 | MODError(String.Format("Invocation of {0} failed; null return value",fname)); |
||
333 | } |
||
334 | catch (Exception e) |
||
335 | { |
||
336 | MODError(String.Format("Invocation of {0} failed; {1}",fname,e.Message)); |
||
337 | } |
||
338 | |||
339 | return null; |
||
340 | } |
||
341 | |||
342 | /// <summary> |
||
343 | /// Send a command to functions registered on an event |
||
344 | /// </summary> |
||
345 | public string modSendCommand(string module, string command, string k) |
||
346 | { |
||
347 | if (!m_MODFunctionsEnabled) |
||
348 | { |
||
349 | MODShoutError("Module command functions not enabled"); |
||
350 | return UUID.Zero.ToString();; |
||
351 | } |
||
352 | |||
353 | UUID req = UUID.Random(); |
||
354 | |||
355 | m_comms.RaiseEvent(m_item.ItemID, req.ToString(), module, command, k); |
||
356 | |||
357 | return req.ToString(); |
||
358 | } |
||
359 | |||
360 | /// <summary> |
||
361 | /// </summary> |
||
362 | protected object ConvertFromLSL(object lslparm, Type type, string fname) |
||
363 | { |
||
364 | // ---------- String ---------- |
||
365 | if (lslparm is LSL_String) |
||
366 | { |
||
367 | if (type == typeof(string)) |
||
368 | return (string)(LSL_String)lslparm; |
||
369 | |||
370 | // Need to check for UUID since keys are often treated as strings |
||
371 | if (type == typeof(UUID)) |
||
372 | return new UUID((string)(LSL_String)lslparm); |
||
373 | } |
||
374 | |||
375 | // ---------- Integer ---------- |
||
376 | else if (lslparm is LSL_Integer) |
||
377 | { |
||
378 | if (type == typeof(int) || type == typeof(float)) |
||
379 | return (int)(LSL_Integer)lslparm; |
||
380 | } |
||
381 | |||
382 | // ---------- Float ---------- |
||
383 | else if (lslparm is LSL_Float) |
||
384 | { |
||
385 | if (type == typeof(float)) |
||
386 | return (float)(LSL_Float)lslparm; |
||
387 | } |
||
388 | |||
389 | // ---------- Key ---------- |
||
390 | else if (lslparm is LSL_Key) |
||
391 | { |
||
392 | if (type == typeof(UUID)) |
||
393 | return new UUID((LSL_Key)lslparm); |
||
394 | } |
||
395 | |||
396 | // ---------- Rotation ---------- |
||
397 | else if (lslparm is LSL_Rotation) |
||
398 | { |
||
399 | if (type == typeof(OpenMetaverse.Quaternion)) |
||
400 | { |
||
401 | return (OpenMetaverse.Quaternion)((LSL_Rotation)lslparm); |
||
402 | } |
||
403 | } |
||
404 | |||
405 | // ---------- Vector ---------- |
||
406 | else if (lslparm is LSL_Vector) |
||
407 | { |
||
408 | if (type == typeof(OpenMetaverse.Vector3)) |
||
409 | { |
||
410 | return (OpenMetaverse.Vector3)((LSL_Vector)lslparm); |
||
411 | } |
||
412 | } |
||
413 | |||
414 | // ---------- List ---------- |
||
415 | else if (lslparm is LSL_List) |
||
416 | { |
||
417 | if (type == typeof(object[])) |
||
418 | { |
||
419 | object[] plist = (lslparm as LSL_List).Data; |
||
420 | object[] result = new object[plist.Length]; |
||
421 | for (int i = 0; i < plist.Length; i++) |
||
422 | { |
||
423 | if (plist[i] is LSL_String) |
||
424 | result[i] = (string)(LSL_String)plist[i]; |
||
425 | else if (plist[i] is LSL_Integer) |
||
426 | result[i] = (int)(LSL_Integer)plist[i]; |
||
427 | // The int check exists because of the many plain old int script constants in ScriptBase which |
||
428 | // are not LSL_Integers. |
||
429 | else if (plist[i] is int) |
||
430 | result[i] = plist[i]; |
||
431 | else if (plist[i] is LSL_Float) |
||
432 | result[i] = (float)(LSL_Float)plist[i]; |
||
433 | else if (plist[i] is LSL_Key) |
||
434 | result[i] = new UUID((LSL_Key)plist[i]); |
||
435 | else if (plist[i] is LSL_Rotation) |
||
436 | result[i] = (Quaternion)((LSL_Rotation)plist[i]); |
||
437 | else if (plist[i] is LSL_Vector) |
||
438 | result[i] = (Vector3)((LSL_Vector)plist[i]); |
||
439 | else |
||
440 | MODError(String.Format("{0}: unknown LSL list element type", fname)); |
||
441 | } |
||
442 | |||
443 | return result; |
||
444 | } |
||
445 | } |
||
446 | |||
447 | MODError(String.Format("{0}: parameter type mismatch; expecting {1}, type(parm)={2}", fname, type.Name, lslparm.GetType())); |
||
448 | return null; |
||
449 | } |
||
450 | |||
451 | } |
||
452 | } |