OpenSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros
MOD_Api.cs
Go to the documentation of this file.
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 
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)
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 
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 
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),
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 
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(void))
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 
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  Type returntype = m_comms.LookupReturnType(fname);
333  if (returntype == typeof(void))
334  return null;
335 
336  MODError(String.Format("Invocation of {0} failed; null return value",fname));
337  }
338  catch (Exception e)
339  {
340  MODError(String.Format("Invocation of {0} failed; {1}",fname,e.Message));
341  }
342 
343  return null;
344  }
345 
349  public string modSendCommand(string module, string command, string k)
350  {
351  if (!m_MODFunctionsEnabled)
352  {
353  MODShoutError("Module command functions not enabled");
354  return UUID.Zero.ToString();;
355  }
356 
357  UUID req = UUID.Random();
358 
359  m_comms.RaiseEvent(m_item.ItemID, req.ToString(), module, command, k);
360 
361  return req.ToString();
362  }
363 
366  protected object ConvertFromLSL(object lslparm, Type type, string fname)
367  {
368  // ---------- String ----------
369  if (lslparm is LSL_String)
370  {
371  if (type == typeof(string))
372  return (string)(LSL_String)lslparm;
373 
374  // Need to check for UUID since keys are often treated as strings
375  if (type == typeof(UUID))
376  return new UUID((string)(LSL_String)lslparm);
377  }
378 
379  // ---------- Integer ----------
380  else if (lslparm is LSL_Integer)
381  {
382  if (type == typeof(int) || type == typeof(float))
383  return (int)(LSL_Integer)lslparm;
384  }
385 
386  // ---------- Float ----------
387  else if (lslparm is LSL_Float)
388  {
389  if (type == typeof(float))
390  return (float)(LSL_Float)lslparm;
391  }
392 
393  // ---------- Key ----------
394  else if (lslparm is LSL_Key)
395  {
396  if (type == typeof(UUID))
397  return new UUID((LSL_Key)lslparm);
398  }
399 
400  // ---------- Rotation ----------
401  else if (lslparm is LSL_Rotation)
402  {
403  if (type == typeof(OpenMetaverse.Quaternion))
404  {
405  return (OpenMetaverse.Quaternion)((LSL_Rotation)lslparm);
406  }
407  }
408 
409  // ---------- Vector ----------
410  else if (lslparm is LSL_Vector)
411  {
412  if (type == typeof(OpenMetaverse.Vector3))
413  {
414  return (OpenMetaverse.Vector3)((LSL_Vector)lslparm);
415  }
416  }
417 
418  // ---------- List ----------
419  else if (lslparm is LSL_List)
420  {
421  if (type == typeof(object[]))
422  {
423  object[] plist = ((LSL_List)lslparm).Data;
424  object[] result = new object[plist.Length];
425  for (int i = 0; i < plist.Length; i++)
426  {
427  if (plist[i] is LSL_String)
428  result[i] = (string)(LSL_String)plist[i];
429  else if (plist[i] is LSL_Integer)
430  result[i] = (int)(LSL_Integer)plist[i];
431  // The int check exists because of the many plain old int script constants in ScriptBase which
432  // are not LSL_Integers.
433  else if (plist[i] is int)
434  result[i] = plist[i];
435  else if (plist[i] is LSL_Float)
436  result[i] = (float)(LSL_Float)plist[i];
437  else if (plist[i] is LSL_Key)
438  result[i] = new UUID((LSL_Key)plist[i]);
439  else if (plist[i] is LSL_Rotation)
440  result[i] = (Quaternion)((LSL_Rotation)plist[i]);
441  else if (plist[i] is LSL_Vector)
442  result[i] = (Vector3)((LSL_Vector)plist[i]);
443  else
444  MODError(String.Format("{0}: unknown LSL list element type", fname));
445  }
446 
447  return result;
448  }
449  }
450 
451  MODError(String.Format("{0}: parameter type mismatch; expecting {1}, type(parm)={2}", fname, type.Name, lslparm.GetType()));
452  return null;
453  }
454 
455  }
456 }
LSL_Key modInvokeK(string fname, params object[] parms)
Definition: MOD_Api.cs:193
LSL_List modInvokeL(string fname, params object[] parms)
Definition: MOD_Api.cs:241
void Initialize(IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item)
Initialize the API
Definition: MOD_Api.cs:68
OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat LSL_Float
Definition: CM_Api.cs:48
OpenSim.Region.ScriptEngine.Shared.LSL_Types.list LSL_List
Definition: CM_Api.cs:51
OpenSim.Region.ScriptEngine.Shared.LSL_Types.list LSL_List
Definition: MOD_Api.cs:50
OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3 LSL_Vector
Definition: MOD_Api.cs:53
LSL_Integer modInvokeI(string fname, params object[] parms)
Definition: MOD_Api.cs:161
OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString LSL_Key
Definition: CM_Api.cs:50
LSL_String modInvokeS(string fname, params object[] parms)
Definition: MOD_Api.cs:145
LSL_Vector modInvokeV(string fname, params object[] parms)
Definition: MOD_Api.cs:209
Represents an item in a task inventory
OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3 LSL_Vector
Definition: CM_Api.cs:54
LSL_Float modInvokeF(string fname, params object[] parms)
Definition: MOD_Api.cs:177
An interface for a script API module to communicate with the engine it's running under ...
OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat LSL_Float
Definition: MOD_Api.cs:47
object ConvertFromLSL(object lslparm, Type type, string fname)
Definition: MOD_Api.cs:366
LSL_Rotation modInvokeR(string fname, params object[] parms)
Definition: MOD_Api.cs:225
string modSendCommand(string module, string command, string k)
Send a command to functions registered on an event
Definition: MOD_Api.cs:349
OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString LSL_Key
Definition: MOD_Api.cs:49
OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger LSL_Integer
Definition: CM_Api.cs:49
Interface for communication between OpenSim modules and in-world scripts
OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion LSL_Rotation
Definition: CM_Api.cs:52
void modInvokeN(string fname, params object[] parms)
Definition: MOD_Api.cs:130
OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger LSL_Integer
Definition: MOD_Api.cs:48
OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString LSL_String
Definition: MOD_Api.cs:52
Interactive OpenSim region server
Definition: OpenSim.cs:55
OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger LSLInteger
Definition: CM_Constants.cs:31
object modInvoke(string fname, params object[] parms)
Invokes a preregistered function through the ScriptModuleComms class
Definition: MOD_Api.cs:302
OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString LSL_String
Definition: CM_Api.cs:53
OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion LSL_Rotation
Definition: MOD_Api.cs:51