clockwerk-opensim-stable – Blame information for rev 1

Subversion Repositories:
Rev:
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 }