MOD_Api.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  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. using System;
  28. using System.Reflection;
  29. using System.Collections;
  30. using System.Collections.Generic;
  31. using System.Runtime.Remoting.Lifetime;
  32. using OpenMetaverse;
  33. using Nini.Config;
  34. using OpenSim;
  35. using OpenSim.Framework;
  36. using OpenSim.Region.Framework.Interfaces;
  37. using OpenSim.Region.Framework.Scenes;
  38. using OpenSim.Region.ScriptEngine.Shared;
  39. using OpenSim.Region.ScriptEngine.Shared.Api.Plugins;
  40. using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
  41. using OpenSim.Region.ScriptEngine.Interfaces;
  42. using OpenSim.Region.ScriptEngine.Shared.Api.Interfaces;
  43. using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
  44. using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
  45. using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
  46. using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
  47. using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
  48. using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
  49. using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
  50. namespace OpenSim.Region.ScriptEngine.Shared.Api
  51. {
  52. [Serializable]
  53. public class MOD_Api : MarshalByRefObject, IMOD_Api, IScriptApi
  54. {
  55. internal IScriptEngine m_ScriptEngine;
  56. internal SceneObjectPart m_host;
  57. internal TaskInventoryItem m_item;
  58. internal bool m_MODFunctionsEnabled = false;
  59. internal IScriptModuleComms m_comms = null;
  60. public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item)
  61. {
  62. m_ScriptEngine = ScriptEngine;
  63. m_host = host;
  64. m_item = item;
  65. if (m_ScriptEngine.Config.GetBoolean("AllowMODFunctions", false))
  66. m_MODFunctionsEnabled = true;
  67. m_comms = m_ScriptEngine.World.RequestModuleInterface<IScriptModuleComms>();
  68. if (m_comms == null)
  69. m_MODFunctionsEnabled = false;
  70. }
  71. public override Object InitializeLifetimeService()
  72. {
  73. ILease lease = (ILease)base.InitializeLifetimeService();
  74. if (lease.CurrentState == LeaseState.Initial)
  75. {
  76. lease.InitialLeaseTime = TimeSpan.FromMinutes(0);
  77. // lease.RenewOnCallTime = TimeSpan.FromSeconds(10.0);
  78. // lease.SponsorshipTimeout = TimeSpan.FromMinutes(1.0);
  79. }
  80. return lease;
  81. }
  82. public Scene World
  83. {
  84. get { return m_ScriptEngine.World; }
  85. }
  86. internal void MODError(string msg)
  87. {
  88. throw new ScriptException("MOD Runtime Error: " + msg);
  89. }
  90. /// <summary>
  91. /// Dumps an error message on the debug console.
  92. /// </summary>
  93. /// <param name='message'></param>
  94. internal void MODShoutError(string message)
  95. {
  96. if (message.Length > 1023)
  97. message = message.Substring(0, 1023);
  98. World.SimChat(Utils.StringToBytes(message),
  99. ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, true);
  100. IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
  101. wComm.DeliverMessage(ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.Name, m_host.UUID, message);
  102. }
  103. /// <summary>
  104. ///
  105. /// </summary>
  106. /// <param name="fname">The name of the function to invoke</param>
  107. /// <param name="parms">List of parameters</param>
  108. /// <returns>string result of the invocation</returns>
  109. public void modInvokeN(string fname, params object[] parms)
  110. {
  111. Type returntype = m_comms.LookupReturnType(fname);
  112. if (returntype != typeof(string))
  113. MODError(String.Format("return type mismatch for {0}",fname));
  114. modInvoke(fname,parms);
  115. }
  116. public LSL_String modInvokeS(string fname, params object[] parms)
  117. {
  118. Type returntype = m_comms.LookupReturnType(fname);
  119. if (returntype != typeof(string))
  120. MODError(String.Format("return type mismatch for {0}",fname));
  121. string result = (string)modInvoke(fname,parms);
  122. return new LSL_String(result);
  123. }
  124. public LSL_Integer modInvokeI(string fname, params object[] parms)
  125. {
  126. Type returntype = m_comms.LookupReturnType(fname);
  127. if (returntype != typeof(int))
  128. MODError(String.Format("return type mismatch for {0}",fname));
  129. int result = (int)modInvoke(fname,parms);
  130. return new LSL_Integer(result);
  131. }
  132. public LSL_Float modInvokeF(string fname, params object[] parms)
  133. {
  134. Type returntype = m_comms.LookupReturnType(fname);
  135. if (returntype != typeof(float))
  136. MODError(String.Format("return type mismatch for {0}",fname));
  137. float result = (float)modInvoke(fname,parms);
  138. return new LSL_Float(result);
  139. }
  140. public LSL_Key modInvokeK(string fname, params object[] parms)
  141. {
  142. Type returntype = m_comms.LookupReturnType(fname);
  143. if (returntype != typeof(UUID))
  144. MODError(String.Format("return type mismatch for {0}",fname));
  145. UUID result = (UUID)modInvoke(fname,parms);
  146. return new LSL_Key(result.ToString());
  147. }
  148. public LSL_Vector modInvokeV(string fname, params object[] parms)
  149. {
  150. Type returntype = m_comms.LookupReturnType(fname);
  151. if (returntype != typeof(OpenMetaverse.Vector3))
  152. MODError(String.Format("return type mismatch for {0}",fname));
  153. OpenMetaverse.Vector3 result = (OpenMetaverse.Vector3)modInvoke(fname,parms);
  154. return new LSL_Vector(result.X,result.Y,result.Z);
  155. }
  156. public LSL_Rotation modInvokeR(string fname, params object[] parms)
  157. {
  158. Type returntype = m_comms.LookupReturnType(fname);
  159. if (returntype != typeof(OpenMetaverse.Quaternion))
  160. MODError(String.Format("return type mismatch for {0}",fname));
  161. OpenMetaverse.Quaternion result = (OpenMetaverse.Quaternion)modInvoke(fname,parms);
  162. return new LSL_Rotation(result.X,result.Y,result.Z,result.W);
  163. }
  164. public LSL_List modInvokeL(string fname, params object[] parms)
  165. {
  166. Type returntype = m_comms.LookupReturnType(fname);
  167. if (returntype != typeof(object[]))
  168. MODError(String.Format("return type mismatch for {0}",fname));
  169. object[] result = (object[])modInvoke(fname,parms);
  170. object[] llist = new object[result.Length];
  171. for (int i = 0; i < result.Length; i++)
  172. {
  173. if (result[i] is string)
  174. {
  175. llist[i] = new LSL_String((string)result[i]);
  176. }
  177. else if (result[i] is int)
  178. {
  179. llist[i] = new LSL_Integer((int)result[i]);
  180. }
  181. else if (result[i] is float)
  182. {
  183. llist[i] = new LSL_Float((float)result[i]);
  184. }
  185. else if (result[i] is UUID)
  186. {
  187. llist[i] = new LSL_Key(result[i].ToString());
  188. }
  189. else if (result[i] is OpenMetaverse.Vector3)
  190. {
  191. OpenMetaverse.Vector3 vresult = (OpenMetaverse.Vector3)result[i];
  192. llist[i] = new LSL_Vector(vresult.X, vresult.Y, vresult.Z);
  193. }
  194. else if (result[i] is OpenMetaverse.Quaternion)
  195. {
  196. OpenMetaverse.Quaternion qresult = (OpenMetaverse.Quaternion)result[i];
  197. llist[i] = new LSL_Rotation(qresult.X, qresult.Y, qresult.Z, qresult.W);
  198. }
  199. else
  200. {
  201. MODError(String.Format("unknown list element {1} returned by {0}", fname, result[i].GetType().Name));
  202. }
  203. }
  204. return new LSL_List(llist);
  205. }
  206. /// <summary>
  207. /// Invokes a preregistered function through the ScriptModuleComms class
  208. /// </summary>
  209. /// <param name="fname">The name of the function to invoke</param>
  210. /// <param name="fname">List of parameters</param>
  211. /// <returns>string result of the invocation</returns>
  212. protected object modInvoke(string fname, params object[] parms)
  213. {
  214. if (!m_MODFunctionsEnabled)
  215. {
  216. MODShoutError("Module command functions not enabled");
  217. return "";
  218. }
  219. Type[] signature = m_comms.LookupTypeSignature(fname);
  220. if (signature.Length != parms.Length)
  221. MODError(String.Format("wrong number of parameters to function {0}",fname));
  222. object[] convertedParms = new object[parms.Length];
  223. for (int i = 0; i < parms.Length; i++)
  224. convertedParms[i] = ConvertFromLSL(parms[i],signature[i], fname);
  225. // now call the function, the contract with the function is that it will always return
  226. // non-null but don't trust it completely
  227. try
  228. {
  229. object result = m_comms.InvokeOperation(m_host.UUID, m_item.ItemID, fname, convertedParms);
  230. if (result != null)
  231. return result;
  232. MODError(String.Format("Invocation of {0} failed; null return value",fname));
  233. }
  234. catch (Exception e)
  235. {
  236. MODError(String.Format("Invocation of {0} failed; {1}",fname,e.Message));
  237. }
  238. return null;
  239. }
  240. /// <summary>
  241. /// Send a command to functions registered on an event
  242. /// </summary>
  243. public string modSendCommand(string module, string command, string k)
  244. {
  245. if (!m_MODFunctionsEnabled)
  246. {
  247. MODShoutError("Module command functions not enabled");
  248. return UUID.Zero.ToString();;
  249. }
  250. UUID req = UUID.Random();
  251. m_comms.RaiseEvent(m_item.ItemID, req.ToString(), module, command, k);
  252. return req.ToString();
  253. }
  254. /// <summary>
  255. /// </summary>
  256. protected object ConvertFromLSL(object lslparm, Type type, string fname)
  257. {
  258. // ---------- String ----------
  259. if (lslparm is LSL_String)
  260. {
  261. if (type == typeof(string))
  262. return (string)(LSL_String)lslparm;
  263. // Need to check for UUID since keys are often treated as strings
  264. if (type == typeof(UUID))
  265. return new UUID((string)(LSL_String)lslparm);
  266. }
  267. // ---------- Integer ----------
  268. else if (lslparm is LSL_Integer)
  269. {
  270. if (type == typeof(int) || type == typeof(float))
  271. return (int)(LSL_Integer)lslparm;
  272. }
  273. // ---------- Float ----------
  274. else if (lslparm is LSL_Float)
  275. {
  276. if (type == typeof(float))
  277. return (float)(LSL_Float)lslparm;
  278. }
  279. // ---------- Key ----------
  280. else if (lslparm is LSL_Key)
  281. {
  282. if (type == typeof(UUID))
  283. return new UUID((LSL_Key)lslparm);
  284. }
  285. // ---------- Rotation ----------
  286. else if (lslparm is LSL_Rotation)
  287. {
  288. if (type == typeof(OpenMetaverse.Quaternion))
  289. {
  290. return (OpenMetaverse.Quaternion)((LSL_Rotation)lslparm);
  291. }
  292. }
  293. // ---------- Vector ----------
  294. else if (lslparm is LSL_Vector)
  295. {
  296. if (type == typeof(OpenMetaverse.Vector3))
  297. {
  298. return (OpenMetaverse.Vector3)((LSL_Vector)lslparm);
  299. }
  300. }
  301. // ---------- List ----------
  302. else if (lslparm is LSL_List)
  303. {
  304. if (type == typeof(object[]))
  305. {
  306. object[] plist = (lslparm as LSL_List).Data;
  307. object[] result = new object[plist.Length];
  308. for (int i = 0; i < plist.Length; i++)
  309. {
  310. if (plist[i] is LSL_String)
  311. result[i] = (string)(LSL_String)plist[i];
  312. else if (plist[i] is LSL_Integer)
  313. result[i] = (int)(LSL_Integer)plist[i];
  314. // The int check exists because of the many plain old int script constants in ScriptBase which
  315. // are not LSL_Integers.
  316. else if (plist[i] is int)
  317. result[i] = plist[i];
  318. else if (plist[i] is LSL_Float)
  319. result[i] = (float)(LSL_Float)plist[i];
  320. else if (plist[i] is LSL_Key)
  321. result[i] = new UUID((LSL_Key)plist[i]);
  322. else if (plist[i] is LSL_Rotation)
  323. result[i] = (Quaternion)((LSL_Rotation)plist[i]);
  324. else if (plist[i] is LSL_Vector)
  325. result[i] = (Vector3)((LSL_Vector)plist[i]);
  326. else
  327. MODError(String.Format("{0}: unknown LSL list element type", fname));
  328. }
  329. return result;
  330. }
  331. }
  332. MODError(String.Format("{1}: parameter type mismatch; expecting {0}",type.Name, fname));
  333. return null;
  334. }
  335. }
  336. }