EventManager.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536
  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 OpenSim 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.Collections.Generic;
  29. using System.Reflection;
  30. using OpenMetaverse;
  31. using OpenSim.Framework;
  32. using OpenSim.Region.CoreModules.Avatar.Currency.SampleMoney;
  33. using OpenSim.Region.CoreModules;
  34. using OpenSim.Region;
  35. using OpenSim.Region.Framework.Scenes;
  36. using OpenSim.Region.Framework.Interfaces;
  37. using OpenSim.Region.ScriptEngine.Shared;
  38. using log4net;
  39. namespace OpenSim.Region.ScriptEngine.DotNetEngine
  40. {
  41. /// <summary>
  42. /// Prepares events so they can be directly executed upon a script by EventQueueManager, then queues it.
  43. /// </summary>
  44. [Serializable]
  45. public class EventManager
  46. {
  47. //
  48. // Class is instanced in "ScriptEngine" and Uses "EventQueueManager"
  49. // that is also instanced in "ScriptEngine".
  50. // This class needs a bit of explaining:
  51. //
  52. // This class it the link between an event inside OpenSim and
  53. // the corresponding event in a user script being executed.
  54. //
  55. // For example when an user touches an object then the
  56. // "myScriptEngine.World.EventManager.OnObjectGrab" event is fired
  57. // inside OpenSim.
  58. // We hook up to this event and queue a touch_start in
  59. // EventQueueManager with the proper LSL parameters.
  60. // It will then be delivered to the script by EventQueueManager.
  61. //
  62. // You can check debug C# dump of an LSL script if you need to
  63. // verify what exact parameters are needed.
  64. //
  65. private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  66. private ScriptEngine myScriptEngine;
  67. public EventManager(ScriptEngine _ScriptEngine, bool performHookUp)
  68. {
  69. myScriptEngine = _ScriptEngine;
  70. ReadConfig();
  71. if (performHookUp)
  72. {
  73. myScriptEngine.World.EventManager.OnRezScript += OnRezScript;
  74. }
  75. }
  76. public void HookUpEvents()
  77. {
  78. m_log.Info("[" + myScriptEngine.ScriptEngineName +
  79. "]: Hooking up to server events");
  80. myScriptEngine.World.EventManager.OnObjectGrab +=
  81. touch_start;
  82. myScriptEngine.World.EventManager.OnObjectDeGrab +=
  83. touch_end;
  84. myScriptEngine.World.EventManager.OnRemoveScript +=
  85. OnRemoveScript;
  86. myScriptEngine.World.EventManager.OnScriptChangedEvent +=
  87. changed;
  88. myScriptEngine.World.EventManager.OnScriptAtTargetEvent +=
  89. at_target;
  90. myScriptEngine.World.EventManager.OnScriptNotAtTargetEvent +=
  91. not_at_target;
  92. myScriptEngine.World.EventManager.OnScriptControlEvent +=
  93. control;
  94. myScriptEngine.World.EventManager.OnScriptColliderStart +=
  95. collision_start;
  96. myScriptEngine.World.EventManager.OnScriptColliding +=
  97. collision;
  98. myScriptEngine.World.EventManager.OnScriptCollidingEnd +=
  99. collision_end;
  100. IMoneyModule money =
  101. myScriptEngine.World.RequestModuleInterface<IMoneyModule>();
  102. if (money != null)
  103. money.OnObjectPaid+=HandleObjectPaid;
  104. }
  105. public void ReadConfig()
  106. {
  107. }
  108. private void HandleObjectPaid(UUID objectID, UUID agentID, int amount)
  109. {
  110. SceneObjectPart part =
  111. myScriptEngine.World.GetSceneObjectPart(objectID);
  112. if (part != null)
  113. {
  114. money(part.LocalId, agentID, amount);
  115. }
  116. }
  117. public void changed(uint localID, uint change)
  118. {
  119. // Add to queue for all scripts in localID, Object pass change.
  120. myScriptEngine.PostObjectEvent(localID, new EventParams(
  121. "changed",new object[] { new LSL_Types.LSLInteger(change) },
  122. new DetectParams[0]));
  123. }
  124. public void state_entry(uint localID)
  125. {
  126. // Add to queue for all scripts in ObjectID object
  127. myScriptEngine.PostObjectEvent(localID, new EventParams(
  128. "state_entry",new object[] { },
  129. new DetectParams[0]));
  130. }
  131. public void touch_start(uint localID, uint originalID,
  132. Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs)
  133. {
  134. // Add to queue for all scripts in ObjectID object
  135. DetectParams[] det = new DetectParams[1];
  136. det[0] = new DetectParams();
  137. det[0].Key = remoteClient.AgentId;
  138. det[0].Populate(myScriptEngine.World);
  139. if (originalID == 0)
  140. {
  141. SceneObjectPart part =
  142. myScriptEngine.World.GetSceneObjectPart(localID);
  143. if (part == null)
  144. return;
  145. det[0].LinkNum = part.LinkNum;
  146. }
  147. else
  148. {
  149. SceneObjectPart originalPart =
  150. myScriptEngine.World.GetSceneObjectPart(originalID);
  151. det[0].LinkNum = originalPart.LinkNum;
  152. }
  153. if (surfaceArgs != null)
  154. {
  155. det[0].SurfaceTouchArgs = surfaceArgs;
  156. }
  157. myScriptEngine.PostObjectEvent(localID, new EventParams(
  158. "touch_start", new Object[] { new LSL_Types.LSLInteger(1) },
  159. det));
  160. }
  161. public void touch(uint localID, uint originalID, Vector3 offsetPos,
  162. IClientAPI remoteClient)
  163. {
  164. // Add to queue for all scripts in ObjectID object
  165. DetectParams[] det = new DetectParams[1];
  166. det[0] = new DetectParams();
  167. det[0].Key = remoteClient.AgentId;
  168. det[0].Populate(myScriptEngine.World);
  169. det[0].OffsetPos = new LSL_Types.Vector3(offsetPos.X,
  170. offsetPos.Y,
  171. offsetPos.Z);
  172. if (originalID == 0)
  173. {
  174. SceneObjectPart part = myScriptEngine.World.GetSceneObjectPart(localID);
  175. if (part == null)
  176. return;
  177. det[0].LinkNum = part.LinkNum;
  178. }
  179. else
  180. {
  181. SceneObjectPart originalPart = myScriptEngine.World.GetSceneObjectPart(originalID);
  182. det[0].LinkNum = originalPart.LinkNum;
  183. }
  184. myScriptEngine.PostObjectEvent(localID, new EventParams(
  185. "touch", new Object[] { new LSL_Types.LSLInteger(1) },
  186. det));
  187. }
  188. public void touch_end(uint localID, uint originalID, IClientAPI remoteClient)
  189. {
  190. // Add to queue for all scripts in ObjectID object
  191. DetectParams[] det = new DetectParams[1];
  192. det[0] = new DetectParams();
  193. det[0].Key = remoteClient.AgentId;
  194. det[0].Populate(myScriptEngine.World);
  195. if (originalID == 0)
  196. {
  197. SceneObjectPart part =
  198. myScriptEngine.World.GetSceneObjectPart(localID);
  199. if (part == null)
  200. return;
  201. det[0].LinkNum = part.LinkNum;
  202. }
  203. else
  204. {
  205. SceneObjectPart originalPart =
  206. myScriptEngine.World.GetSceneObjectPart(originalID);
  207. det[0].LinkNum = originalPart.LinkNum;
  208. }
  209. myScriptEngine.PostObjectEvent(localID, new EventParams(
  210. "touch_end", new Object[] { new LSL_Types.LSLInteger(1) },
  211. det));
  212. }
  213. public void OnRezScript(uint localID, UUID itemID, string script,
  214. int startParam, bool postOnRez, string engine, int stateSource)
  215. {
  216. List<IScriptModule> engines =
  217. new List<IScriptModule>(
  218. myScriptEngine.World.RequestModuleInterfaces<IScriptModule>());
  219. List<string> names = new List<string>();
  220. foreach (IScriptModule m in engines)
  221. names.Add(m.ScriptEngineName);
  222. int lineEnd = script.IndexOf('\n');
  223. if (lineEnd > 1)
  224. {
  225. string firstline = script.Substring(0, lineEnd).Trim();
  226. int colon = firstline.IndexOf(':');
  227. if (firstline.Length > 2 &&
  228. firstline.Substring(0, 2) == "//" && colon != -1)
  229. {
  230. string engineName = firstline.Substring(2, colon-2);
  231. if (names.Contains(engineName))
  232. {
  233. engine = engineName;
  234. script = "//" + script.Substring(script.IndexOf(':')+1);
  235. }
  236. else
  237. {
  238. if (engine == myScriptEngine.ScriptEngineName)
  239. {
  240. SceneObjectPart part =
  241. myScriptEngine.World.GetSceneObjectPart(
  242. localID);
  243. TaskInventoryItem item =
  244. part.Inventory.GetInventoryItem(itemID);
  245. ScenePresence presence =
  246. myScriptEngine.World.GetScenePresence(
  247. item.OwnerID);
  248. if (presence != null)
  249. {
  250. presence.ControllingClient.SendAgentAlertMessage(
  251. "Selected engine unavailable. "+
  252. "Running script on "+
  253. myScriptEngine.ScriptEngineName,
  254. false);
  255. }
  256. }
  257. }
  258. }
  259. }
  260. if (engine != myScriptEngine.ScriptEngineName)
  261. return;
  262. m_log.Debug("OnRezScript localID: " + localID +
  263. " LLUID: " + itemID.ToString() + " Size: " +
  264. script.Length);
  265. myScriptEngine.m_ScriptManager.StartScript(localID, itemID, script,
  266. startParam, postOnRez);
  267. }
  268. public void OnRemoveScript(uint localID, UUID itemID)
  269. {
  270. m_log.Debug("OnRemoveScript localID: " + localID + " LLUID: " + itemID.ToString());
  271. myScriptEngine.m_ScriptManager.StopScript(
  272. localID,
  273. itemID
  274. );
  275. }
  276. public void money(uint localID, UUID agentID, int amount)
  277. {
  278. myScriptEngine.PostObjectEvent(localID, new EventParams(
  279. "money", new object[] {
  280. new LSL_Types.LSLString(agentID.ToString()),
  281. new LSL_Types.LSLInteger(amount) },
  282. new DetectParams[0]));
  283. }
  284. // TODO: Replace placeholders below
  285. // NOTE! THE PARAMETERS FOR THESE FUNCTIONS ARE NOT CORRECT!
  286. // These needs to be hooked up to OpenSim during init of this class
  287. // then queued in EventQueueManager.
  288. // When queued in EventQueueManager they need to be LSL compatible (name and params)
  289. public void state_exit(uint localID)
  290. {
  291. myScriptEngine.PostObjectEvent(localID, new EventParams(
  292. "state_exit", new object[] { },
  293. new DetectParams[0]));
  294. }
  295. public void collision_start(uint localID, ColliderArgs col)
  296. {
  297. // Add to queue for all scripts in ObjectID object
  298. List<DetectParams> det = new List<DetectParams>();
  299. foreach (DetectedObject detobj in col.Colliders)
  300. {
  301. DetectParams d = new DetectParams();
  302. d.Key =detobj.keyUUID;
  303. d.Populate(myScriptEngine.World);
  304. det.Add(d);
  305. }
  306. if (det.Count > 0)
  307. myScriptEngine.PostObjectEvent(localID, new EventParams(
  308. "collision_start",
  309. new Object[] { new LSL_Types.LSLInteger(det.Count) },
  310. det.ToArray()));
  311. }
  312. public void collision(uint localID, ColliderArgs col)
  313. {
  314. // Add to queue for all scripts in ObjectID object
  315. List<DetectParams> det = new List<DetectParams>();
  316. foreach (DetectedObject detobj in col.Colliders)
  317. {
  318. DetectParams d = new DetectParams();
  319. d.Key =detobj.keyUUID;
  320. d.Populate(myScriptEngine.World);
  321. det.Add(d);
  322. }
  323. if (det.Count > 0)
  324. myScriptEngine.PostObjectEvent(localID, new EventParams(
  325. "collision", new Object[] { new LSL_Types.LSLInteger(det.Count) },
  326. det.ToArray()));
  327. }
  328. public void collision_end(uint localID, ColliderArgs col)
  329. {
  330. // Add to queue for all scripts in ObjectID object
  331. List<DetectParams> det = new List<DetectParams>();
  332. foreach (DetectedObject detobj in col.Colliders)
  333. {
  334. DetectParams d = new DetectParams();
  335. d.Key =detobj.keyUUID;
  336. d.Populate(myScriptEngine.World);
  337. det.Add(d);
  338. }
  339. if (det.Count > 0)
  340. myScriptEngine.PostObjectEvent(localID, new EventParams(
  341. "collision_end",
  342. new Object[] { new LSL_Types.LSLInteger(det.Count) },
  343. det.ToArray()));
  344. }
  345. public void land_collision_start(uint localID, UUID itemID)
  346. {
  347. myScriptEngine.PostObjectEvent(localID, new EventParams(
  348. "land_collision_start",
  349. new object[0],
  350. new DetectParams[0]));
  351. }
  352. public void land_collision(uint localID, UUID itemID)
  353. {
  354. myScriptEngine.PostObjectEvent(localID, new EventParams(
  355. "land_collision",
  356. new object[0],
  357. new DetectParams[0]));
  358. }
  359. public void land_collision_end(uint localID, UUID itemID)
  360. {
  361. myScriptEngine.PostObjectEvent(localID, new EventParams(
  362. "land_collision_end",
  363. new object[0],
  364. new DetectParams[0]));
  365. }
  366. // Handled by long commands
  367. public void timer(uint localID, UUID itemID)
  368. {
  369. }
  370. public void listen(uint localID, UUID itemID)
  371. {
  372. }
  373. public void control(uint localID, UUID itemID, UUID agentID, uint held, uint change)
  374. {
  375. if ((change == 0) && (myScriptEngine.m_EventQueueManager.CheckEeventQueueForEvent(localID,"control"))) return;
  376. myScriptEngine.PostObjectEvent(localID, new EventParams(
  377. "control",new object[] {
  378. new LSL_Types.LSLString(agentID.ToString()),
  379. new LSL_Types.LSLInteger(held),
  380. new LSL_Types.LSLInteger(change)},
  381. new DetectParams[0]));
  382. }
  383. public void email(uint localID, UUID itemID, string timeSent,
  384. string address, string subject, string message, int numLeft)
  385. {
  386. myScriptEngine.PostObjectEvent(localID, new EventParams(
  387. "email",new object[] {
  388. new LSL_Types.LSLString(timeSent),
  389. new LSL_Types.LSLString(address),
  390. new LSL_Types.LSLString(subject),
  391. new LSL_Types.LSLString(message),
  392. new LSL_Types.LSLInteger(numLeft)},
  393. new DetectParams[0]));
  394. }
  395. public void at_target(uint localID, uint handle, Vector3 targetpos,
  396. Vector3 atpos)
  397. {
  398. myScriptEngine.PostObjectEvent(localID, new EventParams(
  399. "at_target", new object[] {
  400. new LSL_Types.LSLInteger(handle),
  401. new LSL_Types.Vector3(targetpos.X,targetpos.Y,targetpos.Z),
  402. new LSL_Types.Vector3(atpos.X,atpos.Y,atpos.Z) },
  403. new DetectParams[0]));
  404. }
  405. public void not_at_target(uint localID)
  406. {
  407. myScriptEngine.PostObjectEvent(localID, new EventParams(
  408. "not_at_target",new object[0],
  409. new DetectParams[0]));
  410. }
  411. public void at_rot_target(uint localID, UUID itemID)
  412. {
  413. myScriptEngine.PostObjectEvent(localID, new EventParams(
  414. "at_rot_target",new object[0],
  415. new DetectParams[0]));
  416. }
  417. public void not_at_rot_target(uint localID, UUID itemID)
  418. {
  419. myScriptEngine.PostObjectEvent(localID, new EventParams(
  420. "not_at_rot_target",new object[0],
  421. new DetectParams[0]));
  422. }
  423. public void attach(uint localID, UUID itemID)
  424. {
  425. }
  426. public void dataserver(uint localID, UUID itemID)
  427. {
  428. }
  429. public void link_message(uint localID, UUID itemID)
  430. {
  431. }
  432. public void moving_start(uint localID, UUID itemID)
  433. {
  434. myScriptEngine.PostObjectEvent(localID, new EventParams(
  435. "moving_start",new object[0],
  436. new DetectParams[0]));
  437. }
  438. public void moving_end(uint localID, UUID itemID)
  439. {
  440. myScriptEngine.PostObjectEvent(localID, new EventParams(
  441. "moving_end",new object[0],
  442. new DetectParams[0]));
  443. }
  444. public void object_rez(uint localID, UUID itemID)
  445. {
  446. }
  447. public void remote_data(uint localID, UUID itemID)
  448. {
  449. }
  450. // Handled by long commands
  451. public void http_response(uint localID, UUID itemID)
  452. {
  453. }
  454. /// <summary>
  455. /// If set to true then threads and stuff should try to make a graceful exit
  456. /// </summary>
  457. public bool PleaseShutdown
  458. {
  459. get { return _PleaseShutdown; }
  460. set { _PleaseShutdown = value; }
  461. }
  462. private bool _PleaseShutdown = false;
  463. }
  464. }