MOD_Api.cs 19 KB

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