PageRenderTime 56ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 3ms

/Aurora/AuroraDotNetEngine/APIs/LSL_Api.cs

https://bitbucket.org/VirtualReality/aurora-sim
C# | 11892 lines | 9029 code | 1744 blank | 1119 comment | 2752 complexity | 3e42528a41dc4612bd21e14c964eefd9 MD5 | raw file
  1. /*
  2. * Copyright (c) Contributors, http://aurora-sim.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 Aurora-Sim 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;
  29. using System.Collections.Generic;
  30. using System.Linq;
  31. using System.Runtime.Remoting.Lifetime;
  32. using System.Text;
  33. using System.Threading;
  34. using System.Text.RegularExpressions;
  35. using Nini.Config;
  36. using OpenMetaverse;
  37. using OpenMetaverse.Packets;
  38. using Aurora.Framework;
  39. using OpenSim.Region.Framework.Interfaces;
  40. using OpenSim.Region.Framework.Scenes;
  41. using OpenSim.Region.Framework.Scenes.Serialization;
  42. using Aurora.ScriptEngine.AuroraDotNetEngine.Plugins;
  43. using Aurora.ScriptEngine.AuroraDotNetEngine.APIs.Interfaces;
  44. using Aurora.ScriptEngine.AuroraDotNetEngine.Runtime;
  45. using OpenSim.Services.Interfaces;
  46. using GridRegion = OpenSim.Services.Interfaces.GridRegion;
  47. using PrimType = Aurora.Framework.PrimType;
  48. using AssetLandmark = Aurora.Framework.AssetLandmark;
  49. using LSL_Float = Aurora.ScriptEngine.AuroraDotNetEngine.LSL_Types.LSLFloat;
  50. using LSL_Integer = Aurora.ScriptEngine.AuroraDotNetEngine.LSL_Types.LSLInteger;
  51. using LSL_Key = Aurora.ScriptEngine.AuroraDotNetEngine.LSL_Types.LSLString;
  52. using LSL_List = Aurora.ScriptEngine.AuroraDotNetEngine.LSL_Types.list;
  53. using LSL_Rotation = Aurora.ScriptEngine.AuroraDotNetEngine.LSL_Types.Quaternion;
  54. using LSL_String = Aurora.ScriptEngine.AuroraDotNetEngine.LSL_Types.LSLString;
  55. using LSL_Vector = Aurora.ScriptEngine.AuroraDotNetEngine.LSL_Types.Vector3;
  56. namespace Aurora.ScriptEngine.AuroraDotNetEngine.APIs
  57. {
  58. /// <summary>
  59. /// Contains all LSL ll-functions. This class will be in Default AppDomain.
  60. /// </summary>
  61. [Serializable]
  62. public class LSL_Api : MarshalByRefObject, ILSL_Api, IScriptApi
  63. {
  64. protected IScriptModulePlugin m_ScriptEngine;
  65. protected ISceneChildEntity m_host;
  66. protected uint m_localID;
  67. protected UUID m_itemID;
  68. protected bool throwErrorOnNotImplemented = true;
  69. protected float m_ScriptDelayFactor = 1.0f;
  70. protected float m_ScriptDistanceFactor = 1.0f;
  71. protected float m_MinTimerInterval = 0.1f;
  72. protected DateTime m_timer = DateTime.Now;
  73. protected bool m_waitingForScriptAnswer = false;
  74. protected bool m_automaticLinkPermission = false;
  75. protected IMessageTransferModule m_TransferModule = null;
  76. protected int m_notecardLineReadCharsMax = 255;
  77. protected int m_scriptConsoleChannel = 0;
  78. protected bool m_scriptConsoleChannelEnabled = false;
  79. protected IUrlModule m_UrlModule = null;
  80. internal ScriptProtectionModule ScriptProtection;
  81. protected IWorldComm m_comms = null;
  82. // MUST be a ref type
  83. public class UserInfoCacheEntry
  84. {
  85. public int time;
  86. public UserAccount account;
  87. public UserInfo pinfo;
  88. }
  89. protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache =
  90. new Dictionary<UUID, UserInfoCacheEntry>();
  91. public void Initialize(IScriptModulePlugin ScriptEngine, ISceneChildEntity host, uint localID, UUID itemID, ScriptProtectionModule module)
  92. {
  93. m_ScriptEngine = ScriptEngine;
  94. m_host = host;
  95. m_localID = localID;
  96. m_itemID = itemID;
  97. ScriptProtection = module;
  98. m_ScriptDelayFactor =
  99. m_ScriptEngine.Config.GetFloat("ScriptDelayFactor", 1.0f);
  100. m_ScriptDistanceFactor =
  101. m_ScriptEngine.Config.GetFloat("ScriptDistanceLimitFactor", 1.0f);
  102. m_MinTimerInterval =
  103. m_ScriptEngine.Config.GetFloat("MinTimerInterval", 0.5f);
  104. m_automaticLinkPermission =
  105. m_ScriptEngine.Config.GetBoolean("AutomaticLinkPermission", false);
  106. m_notecardLineReadCharsMax =
  107. m_ScriptEngine.Config.GetInt("NotecardLineReadCharsMax", 255);
  108. if (m_notecardLineReadCharsMax > 65535)
  109. m_notecardLineReadCharsMax = 65535;
  110. m_TransferModule =
  111. World.RequestModuleInterface<IMessageTransferModule>();
  112. m_UrlModule = World.RequestModuleInterface<IUrlModule>();
  113. m_comms = World.RequestModuleInterface<IWorldComm>();
  114. }
  115. public IScriptApi Copy()
  116. {
  117. return new LSL_Api();
  118. }
  119. public string Name
  120. {
  121. get { return "ll"; }
  122. }
  123. public string InterfaceName
  124. {
  125. get { return "ILSL_Api"; }
  126. }
  127. /// <summary>
  128. /// We don't have to add any assemblies here
  129. /// </summary>
  130. public string[] ReferencedAssemblies
  131. {
  132. get { return new string[0]; }
  133. }
  134. /// <summary>
  135. /// We use the default namespace, so we don't have any to add
  136. /// </summary>
  137. public string[] NamespaceAdditions
  138. {
  139. get { return new string[0]; }
  140. }
  141. public void Dispose()
  142. {
  143. }
  144. public override Object InitializeLifetimeService()
  145. {
  146. ILease lease = (ILease)base.InitializeLifetimeService();
  147. if (lease != null && lease.CurrentState == LeaseState.Initial)
  148. {
  149. lease.InitialLeaseTime = TimeSpan.FromMinutes(0);
  150. // lease.RenewOnCallTime = TimeSpan.FromSeconds(10.0);
  151. // lease.SponsorshipTimeout = TimeSpan.FromMinutes(1.0);
  152. }
  153. return lease;
  154. }
  155. protected virtual void ScriptSleep(int delay)
  156. {
  157. delay = (int)(delay * m_ScriptDelayFactor);
  158. if (delay == 0)
  159. return;
  160. Thread.Sleep(delay);
  161. }
  162. /// <summary>
  163. /// This is the new sleep implementation that allows for us to not freeze the script thread while we run
  164. /// </summary>
  165. /// <param name="delay"></param>
  166. /// <returns></returns>
  167. protected DateTime PScriptSleep(int delay)
  168. {
  169. double dly = (delay * m_ScriptDelayFactor);
  170. if (dly == 0.0)
  171. return DateTime.Now;
  172. DateTime timeToStopSleeping = DateTime.Now.AddMilliseconds(dly);
  173. return timeToStopSleeping;
  174. }
  175. public IScene World
  176. {
  177. get { return m_host.ParentEntity.Scene; }
  178. }
  179. public void state(string newState)
  180. {
  181. m_ScriptEngine.SetState(m_itemID, newState);
  182. throw new EventAbortException();
  183. }
  184. /// <summary>
  185. /// Reset the named script. The script must be present
  186. /// in the same prim.
  187. /// </summary>
  188. public void llResetScript()
  189. {
  190. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  191. if (m_UrlModule != null)
  192. {
  193. m_UrlModule.ScriptRemoved(m_itemID);
  194. }
  195. m_ScriptEngine.ResetScript(m_host.UUID, m_itemID, true);
  196. }
  197. public void llResetOtherScript(string name)
  198. {
  199. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  200. UUID item;
  201. if ((item = ScriptByName(name)) != UUID.Zero)
  202. m_ScriptEngine.ResetScript(m_host.UUID, item, false);
  203. else
  204. ShoutError("llResetOtherScript: script " + name + " not found");
  205. }
  206. public LSL_Integer llGetScriptState(string name)
  207. {
  208. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  209. return new LSL_Integer();
  210. UUID item;
  211. if ((item = ScriptByName(name)) != UUID.Zero)
  212. {
  213. return m_ScriptEngine.GetScriptRunningState(item) ? 1 : 0;
  214. }
  215. ShoutError("llGetScriptState: script " + name + " not found");
  216. // If we didn't find it, then it's safe to
  217. // assume it is not running.
  218. return 0;
  219. }
  220. public LSL_Key llGenerateKey()
  221. {
  222. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Key();
  223. return UUID.Random().ToString();
  224. }
  225. public void llSetScriptState(string name, int run)
  226. {
  227. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  228. UUID item;
  229. // These functions are supposed to be robust,
  230. // so get the state one step at a time.
  231. if ((item = ScriptByName(name)) != UUID.Zero)
  232. {
  233. m_ScriptEngine.SetScriptRunningState(item, run == 1);
  234. }
  235. else
  236. {
  237. ShoutError("llSetScriptState: script " + name + " not found");
  238. }
  239. }
  240. public List<ISceneChildEntity> GetLinkParts(int linkType)
  241. {
  242. List<ISceneChildEntity> ret = new List<ISceneChildEntity> { m_host };
  243. if (linkType == ScriptBaseClass.LINK_SET)
  244. {
  245. if (m_host.ParentEntity != null)
  246. return new List<ISceneChildEntity>(m_host.ParentEntity.ChildrenEntities());
  247. return ret;
  248. }
  249. if (linkType == ScriptBaseClass.LINK_ROOT)
  250. {
  251. if (m_host.ParentEntity != null)
  252. {
  253. ret = new List<ISceneChildEntity> { m_host.ParentEntity.RootChild };
  254. return ret;
  255. }
  256. return ret;
  257. }
  258. if (linkType == ScriptBaseClass.LINK_ALL_OTHERS)
  259. {
  260. if (m_host.ParentEntity == null)
  261. return new List<ISceneChildEntity>();
  262. ret = new List<ISceneChildEntity>(m_host.ParentEntity.ChildrenEntities());
  263. if (ret.Contains(m_host))
  264. ret.Remove(m_host);
  265. return ret;
  266. }
  267. if (linkType == ScriptBaseClass.LINK_ALL_CHILDREN)
  268. {
  269. if (m_host.ParentEntity == null)
  270. return new List<ISceneChildEntity>();
  271. ret = new List<ISceneChildEntity>(m_host.ParentEntity.ChildrenEntities());
  272. if (ret.Contains(m_host.ParentEntity.RootChild))
  273. ret.Remove(m_host.ParentEntity.RootChild);
  274. return ret;
  275. }
  276. if (linkType == ScriptBaseClass.LINK_THIS)
  277. {
  278. return ret;
  279. }
  280. if (linkType < 0 || m_host.ParentEntity == null)
  281. return new List<ISceneChildEntity>();
  282. IEntity target = m_host.ParentEntity.GetLinkNumPart(linkType);
  283. if (target is ISceneChildEntity)
  284. {
  285. ret = new List<ISceneChildEntity> { target as ISceneChildEntity };
  286. }
  287. //No allowing scene presences to be found here
  288. return ret;
  289. }
  290. public List<IEntity> GetLinkPartsAndEntities(int linkType)
  291. {
  292. List<IEntity> ret = new List<IEntity> { m_host };
  293. if (linkType == ScriptBaseClass.LINK_SET)
  294. {
  295. if (m_host.ParentEntity != null)
  296. {
  297. List<ISceneChildEntity> parts = new List<ISceneChildEntity>(m_host.ParentEntity.ChildrenEntities());
  298. #if (!ISWIN)
  299. return parts.ConvertAll<IEntity>(new Converter<ISceneChildEntity, IEntity>(delegate(ISceneChildEntity part)
  300. {
  301. return (IEntity)part;
  302. }));
  303. #else
  304. return parts.ConvertAll (part => (IEntity) part);
  305. #endif
  306. }
  307. return ret;
  308. }
  309. if (linkType == ScriptBaseClass.LINK_ROOT)
  310. {
  311. if (m_host.ParentEntity != null)
  312. {
  313. ret = new List<IEntity> { m_host.ParentEntity.RootChild };
  314. return ret;
  315. }
  316. return ret;
  317. }
  318. if (linkType == ScriptBaseClass.LINK_ALL_OTHERS)
  319. {
  320. if (m_host.ParentEntity == null)
  321. return new List<IEntity>();
  322. List<ISceneChildEntity> sceneobjectparts = new List<ISceneChildEntity>(m_host.ParentEntity.ChildrenEntities());
  323. #if (!ISWIN)
  324. ret = sceneobjectparts.ConvertAll<IEntity>(new Converter<ISceneChildEntity, IEntity>(delegate(ISceneChildEntity part)
  325. {
  326. return (IEntity)part;
  327. }));
  328. #else
  329. ret = sceneobjectparts.ConvertAll (part => (IEntity) part);
  330. #endif
  331. if (ret.Contains(m_host))
  332. ret.Remove(m_host);
  333. return ret;
  334. }
  335. if (linkType == ScriptBaseClass.LINK_ALL_CHILDREN)
  336. {
  337. if (m_host.ParentEntity == null)
  338. return new List<IEntity>();
  339. List<ISceneChildEntity> children = new List<ISceneChildEntity>(m_host.ParentEntity.ChildrenEntities());
  340. #if (!ISWIN)
  341. ret = children.ConvertAll<IEntity>(new Converter<ISceneChildEntity, IEntity>(delegate(ISceneChildEntity part)
  342. {
  343. return (IEntity)part;
  344. }));
  345. #else
  346. ret = children.ConvertAll (part => (IEntity) part);
  347. #endif
  348. if (ret.Contains(m_host.ParentEntity.RootChild))
  349. ret.Remove(m_host.ParentEntity.RootChild);
  350. return ret;
  351. }
  352. if (linkType == ScriptBaseClass.LINK_THIS)
  353. {
  354. return ret;
  355. }
  356. if (linkType < 0 || m_host.ParentEntity == null)
  357. return new List<IEntity>();
  358. IEntity target = m_host.ParentEntity.GetLinkNumPart(linkType);
  359. if (target == null)
  360. return new List<IEntity>();
  361. ret = new List<IEntity> { target };
  362. return ret;
  363. }
  364. protected UUID InventorySelf()
  365. {
  366. UUID invItemID = new UUID();
  367. lock (m_host.TaskInventory)
  368. {
  369. foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
  370. {
  371. if (inv.Value.Type == 10 && inv.Value.ItemID == m_itemID)
  372. {
  373. invItemID = inv.Key;
  374. break;
  375. }
  376. }
  377. }
  378. return invItemID;
  379. }
  380. protected UUID InventoryKey(string name, int type)
  381. {
  382. lock (m_host.TaskInventory)
  383. {
  384. foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
  385. {
  386. if (inv.Value.Name == name)
  387. {
  388. if (inv.Value.Type != type)
  389. return UUID.Zero;
  390. return inv.Value.AssetID;
  391. }
  392. }
  393. }
  394. return UUID.Zero;
  395. }
  396. protected UUID InventoryKey(string name, bool throwExceptionIfDoesNotExist)
  397. {
  398. lock (m_host.TaskInventory)
  399. {
  400. foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
  401. {
  402. if (inv.Value.Name == name)
  403. {
  404. return inv.Value.AssetID;
  405. }
  406. }
  407. }
  408. if (throwExceptionIfDoesNotExist)
  409. {
  410. IChatModule chatModule = World.RequestModuleInterface<IChatModule>();
  411. if (chatModule != null)
  412. chatModule.SimChat("Could not find sound '" + name + "'.",
  413. ChatTypeEnum.DebugChannel, 2147483647, m_host.AbsolutePosition,
  414. m_host.Name, m_host.UUID, false, World);
  415. }
  416. return UUID.Zero;
  417. }
  418. /// <summary>
  419. /// accepts a valid UUID, -or- a name of an inventory item.
  420. /// Returns a valid UUID or UUID.Zero if key invalid and item not found
  421. /// in prim inventory.
  422. /// </summary>
  423. /// <param name="k"></param>
  424. /// <param name="throwExceptionIfDoesNotExist"></param>
  425. /// <returns></returns>
  426. protected UUID KeyOrName(string k, bool throwExceptionIfDoesNotExist)
  427. {
  428. UUID key = UUID.Zero;
  429. // if we can parse the string as a key, use it.
  430. if (UUID.TryParse(k, out key))
  431. {
  432. return key;
  433. }
  434. // else try to locate the name in inventory of object. found returns key,
  435. // not found returns UUID.Zero which will translate to the default particle texture
  436. return InventoryKey(k, throwExceptionIfDoesNotExist);
  437. }
  438. // convert a LSL_Rotation to a Quaternion
  439. protected Quaternion Rot2Quaternion(LSL_Rotation r)
  440. {
  441. Quaternion q = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s);
  442. q.Normalize();
  443. return q;
  444. }
  445. //These are the implementations of the various ll-functions used by the LSL scripts.
  446. public LSL_Float llSin(double f)
  447. {
  448. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
  449. return Math.Sin(f);
  450. }
  451. public LSL_Float llCos(double f)
  452. {
  453. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
  454. return Math.Cos(f);
  455. }
  456. public LSL_Float llTan(double f)
  457. {
  458. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
  459. return Math.Tan(f);
  460. }
  461. public LSL_Float llAtan2(double x, double y)
  462. {
  463. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
  464. return Math.Atan2(x, y);
  465. }
  466. public LSL_Float llSqrt(double f)
  467. {
  468. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
  469. return Math.Sqrt(f);
  470. }
  471. public LSL_Float llPow(double fbase, double fexponent)
  472. {
  473. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
  474. return Math.Pow(fbase, fexponent);
  475. }
  476. public LSL_Integer llAbs(int i)
  477. {
  478. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Integer();
  479. // changed to replicate LSL behaviour whereby minimum int value is returned untouched.
  480. if (i == Int32.MinValue)
  481. return i;
  482. return Math.Abs(i);
  483. }
  484. public LSL_Float llFabs(double f)
  485. {
  486. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
  487. return Math.Abs(f);
  488. }
  489. public LSL_Float llFrand(double mag)
  490. {
  491. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
  492. lock (Util.RandomClass)
  493. {
  494. return Util.RandomClass.NextDouble() * mag;
  495. }
  496. }
  497. public LSL_Integer llFloor(double f)
  498. {
  499. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Integer();
  500. return (int)Math.Floor(f);
  501. }
  502. public LSL_Integer llCeil(double f)
  503. {
  504. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Integer();
  505. return (int)Math.Ceiling(f);
  506. }
  507. // Xantor 01/May/2008 fixed midpointrounding (2.5 becomes 3.0 instead of 2.0, default = ToEven)
  508. public LSL_Integer llRound(double f)
  509. {
  510. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Integer();
  511. double RoundedNumber = Math.Round(f, MidpointRounding.AwayFromZero);
  512. //Attempt to fix rounded numbers like -4.5 arounding away from zero
  513. if (f < 0)
  514. {
  515. if (f + 0.5 == RoundedNumber || f - 0.5 == RoundedNumber)
  516. {
  517. RoundedNumber += 1;
  518. }
  519. }
  520. return (int)RoundedNumber;
  521. }
  522. //This next group are vector operations involving squaring and square root. ckrinke
  523. public LSL_Float llVecMag(LSL_Vector v)
  524. {
  525. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
  526. return LSL_Vector.Mag(v);
  527. }
  528. public LSL_Vector llVecNorm(LSL_Vector v)
  529. {
  530. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
  531. return LSL_Vector.Norm(v);
  532. }
  533. public LSL_Float llVecDist(LSL_Vector a, LSL_Vector b)
  534. {
  535. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
  536. double dx = a.x - b.x;
  537. double dy = a.y - b.y;
  538. double dz = a.z - b.z;
  539. return Math.Sqrt(dx * dx + dy * dy + dz * dz);
  540. }
  541. //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke
  542. // Old implementation of llRot2Euler. Normalization not required as Atan2 function will
  543. // only return values >= -PI (-180 degrees) and <= PI (180 degrees).
  544. public LSL_Vector llRot2Euler(LSL_Rotation r)
  545. {
  546. //This implementation is from http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions. ckrinke
  547. LSL_Rotation t = new LSL_Rotation(r.x * r.x, r.y * r.y, r.z * r.z, r.s * r.s);
  548. double m = (t.x + t.y + t.z + t.s);
  549. if (m == 0) return new LSL_Vector();
  550. double n = 2 * (r.y * r.s + r.x * r.z);
  551. double p = m * m - n * n;
  552. if (p > 0)
  553. return new LSL_Vector(Math.Atan2(2.0 * (r.x * r.s - r.y * r.z), (-t.x - t.y + t.z + t.s)),
  554. Math.Atan2(n, Math.Sqrt(p)),
  555. Math.Atan2(2.0 * (r.z * r.s - r.x * r.y), (t.x - t.y - t.z + t.s)));
  556. if (n > 0)
  557. return new LSL_Vector(0.0, Math.PI * 0.5, Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z));
  558. return new LSL_Vector(0.0, -Math.PI * 0.5, Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z));
  559. }
  560. /* From wiki:
  561. The Euler angle vector (in radians) is converted to a rotation by doing the rotations around the 3 axes
  562. in Z, Y, X order. So llEuler2Rot(<1.0, 2.0, 3.0> * DEG_TO_RAD) generates a rotation by taking the zero rotation,
  563. a vector pointing along the X axis, first rotating it 3 degrees around the global Z axis, then rotating the resulting
  564. vector 2 degrees around the global Y axis, and finally rotating that 1 degree around the global X axis.
  565. */
  566. /* How we arrived at this llEuler2Rot
  567. *
  568. * Experiment in SL to determine conventions:
  569. * llEuler2Rot(<PI,0,0>)=<1,0,0,0>
  570. * llEuler2Rot(<0,PI,0>)=<0,1,0,0>
  571. * llEuler2Rot(<0,0,PI>)=<0,0,1,0>
  572. *
  573. * Important facts about Quaternions
  574. * - multiplication is non-commutative (a*b != b*a)
  575. * - http://en.wikipedia.org/wiki/Quaternion#Basis_multiplication
  576. *
  577. * Above SL experiment gives (c1,c2,c3,s1,s2,s3 as defined in our llEuler2Rot):
  578. * Qx = c1+i*s1
  579. * Qy = c2+j*s2;
  580. * Qz = c3+k*s3;
  581. *
  582. * Rotations applied in order (from above) Z, Y, X
  583. * Q = (Qz * Qy) * Qx
  584. * ((c1+i*s1)*(c2+j*s2))*(c3+k*s3)
  585. * (c1*c2+i*s1*c2+j*c1*s2+ij*s1*s2)*(c3+k*s3)
  586. * (c1*c2+i*s1*c2+j*c1*s2+k*s1*s2)*(c3+k*s3)
  587. * c1*c2*c3+i*s1*c2*c3+j*c1*s2*c3+k*s1*s2*c3+k*c1*c2*s3+ik*s1*c2*s3+jk*c1*s2*s3+kk*s1*s2*s3
  588. * c1*c2*c3+i*s1*c2*c3+j*c1*s2*c3+k*s1*s2*c3+k*c1*c2*s3 -j*s1*c2*s3 +i*c1*s2*s3 -s1*s2*s3
  589. * regroup: x=i*(s1*c2*c3+c1*s2*s3)
  590. * y=j*(c1*s2*c3-s1*c2*s3)
  591. * z=k*(s1*s2*c3+c1*c2*s3)
  592. * s= c1*c2*c3-s1*s2*s3
  593. *
  594. * This implementation agrees with the functions found here:
  595. * http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions
  596. * And with the results in SL.
  597. *
  598. * It's also possible to calculate llEuler2Rot by direct multiplication of
  599. * the Qz, Qy, and Qx vectors (as above - and done in the "accurate" function
  600. * from the wiki).
  601. * Apparently in some cases this is better from a numerical precision perspective?
  602. */
  603. public LSL_Rotation llEuler2Rot(LSL_Vector v)
  604. {
  605. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Rotation();
  606. double c1 = Math.Cos(v.x * 0.5);
  607. double c2 = Math.Cos(v.y * 0.5);
  608. double c3 = Math.Cos(v.z * 0.5);
  609. double s1 = Math.Sin(v.x * 0.5);
  610. double s2 = Math.Sin(v.y * 0.5);
  611. double s3 = Math.Sin(v.z * 0.5);
  612. double x = s1 * c2 * c3 + c1 * s2 * s3;
  613. double y = c1 * s2 * c3 - s1 * c2 * s3;
  614. double z = s1 * s2 * c3 + c1 * c2 * s3;
  615. double s = c1 * c2 * c3 - s1 * s2 * s3;
  616. return new LSL_Rotation(x, y, z, s);
  617. }
  618. public LSL_Rotation llAxes2Rot(LSL_Vector fwd, LSL_Vector left, LSL_Vector up)
  619. {
  620. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Rotation();
  621. double s;
  622. double tr = fwd.x + left.y + up.z + 1.0;
  623. if (tr >= 1.0)
  624. {
  625. s = 0.5 / Math.Sqrt(tr);
  626. return new LSL_Rotation(
  627. (left.z - up.y) * s,
  628. (up.x - fwd.z) * s,
  629. (fwd.y - left.x) * s,
  630. 0.25 / s);
  631. }
  632. double max = (left.y > up.z) ? left.y : up.z;
  633. if (max < fwd.x)
  634. {
  635. s = Math.Sqrt(fwd.x - (left.y + up.z) + 1.0);
  636. double x = s * 0.5;
  637. s = 0.5 / s;
  638. return new LSL_Rotation(
  639. x,
  640. (fwd.y + left.x) * s,
  641. (up.x + fwd.z) * s,
  642. (left.z - up.y) * s);
  643. }
  644. if (max == left.y)
  645. {
  646. s = Math.Sqrt(left.y - (up.z + fwd.x) + 1.0);
  647. double y = s * 0.5;
  648. s = 0.5 / s;
  649. return new LSL_Rotation(
  650. (fwd.y + left.x) * s,
  651. y,
  652. (left.z + up.y) * s,
  653. (up.x - fwd.z) * s);
  654. }
  655. s = Math.Sqrt(up.z - (fwd.x + left.y) + 1.0);
  656. double z = s * 0.5;
  657. s = 0.5 / s;
  658. return new LSL_Rotation(
  659. (up.x + fwd.z) * s,
  660. (left.z + up.y) * s,
  661. z,
  662. (fwd.y - left.x) * s);
  663. }
  664. public LSL_Vector llRot2Fwd(LSL_Rotation r)
  665. {
  666. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  667. return new LSL_Vector();
  668. double m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s;
  669. // m is always greater than zero
  670. // if m is not equal to 1 then Rotation needs to be normalized
  671. if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision
  672. {
  673. m = 1.0 / Math.Sqrt(m);
  674. r.x *= m;
  675. r.y *= m;
  676. r.z *= m;
  677. r.s *= m;
  678. }
  679. // Fast Algebric Calculations instead of Vectors & Quaternions Product
  680. double x = r.x * r.x - r.y * r.y - r.z * r.z + r.s * r.s;
  681. double y = 2 * (r.x * r.y + r.z * r.s);
  682. double z = 2 * (r.x * r.z - r.y * r.s);
  683. return (new LSL_Vector(x, y, z));
  684. }
  685. public LSL_Vector llRot2Left(LSL_Rotation r)
  686. {
  687. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
  688. double m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s;
  689. // m is always greater than zero
  690. // if m is not equal to 1 then Rotation needs to be normalized
  691. if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision
  692. {
  693. m = 1.0 / Math.Sqrt(m);
  694. r.x *= m;
  695. r.y *= m;
  696. r.z *= m;
  697. r.s *= m;
  698. }
  699. // Fast Algebric Calculations instead of Vectors & Quaternions Product
  700. double x = 2 * (r.x * r.y - r.z * r.s);
  701. double y = -r.x * r.x + r.y * r.y - r.z * r.z + r.s * r.s;
  702. double z = 2 * (r.x * r.s + r.y * r.z);
  703. return (new LSL_Vector(x, y, z));
  704. }
  705. public LSL_Vector llRot2Up(LSL_Rotation r)
  706. {
  707. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
  708. double m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s;
  709. // m is always greater than zero
  710. // if m is not equal to 1 then Rotation needs to be normalized
  711. if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision
  712. {
  713. m = 1.0 / Math.Sqrt(m);
  714. r.x *= m;
  715. r.y *= m;
  716. r.z *= m;
  717. r.s *= m;
  718. }
  719. // Fast Algebric Calculations instead of Vectors & Quaternions Product
  720. double x = 2 * (r.x * r.z + r.y * r.s);
  721. double y = 2 * (-r.x * r.s + r.y * r.z);
  722. double z = -r.x * r.x - r.y * r.y + r.z * r.z + r.s * r.s;
  723. return (new LSL_Vector(x, y, z));
  724. }
  725. public LSL_Rotation llRotBetween(LSL_Vector a, LSL_Vector b)
  726. {
  727. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Rotation();
  728. //A and B should both be normalized
  729. LSL_Rotation rotBetween;
  730. // Check for zero vectors. If either is zero, return zero rotation. Otherwise,
  731. // continue calculation.
  732. if (a == new LSL_Vector(0.0f, 0.0f, 0.0f) || b == new LSL_Vector(0.0f, 0.0f, 0.0f))
  733. {
  734. rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
  735. }
  736. else
  737. {
  738. a = LSL_Vector.Norm(a);
  739. b = LSL_Vector.Norm(b);
  740. double dotProduct = LSL_Vector.Dot(a, b);
  741. // There are two degenerate cases possible. These are for vectors 180 or
  742. // 0 degrees apart. These have to be detected and handled individually.
  743. //
  744. // Check for vectors 180 degrees apart.
  745. // A dot product of -1 would mean the angle between vectors is 180 degrees.
  746. if (dotProduct < -0.9999999f)
  747. {
  748. // First assume X axis is orthogonal to the vectors.
  749. LSL_Vector orthoVector = new LSL_Vector(1.0f, 0.0f, 0.0f);
  750. orthoVector = orthoVector - a * (a.x / LSL_Vector.Dot(a, a));
  751. // Check for near zero vector. A very small non-zero number here will create
  752. // a rotation in an undesired direction.
  753. rotBetween = LSL_Vector.Mag(orthoVector) > 0.0001 ? new LSL_Rotation(orthoVector.x, orthoVector.y, orthoVector.z, 0.0f) : new LSL_Rotation(0.0f, 0.0f, 1.0f, 0.0f);
  754. }
  755. // Check for parallel vectors.
  756. // A dot product of 1 would mean the angle between vectors is 0 degrees.
  757. else if (dotProduct > 0.9999999f)
  758. {
  759. // Set zero rotation.
  760. rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
  761. }
  762. else
  763. {
  764. // All special checks have been performed so get the axis of rotation.
  765. LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
  766. // Quarternion s value is the length of the unit vector + dot product.
  767. double qs = 1.0 + dotProduct;
  768. rotBetween = new LSL_Rotation(crossProduct.x, crossProduct.y, crossProduct.z, qs);
  769. // Normalize the rotation.
  770. double mag = LSL_Rotation.Mag(rotBetween);
  771. // We shouldn't have to worry about a divide by zero here. The qs value will be
  772. // non-zero because we already know if we're here, then the dotProduct is not -1 so
  773. // qs will not be zero. Also, we've already handled the input vectors being zero so the
  774. // crossProduct vector should also not be zero.
  775. rotBetween.x = rotBetween.x / mag;
  776. rotBetween.y = rotBetween.y / mag;
  777. rotBetween.z = rotBetween.z / mag;
  778. rotBetween.s = rotBetween.s / mag;
  779. // Check for undefined values and set zero rotation if any found. This code might not actually be required
  780. // any longer since zero vectors are checked for at the top.
  781. if (Double.IsNaN(rotBetween.x) || Double.IsNaN(rotBetween.y) || Double.IsNaN(rotBetween.z) || Double.IsNaN(rotBetween.s))
  782. {
  783. rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
  784. }
  785. }
  786. }
  787. return rotBetween;
  788. }
  789. public void llWhisper(int channelID, string text)
  790. {
  791. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  792. if (text.Length > 1023)
  793. text = text.Substring(0, 1023);
  794. IChatModule chatModule = World.RequestModuleInterface<IChatModule>();
  795. if (chatModule != null)
  796. chatModule.SimChat(text, ChatTypeEnum.Whisper, channelID,
  797. m_host.ParentEntity.RootChild.AbsolutePosition, m_host.Name, m_host.UUID, false, World);
  798. if (m_comms != null)
  799. m_comms.DeliverMessage(ChatTypeEnum.Whisper, channelID, m_host.Name, m_host.UUID, text);
  800. }
  801. public void llSay(int channelID, object m_text)
  802. {
  803. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  804. string text = m_text.ToString();
  805. if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel))
  806. {
  807. Console.WriteLine(text);
  808. }
  809. else
  810. {
  811. if (text.Length > 1023)
  812. text = text.Substring(0, 1023);
  813. IChatModule chatModule = World.RequestModuleInterface<IChatModule>();
  814. if (chatModule != null)
  815. chatModule.SimChat(text, ChatTypeEnum.Say, channelID,
  816. m_host.ParentEntity.RootChild.AbsolutePosition, m_host.Name, m_host.UUID, false, World);
  817. if (m_comms != null)
  818. m_comms.DeliverMessage(ChatTypeEnum.Say, channelID, m_host.Name, m_host.UUID, text);
  819. }
  820. }
  821. public void llShout(int channelID, string text)
  822. {
  823. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  824. if (text.Length > 1023)
  825. text = text.Substring(0, 1023);
  826. IChatModule chatModule = World.RequestModuleInterface<IChatModule>();
  827. if (chatModule != null)
  828. chatModule.SimChat(text, ChatTypeEnum.Shout, channelID,
  829. m_host.ParentEntity.RootChild.AbsolutePosition, m_host.Name, m_host.UUID, true, World);
  830. if (m_comms != null)
  831. m_comms.DeliverMessage(ChatTypeEnum.Shout, channelID, m_host.Name, m_host.UUID, text);
  832. }
  833. public void llRegionSay(int channelID, string text)
  834. {
  835. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  836. if (text.Length > 1023)
  837. text = text.Substring(0, 1023);
  838. if (channelID == 0) //0 isn't normally allowed, so check against a higher threat level
  839. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.Moderate, "LSL", m_host, "LSL", m_itemID)) return;
  840. IChatModule chatModule = World.RequestModuleInterface<IChatModule>();
  841. if (chatModule != null)
  842. chatModule.SimChat(text, ChatTypeEnum.Region, channelID,
  843. m_host.ParentEntity.RootChild.AbsolutePosition, m_host.Name, m_host.UUID, false, World);
  844. if (m_comms != null)
  845. m_comms.DeliverMessage(ChatTypeEnum.Region, channelID, m_host.Name, m_host.UUID, text);
  846. }
  847. public void llRegionSayTo(LSL_Key toID, int channelID, string text)
  848. {
  849. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  850. IChatModule chatModule = World.RequestModuleInterface<IChatModule>();
  851. if (text.Length > 1023)
  852. text = text.Substring(0, 1023);
  853. if (channelID == 0)
  854. {
  855. IScenePresence presence = World.GetScenePresence(UUID.Parse(toID.m_string));
  856. if (presence != null)
  857. {
  858. if (chatModule != null)
  859. chatModule.TrySendChatMessage(presence, m_host.AbsolutePosition, m_host.AbsolutePosition,
  860. m_host.UUID, m_host.Name, ChatTypeEnum.Say, text, ChatSourceType.Object, 10000);
  861. }
  862. }
  863. if (m_comms != null)
  864. m_comms.DeliverMessage(ChatTypeEnum.Region, channelID, m_host.Name, m_host.UUID, UUID.Parse(toID.m_string), text);
  865. }
  866. public LSL_Integer llListen(int channelID, string name, string ID, string msg)
  867. {
  868. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Integer();
  869. UUID keyID;
  870. UUID.TryParse(ID, out keyID);
  871. if (m_comms != null)
  872. return m_comms.Listen(m_itemID, m_host.UUID, channelID, name, keyID, msg);
  873. return -1;
  874. }
  875. public void llListenControl(int number, int active)
  876. {
  877. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  878. if (m_comms != null)
  879. m_comms.ListenControl(m_itemID, number, active);
  880. }
  881. public void llListenRemove(int number)
  882. {
  883. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  884. if (m_comms != null)
  885. m_comms.ListenRemove(m_itemID, number);
  886. }
  887. public void llSensor(string name, string id, int type, double range, double arc)
  888. {
  889. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  890. UUID keyID = UUID.Zero;
  891. UUID.TryParse(id, out keyID);
  892. SensorRepeatPlugin sensorPlugin = (SensorRepeatPlugin)m_ScriptEngine.GetScriptPlugin("SensorRepeat");
  893. sensorPlugin.SenseOnce(m_host.UUID, m_itemID, name, keyID, type, range, arc, m_host);
  894. }
  895. public void llSensorRepeat(string name, string id, int type, double range, double arc, double rate)
  896. {
  897. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  898. UUID keyID = UUID.Zero;
  899. UUID.TryParse(id, out keyID);
  900. SensorRepeatPlugin sensorPlugin = (SensorRepeatPlugin)m_ScriptEngine.GetScriptPlugin("SensorRepeat");
  901. sensorPlugin.SetSenseRepeatEvent(m_host.UUID, m_itemID, name, keyID, type, range, arc, rate, m_host);
  902. }
  903. public void llSensorRemove()
  904. {
  905. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  906. SensorRepeatPlugin sensorPlugin = (SensorRepeatPlugin)m_ScriptEngine.GetScriptPlugin("SensorRepeat");
  907. sensorPlugin.RemoveScript(m_host.UUID, m_itemID);
  908. }
  909. public string resolveName(UUID objecUUID)
  910. {
  911. // try avatar username surname
  912. UserAccount account = World.UserAccountService.GetUserAccount(World.RegionInfo.AllScopeIDs, objecUUID);
  913. if (account != null)
  914. return account.Name;
  915. // try an scene object
  916. ISceneChildEntity SOP = World.GetSceneObjectPart(objecUUID);
  917. if (SOP != null)
  918. return SOP.Name;
  919. IEntity SensedObject;
  920. if (!World.Entities.TryGetValue(objecUUID, out SensedObject))
  921. {
  922. IGroupsModule groups = World.RequestModuleInterface<IGroupsModule>();
  923. if (groups != null)
  924. {
  925. GroupRecord gr = groups.GetGroupRecord(objecUUID);
  926. if (gr != null)
  927. return gr.GroupName;
  928. }
  929. return String.Empty;
  930. }
  931. return SensedObject.Name;
  932. }
  933. public LSL_String llDetectedName(int number)
  934. {
  935. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_String();
  936. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, number);
  937. if (detectedParams == null)
  938. return String.Empty;
  939. return detectedParams.Name;
  940. }
  941. public LSL_String llDetectedKey(int number)
  942. {
  943. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_String();
  944. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, number);
  945. if (detectedParams == null)
  946. return String.Empty;
  947. return detectedParams.Key.ToString();
  948. }
  949. public LSL_String llDetectedOwner(int number)
  950. {
  951. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_String();
  952. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, number);
  953. if (detectedParams == null)
  954. return String.Empty;
  955. return detectedParams.Owner.ToString();
  956. }
  957. public LSL_Integer llDetectedType(int number)
  958. {
  959. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Integer();
  960. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, number);
  961. if (detectedParams == null)
  962. return 0;
  963. return new LSL_Integer(detectedParams.Type);
  964. }
  965. public LSL_Vector llDetectedPos(int number)
  966. {
  967. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
  968. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, number);
  969. if (detectedParams == null)
  970. return new LSL_Vector();
  971. return detectedParams.Position;
  972. }
  973. public LSL_Vector llDetectedVel(int number)
  974. {
  975. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
  976. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, number);
  977. if (detectedParams == null)
  978. return new LSL_Vector();
  979. return detectedParams.Velocity;
  980. }
  981. public LSL_Vector llDetectedGrab(int number)
  982. {
  983. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
  984. DetectParams parms = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, number);
  985. if (parms == null)
  986. return new LSL_Vector(0, 0, 0);
  987. return parms.OffsetPos;
  988. }
  989. public LSL_Rotation llDetectedRot(int number)
  990. {
  991. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Rotation();
  992. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, number);
  993. if (detectedParams == null)
  994. return new LSL_Rotation();
  995. return detectedParams.Rotation;
  996. }
  997. public LSL_Integer llDetectedGroup(int number)
  998. {
  999. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Integer();
  1000. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, number);
  1001. if (detectedParams == null)
  1002. return new LSL_Integer(0);
  1003. if (m_host.GroupID == detectedParams.Group)
  1004. return new LSL_Integer(1);
  1005. return new LSL_Integer(0);
  1006. }
  1007. public LSL_Integer llDetectedLinkNumber(int number)
  1008. {
  1009. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Integer();
  1010. DetectParams parms = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, number);
  1011. if (parms == null)
  1012. return new LSL_Integer(0);
  1013. return new LSL_Integer(parms.LinkNum);
  1014. }
  1015. /// <summary>
  1016. /// See http://wiki.secondlife.com/wiki/LlDetectedTouchBinormal for details
  1017. /// </summary>
  1018. public LSL_Vector llDetectedTouchBinormal(int index)
  1019. {
  1020. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
  1021. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, index);
  1022. if (detectedParams == null)
  1023. return new LSL_Vector();
  1024. return detectedParams.TouchBinormal;
  1025. }
  1026. /// <summary>
  1027. /// See http://wiki.secondlife.com/wiki/LlDetectedTouchFace for details
  1028. /// </summary>
  1029. public LSL_Integer llDetectedTouchFace(int index)
  1030. {
  1031. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Integer();
  1032. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, index);
  1033. if (detectedParams == null)
  1034. return new LSL_Integer(-1);
  1035. return new LSL_Integer(detectedParams.TouchFace);
  1036. }
  1037. /// <summary>
  1038. /// See http://wiki.secondlife.com/wiki/LlDetectedTouchNormal for details
  1039. /// </summary>
  1040. public LSL_Vector llDetectedTouchNormal(int index)
  1041. {
  1042. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
  1043. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, index);
  1044. if (detectedParams == null)
  1045. return new LSL_Vector();
  1046. return detectedParams.TouchNormal;
  1047. }
  1048. /// <summary>
  1049. /// See http://wiki.secondlife.com/wiki/LlDetectedTouchPos for details
  1050. /// </summary>
  1051. public LSL_Vector llDetectedTouchPos(int index)
  1052. {
  1053. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
  1054. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, index);
  1055. if (detectedParams == null)
  1056. return new LSL_Vector();
  1057. return detectedParams.TouchPos;
  1058. }
  1059. /// <summary>
  1060. /// See http://wiki.secondlife.com/wiki/LlDetectedTouchST for details
  1061. /// </summary>
  1062. public LSL_Vector llDetectedTouchST(int index)
  1063. {
  1064. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
  1065. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, index);
  1066. if (detectedParams == null)
  1067. return new LSL_Vector(-1.0, -1.0, 0.0);
  1068. return detectedParams.TouchST;
  1069. }
  1070. /// <summary>
  1071. /// See http://wiki.secondlife.com/wiki/LlDetectedTouchUV for details
  1072. /// </summary>
  1073. public LSL_Vector llDetectedTouchUV(int index)
  1074. {
  1075. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
  1076. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, index);
  1077. if (detectedParams == null)
  1078. return new LSL_Vector(-1.0, -1.0, 0.0);
  1079. return detectedParams.TouchUV;
  1080. }
  1081. public virtual void llDie()
  1082. {
  1083. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  1084. throw new SelfDeleteException();
  1085. }
  1086. public LSL_Float llGround(LSL_Vector offset)
  1087. {
  1088. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
  1089. Vector3 pos = m_host.GetWorldPosition() + new Vector3((float)offset.x,
  1090. (float)offset.y,
  1091. (float)offset.z);
  1092. //Get the slope normal. This gives us the equation of the plane tangent to the slope.
  1093. LSL_Vector vsn = llGroundNormal(offset);
  1094. ITerrainChannel heightmap = World.RequestModuleInterface<ITerrainChannel>();
  1095. // Clamp to valid position
  1096. if (pos.X < 0)
  1097. pos.X = 0;
  1098. else if (pos.X >= heightmap.Width)
  1099. pos.X = heightmap.Width - 1;
  1100. if (pos.Y < 0)
  1101. pos.Y = 0;
  1102. else if (pos.Y >= heightmap.Height)
  1103. pos.Y = heightmap.Height - 1;
  1104. //Get the height for the integer coordinates from the Heightmap
  1105. float baseheight = heightmap[(int)pos.X, (int)pos.Y];
  1106. //Calculate the difference between the actual coordinates and the integer coordinates
  1107. float xdiff = pos.X - (int)pos.X;
  1108. float ydiff = pos.Y - (int)pos.Y;
  1109. //Use the equation of the tangent plane to adjust the height to account for slope
  1110. return (((vsn.x * xdiff) + (vsn.y * ydiff)) / (-1 * vsn.z)) + baseheight;
  1111. }
  1112. public LSL_Float llCloud(LSL_Vector offset)
  1113. {
  1114. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
  1115. float cloudCover = 0f;
  1116. ICloudModule module = World.RequestModuleInterface<ICloudModule>();
  1117. if (module != null)
  1118. {
  1119. Vector3 pos = m_host.GetWorldPosition();
  1120. int x = (int)(pos.X + offset.x);
  1121. int y = (int)(pos.Y + offset.y);
  1122. cloudCover = module.CloudCover(x, y, 0);
  1123. }
  1124. return cloudCover;
  1125. }
  1126. public LSL_Vector llWind(LSL_Vector offset)
  1127. {
  1128. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
  1129. LSL_Vector wind = new LSL_Vector(0, 0, 0);
  1130. IWindModule module = World.RequestModuleInterface<IWindModule>();
  1131. if (module != null)
  1132. {
  1133. Vector3 pos = m_host.GetWorldPosition();
  1134. int x = (int)(pos.X + offset.x);
  1135. int y = (int)(pos.Y + offset.y);
  1136. Vector3 windSpeed = module.WindSpeed(x, y, 0);
  1137. wind.x = windSpeed.X;
  1138. wind.y = windSpeed.Y;
  1139. }
  1140. return wind;
  1141. }
  1142. public void llSetStatus(int status, int value)
  1143. {
  1144. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  1145. int statusrotationaxis = 0;
  1146. if ((status & ScriptBaseClass.STATUS_PHYSICS) == ScriptBaseClass.STATUS_PHYSICS)
  1147. {
  1148. if (value != 0)
  1149. {
  1150. ISceneEntity group = m_host.ParentEntity;
  1151. if (group == null)
  1152. return;
  1153. #if (!ISWIN)
  1154. bool allow = true;
  1155. foreach (ISceneChildEntity part in group.ChildrenEntities())
  1156. {
  1157. IOpenRegionSettingsModule WSModule = group.Scene.RequestModuleInterface<IOpenRegionSettingsModule>();
  1158. if (WSModule != null && WSModule.MaximumPhysPrimScale != -1)
  1159. {
  1160. Vector3 tmp = part.Scale;
  1161. if (tmp.X > WSModule.MaximumPhysPrimScale ||
  1162. tmp.Y > WSModule.MaximumPhysPrimScale ||
  1163. tmp.Z > WSModule.MaximumPhysPrimScale)
  1164. {
  1165. allow = false;
  1166. break;
  1167. }
  1168. }
  1169. }
  1170. #else
  1171. bool allow = !(from part in @group.ChildrenEntities()
  1172. let WSModule = @group.Scene.RequestModuleInterface<IOpenRegionSettingsModule>()
  1173. where WSModule != null && WSModule.MaximumPhysPrimScale != -1
  1174. let tmp = part.Scale
  1175. where
  1176. tmp.X > WSModule.MaximumPhysPrimScale || tmp.Y > WSModule.MaximumPhysPrimScale ||
  1177. tmp.Z > WSModule.MaximumPhysPrimScale
  1178. select WSModule).Any();
  1179. #endif
  1180. if (!allow)
  1181. return;
  1182. ((SceneObjectGroup)m_host.ParentEntity).ScriptSetPhysicsStatus(true);
  1183. }
  1184. else
  1185. {
  1186. ((SceneObjectGroup)m_host.ParentEntity).ScriptSetPhysicsStatus(false);
  1187. }
  1188. }
  1189. if ((status & ScriptBaseClass.STATUS_PHANTOM) == ScriptBaseClass.STATUS_PHANTOM)
  1190. {
  1191. m_host.ScriptSetPhantomStatus(value != 0);
  1192. }
  1193. if ((status & ScriptBaseClass.STATUS_CAST_SHADOWS) == ScriptBaseClass.STATUS_CAST_SHADOWS)
  1194. {
  1195. m_host.AddFlag(PrimFlags.CastShadows);
  1196. }
  1197. if ((status & ScriptBaseClass.STATUS_ROTATE_X) == ScriptBaseClass.STATUS_ROTATE_X)
  1198. {
  1199. statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_X;
  1200. }
  1201. if ((status & ScriptBaseClass.STATUS_ROTATE_Y) == ScriptBaseClass.STATUS_ROTATE_Y)
  1202. {
  1203. statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_Y;
  1204. }
  1205. if ((status & ScriptBaseClass.STATUS_ROTATE_Z) == ScriptBaseClass.STATUS_ROTATE_Z)
  1206. {
  1207. statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_Z;
  1208. }
  1209. if ((status & ScriptBaseClass.STATUS_BLOCK_GRAB) == ScriptBaseClass.STATUS_BLOCK_GRAB)
  1210. {
  1211. m_host.SetBlockGrab(value != 0, false);
  1212. }
  1213. if ((status & ScriptBaseClass.STATUS_BLOCK_GRAB_OBJECT) == ScriptBaseClass.STATUS_BLOCK_GRAB_OBJECT)
  1214. {
  1215. m_host.SetBlockGrab(value != 0, true);
  1216. }
  1217. if ((status & ScriptBaseClass.STATUS_DIE_AT_EDGE) == ScriptBaseClass.STATUS_DIE_AT_EDGE)
  1218. {
  1219. m_host.SetDieAtEdge(value != 0);
  1220. }
  1221. if ((status & ScriptBaseClass.STATUS_RETURN_AT_EDGE) == ScriptBaseClass.STATUS_RETURN_AT_EDGE)
  1222. {
  1223. m_host.SetReturnAtEdge(value != 0);
  1224. }
  1225. if ((status & ScriptBaseClass.STATUS_SANDBOX) == ScriptBaseClass.STATUS_SANDBOX)
  1226. {
  1227. m_host.SetStatusSandbox(value != 0);
  1228. }
  1229. if (statusrotationaxis != 0)
  1230. {
  1231. m_host.SetAxisRotation(statusrotationaxis, value);
  1232. }
  1233. }
  1234. public LSL_Integer llGetStatus(int status)
  1235. {
  1236. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Integer();
  1237. if (status == ScriptBaseClass.STATUS_PHYSICS)
  1238. {
  1239. return (m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Physics) == (uint)PrimFlags.Physics ? new LSL_Integer(1) : new LSL_Integer(0);
  1240. }
  1241. if (status == ScriptBaseClass.STATUS_PHANTOM)
  1242. {
  1243. return (m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) == (uint)PrimFlags.Phantom ? new LSL_Integer(1) : new LSL_Integer(0);
  1244. }
  1245. if (status == ScriptBaseClass.STATUS_CAST_SHADOWS)
  1246. {
  1247. if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.CastShadows) == (uint)PrimFlags.CastShadows)
  1248. return new LSL_Integer(1);
  1249. return new LSL_Integer(0);
  1250. }
  1251. if (status == ScriptBaseClass.STATUS_BLOCK_GRAB)
  1252. {
  1253. return m_host.GetBlockGrab(false) ? new LSL_Integer(1) : new LSL_Integer(0);
  1254. }
  1255. if (status == ScriptBaseClass.STATUS_BLOCK_GRAB_OBJECT)
  1256. {
  1257. return m_host.GetBlockGrab(true) ? new LSL_Integer(1) : new LSL_Integer(0);
  1258. }
  1259. if (status == ScriptBaseClass.STATUS_DIE_AT_EDGE)
  1260. {
  1261. return m_host.GetDieAtEdge() ? new LSL_Integer(1) : new LSL_Integer(0);
  1262. }
  1263. if (status == ScriptBaseClass.STATUS_RETURN_AT_EDGE)
  1264. {
  1265. return m_host.GetReturnAtEdge() ? new LSL_Integer(1) : new LSL_Integer(0);
  1266. }
  1267. if (status == ScriptBaseClass.STATUS_ROTATE_X)
  1268. {
  1269. return m_host.GetAxisRotation(2) == 2 ? new LSL_Integer(1) : new LSL_Integer(0);
  1270. }
  1271. if (status == ScriptBaseClass.STATUS_ROTATE_Y)
  1272. {
  1273. return m_host.GetAxisRotation(4) == 4 ? new LSL_Integer(1) : new LSL_Integer(0);
  1274. }
  1275. if (status == ScriptBaseClass.STATUS_ROTATE_Z)
  1276. {
  1277. return m_host.GetAxisRotation(8) == 8 ? new LSL_Integer(1) : new LSL_Integer(0);
  1278. }
  1279. if (status == ScriptBaseClass.STATUS_SANDBOX)
  1280. {
  1281. return m_host.GetStatusSandbox() ? new LSL_Integer(1) : new LSL_Integer(0);
  1282. }
  1283. return new LSL_Integer(0);
  1284. }
  1285. public void llSetScale(LSL_Vector scale)
  1286. {
  1287. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  1288. SetScale(m_host, scale);
  1289. }
  1290. protected void SetScale(ISceneChildEntity part, LSL_Vector scale)
  1291. {
  1292. if (part == null || part.ParentEntity == null || part.ParentEntity.IsDeleted)
  1293. return;
  1294. IOpenRegionSettingsModule WSModule = m_host.ParentEntity.Scene.RequestModuleInterface<IOpenRegionSettingsModule>();
  1295. if (WSModule != null)
  1296. {
  1297. if (WSModule.MinimumPrimScale != -1)
  1298. {
  1299. if (scale.x < WSModule.MinimumPrimScale)
  1300. scale.x = WSModule.MinimumPrimScale;
  1301. if (scale.y < WSModule.MinimumPrimScale)
  1302. scale.y = WSModule.MinimumPrimScale;
  1303. if (scale.z < WSModule.MinimumPrimScale)
  1304. scale.z = WSModule.MinimumPrimScale;
  1305. }
  1306. if (part.ParentEntity.RootChild.PhysActor != null && part.ParentEntity.RootChild.PhysActor.IsPhysical &&
  1307. WSModule.MaximumPhysPrimScale != -1)
  1308. {
  1309. if (scale.x > WSModule.MaximumPhysPrimScale)
  1310. scale.x = WSModule.MaximumPhysPrimScale;
  1311. if (scale.y > WSModule.MaximumPhysPrimScale)
  1312. scale.y = WSModule.MaximumPhysPrimScale;
  1313. if (scale.z > WSModule.MaximumPhysPrimScale)
  1314. scale.z = WSModule.MaximumPhysPrimScale;
  1315. }
  1316. if (WSModule.MaximumPrimScale != -1)
  1317. {
  1318. if (scale.x > WSModule.MaximumPrimScale)
  1319. scale.x = WSModule.MaximumPrimScale;
  1320. if (scale.y > WSModule.MaximumPrimScale)
  1321. scale.y = WSModule.MaximumPrimScale;
  1322. if (scale.z > WSModule.MaximumPrimScale)
  1323. scale.z = WSModule.MaximumPrimScale;
  1324. }
  1325. }
  1326. Vector3 tmp = part.Scale;
  1327. tmp.X = (float)scale.x;
  1328. tmp.Y = (float)scale.y;
  1329. tmp.Z = (float)scale.z;
  1330. part.Scale = tmp;
  1331. part.ScheduleUpdate(PrimUpdateFlags.FindBest);
  1332. }
  1333. public LSL_Vector llGetScale()
  1334. {
  1335. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
  1336. Vector3 tmp = m_host.Scale;
  1337. return new LSL_Vector(tmp.X, tmp.Y, tmp.Z);
  1338. }
  1339. public void llSetClickAction(int action)
  1340. {
  1341. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  1342. m_host.ClickAction = (byte)action;
  1343. m_host.ScheduleUpdate(PrimUpdateFlags.FindBest);
  1344. }
  1345. public void llSetColor(LSL_Vector color, int face)
  1346. {
  1347. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  1348. if (face == ScriptBaseClass.ALL_SIDES)
  1349. face = SceneObjectPart.ALL_SIDES;
  1350. m_host.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face);
  1351. }
  1352. public void SetTexGen(ISceneChildEntity part, int face, int style)
  1353. {
  1354. Primitive.TextureEntry tex = part.Shape.Textures;
  1355. MappingType textype = MappingType.Default;
  1356. if (style == (int)ScriptBaseClass.PRIM_TEXGEN_PLANAR)
  1357. textype = MappingType.Planar;
  1358. if (face >= 0 && face < GetNumberOfSides(part))
  1359. {
  1360. tex.CreateFace((uint)face);
  1361. tex.FaceTextures[face].TexMapType = textype;
  1362. part.UpdateTexture(tex, false);
  1363. return;
  1364. }
  1365. if (face == ScriptBaseClass.ALL_SIDES)
  1366. {
  1367. for (uint i = 0; i < GetNumberOfSides(part); i++)
  1368. {
  1369. if (tex.FaceTextures[i] != null)
  1370. {
  1371. tex.FaceTextures[i].TexMapType = textype;
  1372. }
  1373. tex.DefaultTexture.TexMapType = textype;
  1374. }
  1375. part.UpdateTexture(tex, false);
  1376. }
  1377. }
  1378. public void SetGlow(ISceneChildEntity part, int face, float glow)
  1379. {
  1380. Primitive.TextureEntry tex = part.Shape.Textures;
  1381. if (face >= 0 && face < GetNumberOfSides(part))
  1382. {
  1383. tex.CreateFace((uint)face);
  1384. tex.FaceTextures[face].Glow = glow;
  1385. part.UpdateTexture(tex, false);
  1386. return;
  1387. }
  1388. if (face == ScriptBaseClass.ALL_SIDES)
  1389. {
  1390. for (uint i = 0; i < GetNumberOfSides(part); i++)
  1391. {
  1392. if (tex.FaceTextures[i] != null)
  1393. {
  1394. tex.FaceTextures[i].Glow = glow;
  1395. }
  1396. tex.DefaultTexture.Glow = glow;
  1397. }
  1398. part.UpdateTexture(tex, false);
  1399. }
  1400. }
  1401. public void SetShiny(ISceneChildEntity part, int face, int shiny, Bumpiness bump)
  1402. {
  1403. Shininess sval = new Shininess();
  1404. switch (shiny)
  1405. {
  1406. case 0:
  1407. sval = Shininess.None;
  1408. break;
  1409. case 1:
  1410. sval = Shininess.Low;
  1411. break;
  1412. case 2:
  1413. sval = Shininess.Medium;
  1414. break;
  1415. case 3:
  1416. sval = Shininess.High;
  1417. break;
  1418. default:
  1419. sval = Shininess.None;
  1420. break;
  1421. }
  1422. Primitive.TextureEntry tex = part.Shape.Textures;
  1423. if (face >= 0 && face < GetNumberOfSides(part))
  1424. {
  1425. tex.CreateFace((uint)face);
  1426. tex.FaceTextures[face].Shiny = sval;
  1427. tex.FaceTextures[face].Bump = bump;
  1428. part.UpdateTexture(tex, false);
  1429. return;
  1430. }
  1431. if (face == ScriptBaseClass.ALL_SIDES)
  1432. {
  1433. for (uint i = 0; i < GetNumberOfSides(part); i++)
  1434. {
  1435. if (tex.FaceTextures[i] != null)
  1436. {
  1437. tex.FaceTextures[i].Shiny = sval;
  1438. tex.FaceTextures[i].Bump = bump;
  1439. }
  1440. tex.DefaultTexture.Shiny = sval;
  1441. tex.DefaultTexture.Bump = bump;
  1442. }
  1443. part.UpdateTexture(tex, false);
  1444. }
  1445. }
  1446. public void SetFullBright(ISceneChildEntity part, int face, bool bright)
  1447. {
  1448. Primitive.TextureEntry tex = part.Shape.Textures;
  1449. if (face >= 0 && face < GetNumberOfSides(part))
  1450. {
  1451. tex.CreateFace((uint)face);
  1452. tex.FaceTextures[face].Fullbright = bright;
  1453. part.UpdateTexture(tex, false);
  1454. return;
  1455. }
  1456. if (face == ScriptBaseClass.ALL_SIDES)
  1457. {
  1458. for (uint i = 0; i < GetNumberOfSides(part); i++)
  1459. {
  1460. if (tex.FaceTextures[i] != null)
  1461. {
  1462. tex.FaceTextures[i].Fullbright = bright;
  1463. }
  1464. }
  1465. tex.DefaultTexture.Fullbright = bright;
  1466. part.UpdateTexture(tex, false);
  1467. }
  1468. }
  1469. public LSL_Float llGetAlpha(int face)
  1470. {
  1471. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
  1472. return GetAlpha(m_host, face);
  1473. }
  1474. protected LSL_Float GetAlpha(ISceneChildEntity part, int face)
  1475. {
  1476. Primitive.TextureEntry tex = part.Shape.Textures;
  1477. if (face == ScriptBaseClass.ALL_SIDES)
  1478. {
  1479. int i;
  1480. double sum = 0.0;
  1481. for (i = 0; i < GetNumberOfSides(part); i++)
  1482. sum += tex.GetFace((uint)i).RGBA.A;
  1483. return sum;
  1484. }
  1485. if (face >= 0 && face < GetNumberOfSides(part))
  1486. {
  1487. return tex.GetFace((uint)face).RGBA.A;
  1488. }
  1489. return 0.0;
  1490. }
  1491. public void llSetAlpha(double alpha, int face)
  1492. {
  1493. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  1494. SetAlpha(m_host, alpha, face);
  1495. }
  1496. public void llSetLinkAlpha(int linknumber, double alpha, int face)
  1497. {
  1498. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  1499. List<ISceneChildEntity> parts = GetLinkParts(linknumber);
  1500. foreach (ISceneChildEntity part in parts)
  1501. SetAlpha(part, alpha, face);
  1502. }
  1503. protected void SetAlpha(ISceneChildEntity part, double alpha, int face)
  1504. {
  1505. Primitive.TextureEntry tex = part.Shape.Textures;
  1506. Color4 texcolor;
  1507. bool changed = false;
  1508. if (face >= 0 && face < GetNumberOfSides(part))
  1509. {
  1510. texcolor = tex.CreateFace((uint)face).RGBA;
  1511. if (texcolor.A != alpha)
  1512. changed = true;
  1513. texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
  1514. tex.FaceTextures[face].RGBA = texcolor;
  1515. if (changed)
  1516. part.UpdateTexture(tex, false);
  1517. }
  1518. else if (face == ScriptBaseClass.ALL_SIDES)
  1519. {
  1520. for (int i = 0; i < GetNumberOfSides(part); i++)
  1521. {
  1522. if (tex.FaceTextures[i] != null)
  1523. {
  1524. texcolor = tex.FaceTextures[i].RGBA;
  1525. if (texcolor.A != alpha)
  1526. changed = true;
  1527. texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
  1528. tex.FaceTextures[i].RGBA = texcolor;
  1529. }
  1530. }
  1531. texcolor = tex.DefaultTexture.RGBA;
  1532. if (texcolor.A != alpha)
  1533. changed = true;
  1534. texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
  1535. tex.DefaultTexture.RGBA = texcolor;
  1536. if (changed)
  1537. part.UpdateTexture(tex, false);
  1538. }
  1539. part.ScheduleUpdate(PrimUpdateFlags.FullUpdate);
  1540. }
  1541. /// <summary>
  1542. /// Set flexi parameters of a part.
  1543. ///
  1544. /// FIXME: Much of this code should probably be within the part itself.
  1545. /// </summary>
  1546. /// <param name="part"></param>
  1547. /// <param name="flexi"></param>
  1548. /// <param name="softness"></param>
  1549. /// <param name="gravity"></param>
  1550. /// <param name="friction"></param>
  1551. /// <param name="wind"></param>
  1552. /// <param name="tension"></param>
  1553. /// <param name="Force"></param>
  1554. protected void SetFlexi(ISceneChildEntity part, bool flexi, int softness, float gravity, float friction,
  1555. float wind, float tension, LSL_Vector Force)
  1556. {
  1557. if (part == null)
  1558. return;
  1559. if (flexi)
  1560. {
  1561. part.Shape.PathCurve |= (byte)Extrusion.Flexible;
  1562. part.Shape.FlexiEntry = true; // this setting flexi true isn't working, but the below parameters do
  1563. // work once the prim is already flexi
  1564. part.Shape.FlexiSoftness = softness;
  1565. part.Shape.FlexiGravity = gravity;
  1566. part.Shape.FlexiDrag = friction;
  1567. part.Shape.FlexiWind = wind;
  1568. part.Shape.FlexiTension = tension;
  1569. part.Shape.FlexiForceX = (float)Force.x;
  1570. part.Shape.FlexiForceY = (float)Force.y;
  1571. part.Shape.FlexiForceZ = (float)Force.z;
  1572. part.Shape.PathCurve = 0x80;
  1573. }
  1574. else
  1575. {
  1576. int curve = part.Shape.PathCurve;
  1577. curve &= (int)(~(Extrusion.Flexible));
  1578. part.Shape.PathCurve = (byte)curve;
  1579. part.Shape.FlexiEntry = false;
  1580. }
  1581. part.ParentEntity.HasGroupChanged = true;
  1582. part.ScheduleUpdate(PrimUpdateFlags.FullUpdate);
  1583. }
  1584. /// <summary>
  1585. /// Set a light point on a part
  1586. /// </summary>
  1587. /// FIXME: Much of this code should probably be in SceneObjectGroup
  1588. ///
  1589. /// <param name="part"></param>
  1590. /// <param name="light"></param>
  1591. /// <param name="color"></param>
  1592. /// <param name="intensity"></param>
  1593. /// <param name="radius"></param>
  1594. /// <param name="falloff"></param>
  1595. protected void SetPointLight(ISceneChildEntity part, bool light, LSL_Vector color, float intensity, float radius, float falloff)
  1596. {
  1597. if (part == null)
  1598. return;
  1599. bool same = true;
  1600. if (light)
  1601. {
  1602. if (part.Shape.LightEntry != true)
  1603. same = false;
  1604. part.Shape.LightEntry = true;
  1605. if (part.Shape.LightColorR != Util.Clip((float)color.x, 0.0f, 1.0f))
  1606. same = false;
  1607. part.Shape.LightColorR = Util.Clip((float)color.x, 0.0f, 1.0f);
  1608. if (part.Shape.LightColorG != Util.Clip((float)color.y, 0.0f, 1.0f))
  1609. same = false;
  1610. part.Shape.LightColorG = Util.Clip((float)color.y, 0.0f, 1.0f);
  1611. if (part.Shape.LightColorB != Util.Clip((float)color.z, 0.0f, 1.0f))
  1612. same = false;
  1613. part.Shape.LightColorB = Util.Clip((float)color.z, 0.0f, 1.0f);
  1614. if (part.Shape.LightIntensity != intensity)
  1615. same = false;
  1616. part.Shape.LightIntensity = intensity;
  1617. if (part.Shape.LightRadius != radius)
  1618. same = false;
  1619. part.Shape.LightRadius = radius;
  1620. if (part.Shape.LightFalloff != falloff)
  1621. same = false;
  1622. part.Shape.LightFalloff = falloff;
  1623. }
  1624. else
  1625. {
  1626. if (part.Shape.LightEntry)
  1627. same = false;
  1628. part.Shape.LightEntry = false;
  1629. }
  1630. if (!same)
  1631. {
  1632. part.ParentEntity.HasGroupChanged = true;
  1633. part.ScheduleUpdate(PrimUpdateFlags.FindBest);
  1634. }
  1635. }
  1636. public LSL_Vector llGetColor(int face)
  1637. {
  1638. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
  1639. return GetColor(m_host, face);
  1640. }
  1641. protected LSL_Vector GetColor(ISceneChildEntity part, int face)
  1642. {
  1643. Primitive.TextureEntry tex = part.Shape.Textures;
  1644. Color4 texcolor;
  1645. LSL_Vector rgb = new LSL_Vector();
  1646. int ns = GetNumberOfSides(part);
  1647. if (face == ScriptBaseClass.ALL_SIDES)
  1648. {
  1649. int i;
  1650. for (i = 0; i < ns; i++)
  1651. {
  1652. texcolor = tex.GetFace((uint)i).RGBA;
  1653. rgb.x += texcolor.R;
  1654. rgb.y += texcolor.G;
  1655. rgb.z += texcolor.B;
  1656. }
  1657. float tmp = 1f / ns;
  1658. rgb.x *= tmp;
  1659. rgb.y *= tmp;
  1660. rgb.z *= tmp;
  1661. return rgb;
  1662. }
  1663. if (face >= 0 && face < ns)
  1664. {
  1665. texcolor = tex.GetFace((uint)face).RGBA;
  1666. rgb.x = texcolor.R;
  1667. rgb.y = texcolor.G;
  1668. rgb.z = texcolor.B;
  1669. return rgb;
  1670. }
  1671. return new LSL_Vector();
  1672. }
  1673. public DateTime llSetTexture(string texture, int face)
  1674. {
  1675. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return DateTime.Now;
  1676. bool found = SetTexture(m_host, texture, face);
  1677. if (!found)
  1678. ShoutError("Could not find texture '" + texture + "'");
  1679. return PScriptSleep(200);
  1680. }
  1681. public DateTime llSetLinkTexture(int linknumber, string texture, int face)
  1682. {
  1683. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return DateTime.Now;
  1684. List<ISceneChildEntity> parts = GetLinkParts(linknumber);
  1685. foreach (ISceneChildEntity part in parts)
  1686. SetTexture(part, texture, face);
  1687. return PScriptSleep(100);
  1688. }
  1689. protected bool SetTexture(ISceneChildEntity part, string texture, int face)
  1690. {
  1691. UUID textureID = new UUID();
  1692. int ns = GetNumberOfSides(part);
  1693. textureID = InventoryKey(texture, (int)AssetType.Texture);
  1694. if (textureID == UUID.Zero)
  1695. {
  1696. if (!UUID.TryParse(texture, out textureID))
  1697. return false;
  1698. }
  1699. Primitive.TextureEntry tex = part.Shape.Textures;
  1700. if (face >= 0 && face < ns)
  1701. {
  1702. Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
  1703. texface.TextureID = textureID;
  1704. tex.FaceTextures[face] = texface;
  1705. part.UpdateTexture(tex, false);
  1706. }
  1707. if (face == ScriptBaseClass.ALL_SIDES)
  1708. {
  1709. for (uint i = 0; i < ns; i++)
  1710. {
  1711. if (tex.FaceTextures[i] != null)
  1712. {
  1713. tex.FaceTextures[i].TextureID = textureID;
  1714. }
  1715. }
  1716. tex.DefaultTexture.TextureID = textureID;
  1717. part.UpdateTexture(tex, false);
  1718. }
  1719. return true;
  1720. }
  1721. public DateTime llScaleTexture(double u, double v, int face)
  1722. {
  1723. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return DateTime.Now;
  1724. ScaleTexture(m_host, u, v, face);
  1725. return PScriptSleep(200);
  1726. }
  1727. protected void ScaleTexture(ISceneChildEntity part, double u, double v, int face)
  1728. {
  1729. Primitive.TextureEntry tex = part.Shape.Textures;
  1730. int ns = GetNumberOfSides(part);
  1731. if (face >= 0 && face < ns)
  1732. {
  1733. Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
  1734. texface.RepeatU = (float)u;
  1735. texface.RepeatV = (float)v;
  1736. tex.FaceTextures[face] = texface;
  1737. part.UpdateTexture(tex, false);
  1738. return;
  1739. }
  1740. if (face == ScriptBaseClass.ALL_SIDES)
  1741. {
  1742. for (int i = 0; i < ns; i++)
  1743. {
  1744. if (tex.FaceTextures[i] != null)
  1745. {
  1746. tex.FaceTextures[i].RepeatU = (float)u;
  1747. tex.FaceTextures[i].RepeatV = (float)v;
  1748. }
  1749. }
  1750. tex.DefaultTexture.RepeatU = (float)u;
  1751. tex.DefaultTexture.RepeatV = (float)v;
  1752. part.UpdateTexture(tex, false);
  1753. }
  1754. }
  1755. public DateTime llOffsetTexture(double u, double v, int face)
  1756. {
  1757. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return DateTime.Now;
  1758. OffsetTexture(m_host, u, v, face);
  1759. return PScriptSleep(200);
  1760. }
  1761. protected void OffsetTexture(ISceneChildEntity part, double u, double v, int face)
  1762. {
  1763. Primitive.TextureEntry tex = part.Shape.Textures;
  1764. int ns = GetNumberOfSides(part);
  1765. if (face >= 0 && face < ns)
  1766. {
  1767. Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
  1768. texface.OffsetU = (float)u;
  1769. texface.OffsetV = (float)v;
  1770. tex.FaceTextures[face] = texface;
  1771. part.UpdateTexture(tex, false);
  1772. return;
  1773. }
  1774. if (face == ScriptBaseClass.ALL_SIDES)
  1775. {
  1776. for (int i = 0; i < ns; i++)
  1777. {
  1778. if (tex.FaceTextures[i] != null)
  1779. {
  1780. tex.FaceTextures[i].OffsetU = (float)u;
  1781. tex.FaceTextures[i].OffsetV = (float)v;
  1782. }
  1783. }
  1784. tex.DefaultTexture.OffsetU = (float)u;
  1785. tex.DefaultTexture.OffsetV = (float)v;
  1786. part.UpdateTexture(tex, false);
  1787. }
  1788. }
  1789. public DateTime llRotateTexture(double rotation, int face)
  1790. {
  1791. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return DateTime.Now;
  1792. RotateTexture(m_host, rotation, face);
  1793. return PScriptSleep(200);
  1794. }
  1795. protected void RotateTexture(ISceneChildEntity part, double rotation, int face)
  1796. {
  1797. Primitive.TextureEntry tex = part.Shape.Textures;
  1798. int ns = GetNumberOfSides(part);
  1799. if (face >= 0 && face < ns)
  1800. {
  1801. Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
  1802. texface.Rotation = (float)rotation;
  1803. tex.FaceTextures[face] = texface;
  1804. part.UpdateTexture(tex, false);
  1805. return;
  1806. }
  1807. if (face == ScriptBaseClass.ALL_SIDES)
  1808. {
  1809. for (int i = 0; i < ns; i++)
  1810. {
  1811. if (tex.FaceTextures[i] != null)
  1812. {
  1813. tex.FaceTextures[i].Rotation = (float)rotation;
  1814. }
  1815. }
  1816. tex.DefaultTexture.Rotation = (float)rotation;
  1817. part.UpdateTexture(tex, false);
  1818. return;
  1819. }
  1820. }
  1821. public LSL_String llGetTexture(int face)
  1822. {
  1823. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_String();
  1824. return GetTexture(m_host, face);
  1825. }
  1826. protected LSL_String GetTexture(ISceneChildEntity part, int face)
  1827. {
  1828. Primitive.TextureEntry tex = part.Shape.Textures;
  1829. if (face == ScriptBaseClass.ALL_SIDES)
  1830. {
  1831. face = 0;
  1832. }
  1833. if (face >= 0 && face < GetNumberOfSides(part))
  1834. {
  1835. Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
  1836. TaskInventoryItem item = null;
  1837. m_host.TaskInventory.TryGetValue(texface.TextureID, out item);
  1838. if (item != null)
  1839. return item.Name.ToString();
  1840. return texface.TextureID.ToString();
  1841. }
  1842. return String.Empty;
  1843. }
  1844. public DateTime llSetPos(LSL_Vector pos)
  1845. {
  1846. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return DateTime.Now;
  1847. SetPos(m_host, pos, true);
  1848. return PScriptSleep(200);
  1849. }
  1850. public LSL_Integer llSetRegionPos(LSL_Vector pos)
  1851. {
  1852. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return ScriptBaseClass.FALSE;
  1853. SetPos(m_host, pos, false);
  1854. return ScriptBaseClass.TRUE;
  1855. }
  1856. // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos)
  1857. // note linked setpos is capped "differently"
  1858. private LSL_Vector SetPosAdjust(LSL_Vector start, LSL_Vector end)
  1859. {
  1860. if (llVecDist(start, end) > 10.0f * m_ScriptDistanceFactor)
  1861. return start + m_ScriptDistanceFactor * 10.0f * llVecNorm(end - start);
  1862. return end;
  1863. }
  1864. protected void SetPos(ISceneChildEntity part, LSL_Vector targetPos, bool checkPos)
  1865. {
  1866. // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos)
  1867. LSL_Vector currentPos = GetPartLocalPos(part);
  1868. float ground = 0;
  1869. bool disable_underground_movement = m_ScriptEngine.Config.GetBoolean("DisableUndergroundMovement", true);
  1870. ITerrainChannel heightmap = World.RequestModuleInterface<ITerrainChannel>();
  1871. if (heightmap != null)
  1872. ground = heightmap.GetNormalizedGroundHeight((int)(float)targetPos.x, (int)(float)targetPos.y);
  1873. if (part.ParentEntity == null)
  1874. return;
  1875. if (part.ParentEntity.RootChild == part)
  1876. {
  1877. ISceneEntity parent = part.ParentEntity;
  1878. if (!part.IsAttachment)
  1879. {
  1880. if (ground != 0 && (targetPos.z < ground) && disable_underground_movement)
  1881. targetPos.z = ground;
  1882. }
  1883. LSL_Vector real_vec = checkPos ? SetPosAdjust(currentPos, targetPos) : targetPos;
  1884. parent.UpdateGroupPosition(new Vector3((float)real_vec.x, (float)real_vec.y, (float)real_vec.z), true);
  1885. }
  1886. else
  1887. {
  1888. LSL_Vector rel_vec = checkPos ? SetPosAdjust(currentPos, targetPos) : targetPos;
  1889. part.FixOffsetPosition((new Vector3((float)rel_vec.x, (float)rel_vec.y, (float)rel_vec.z)), true);
  1890. }
  1891. }
  1892. protected LSL_Vector GetPartLocalPos(ISceneChildEntity part)
  1893. {
  1894. Vector3 tmp;
  1895. if (part.ParentID == 0)
  1896. {
  1897. tmp = part.AbsolutePosition;
  1898. return new LSL_Vector(tmp.X,
  1899. tmp.Y,
  1900. tmp.Z);
  1901. }
  1902. if (m_host.IsRoot)
  1903. {
  1904. tmp = m_host.AttachedPos;
  1905. return new LSL_Vector(tmp.X,
  1906. tmp.Y,
  1907. tmp.Z);
  1908. }
  1909. tmp = part.OffsetPosition;
  1910. return new LSL_Vector(tmp.X,
  1911. tmp.Y,
  1912. tmp.Z);
  1913. }
  1914. public LSL_Vector llGetPos()
  1915. {
  1916. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
  1917. Vector3 pos = m_host.GetWorldPosition();
  1918. return new LSL_Vector(pos.X, pos.Y, pos.Z);
  1919. }
  1920. public LSL_Vector llGetLocalPos()
  1921. {
  1922. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
  1923. return GetLocalPos(m_host);
  1924. }
  1925. private LSL_Vector GetLocalPos(ISceneChildEntity entity)
  1926. {
  1927. Vector3 tmp;
  1928. if (entity.ParentID != 0)
  1929. {
  1930. tmp = entity.OffsetPosition;
  1931. return new LSL_Vector(tmp.X,
  1932. tmp.Y,
  1933. tmp.Z);
  1934. }
  1935. tmp = entity.AbsolutePosition;
  1936. return new LSL_Vector(tmp.X,
  1937. tmp.Y,
  1938. tmp.Z);
  1939. }
  1940. public DateTime llSetRot(LSL_Rotation rot)
  1941. {
  1942. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return DateTime.Now;
  1943. // try to let this work as in SL...
  1944. SetLinkRot(m_host, rot);
  1945. return PScriptSleep(200);
  1946. }
  1947. private void SetLinkRot(ISceneChildEntity obj, LSL_Rotation rot)
  1948. {
  1949. if (obj.ParentID == 0)
  1950. {
  1951. // special case: If we are root, rotate complete SOG to new rotation
  1952. SetRot(obj, Rot2Quaternion(rot));
  1953. }
  1954. else
  1955. {
  1956. // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask.
  1957. ISceneEntity group = obj.ParentEntity;
  1958. if (group != null) // a bit paranoid, maybe
  1959. {
  1960. ISceneChildEntity rootPart = group.RootChild;
  1961. if (rootPart != null) // again, better safe than sorry
  1962. {
  1963. SetRot(obj, rootPart.RotationOffset * Rot2Quaternion(rot));
  1964. }
  1965. }
  1966. }
  1967. }
  1968. public DateTime llSetLocalRot(LSL_Rotation rot)
  1969. {
  1970. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return DateTime.Now;
  1971. SetRot(m_host, Rot2Quaternion(rot));
  1972. return PScriptSleep(200);
  1973. }
  1974. protected void SetRot(ISceneChildEntity part, Quaternion rot)
  1975. {
  1976. part.UpdateRotation(rot);
  1977. // Update rotation does not move the object in the physics scene if it's a linkset.
  1978. //KF: Do NOT use this next line if using ODE physics engine.
  1979. // This need a switch based on .ini Phys Engine type
  1980. //part.ParentGroup.ResetChildPrimPhysicsPositions()
  1981. // So, after thinking about this for a bit, the issue with the part.ParentGroup.AbsolutePosition = part.ParentGroup.AbsolutePosition line
  1982. // is it isn't compatible with vehicles because it causes the vehicle body to have to be broken down and rebuilt
  1983. // It's perfectly okay when the object is not an active physical body though.
  1984. // So, part.ParentGroup.ResetChildPrimPhysicsPositions(); does the thing that Kitto is warning against
  1985. // but only if the object is not physial and active. This is important for rotating doors.
  1986. // without the absoluteposition = absoluteposition happening, the doors do not move in the physics
  1987. // scene
  1988. if (part.PhysActor != null && !part.PhysActor.IsPhysical)
  1989. {
  1990. part.ParentEntity.ResetChildPrimPhysicsPositions();
  1991. }
  1992. }
  1993. /// <summary>
  1994. /// See http://lslwiki.net/lslwiki/wakka.php?wakka=ChildRotation
  1995. /// </summary>
  1996. public LSL_Rotation llGetRot()
  1997. {
  1998. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Rotation();
  1999. // unlinked or root prim then use llRootRotation
  2000. // see llRootRotaion for references.
  2001. if (m_host.LinkNum == 0 || m_host.LinkNum == 1)
  2002. {
  2003. return llGetRootRotation();
  2004. }
  2005. Quaternion q = m_host.GetWorldRotation();
  2006. return new LSL_Rotation(q.X, q.Y, q.Z, q.W);
  2007. }
  2008. private LSL_Rotation GetPartRot(ISceneChildEntity part)
  2009. {
  2010. Quaternion q;
  2011. if (part.LinkNum == 0 || part.LinkNum == 1) // unlinked or root prim
  2012. {
  2013. if (part.ParentEntity.RootChild.AttachmentPoint != 0)
  2014. {
  2015. IScenePresence avatar = World.GetScenePresence(part.AttachedAvatar);
  2016. if (avatar != null)
  2017. {
  2018. q = (avatar.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0 ? avatar.CameraRotation : avatar.Rotation;
  2019. }
  2020. else
  2021. q = part.ParentEntity.GroupRotation; // Likely never get here but just in case
  2022. }
  2023. else
  2024. q = part.ParentEntity.GroupRotation; // just the group rotation
  2025. return new LSL_Rotation(q.X, q.Y, q.Z, q.W);
  2026. }
  2027. q = part.GetWorldRotation();
  2028. return new LSL_Rotation(q.X, q.Y, q.Z, q.W);
  2029. }
  2030. public LSL_Rotation llGetLocalRot()
  2031. {
  2032. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Rotation();
  2033. return new LSL_Rotation(m_host.RotationOffset.X, m_host.RotationOffset.Y, m_host.RotationOffset.Z, m_host.RotationOffset.W);
  2034. }
  2035. public void llSetForce(LSL_Vector force, int local)
  2036. {
  2037. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  2038. if (m_host.ParentEntity != null)
  2039. {
  2040. if (!m_host.ParentEntity.IsDeleted)
  2041. {
  2042. if (local != 0)
  2043. force *= llGetRot();
  2044. m_host.ParentEntity.RootChild.SetForce(new Vector3((float)force.x, (float)force.y, (float)force.z));
  2045. }
  2046. }
  2047. }
  2048. public LSL_Vector llGetForce()
  2049. {
  2050. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
  2051. LSL_Vector force = new LSL_Vector(0.0, 0.0, 0.0);
  2052. if (m_host.ParentEntity != null)
  2053. {
  2054. if (!m_host.ParentEntity.IsDeleted)
  2055. {
  2056. Vector3 tmpForce = m_host.ParentEntity.RootChild.GetForce();
  2057. force.x = tmpForce.X;
  2058. force.y = tmpForce.Y;
  2059. force.z = tmpForce.Z;
  2060. }
  2061. }
  2062. return force;
  2063. }
  2064. public LSL_Integer llTarget(LSL_Vector position, LSL_Float range)
  2065. {
  2066. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  2067. return m_host.registerTargetWaypoint(new Vector3((float)position.x, (float)position.y, (float)position.z), (float)range);
  2068. }
  2069. public void llTargetRemove(int number)
  2070. {
  2071. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  2072. m_host.unregisterTargetWaypoint(number);
  2073. }
  2074. public LSL_Integer llRotTarget(LSL_Rotation rot, double error)
  2075. {
  2076. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  2077. return m_host.registerRotTargetWaypoint(new Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s), (float)error);
  2078. }
  2079. public void llRotTargetRemove(int number)
  2080. {
  2081. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  2082. m_host.unregisterRotTargetWaypoint(number);
  2083. }
  2084. public void llMoveToTarget(LSL_Vector target, double tau)
  2085. {
  2086. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  2087. m_host.MoveToTarget(new Vector3((float)target.x, (float)target.y, (float)target.z), (float)tau);
  2088. }
  2089. public void llStopMoveToTarget()
  2090. {
  2091. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  2092. m_host.StopMoveToTarget();
  2093. }
  2094. public void llApplyImpulse(LSL_Vector force, int local)
  2095. {
  2096. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  2097. //No energy force yet
  2098. Vector3 v = new Vector3((float)force.x, (float)force.y, (float)force.z);
  2099. float len = v.Length();
  2100. if (len > 20000.0f)
  2101. {
  2102. // v.Normalize();
  2103. v = v * 20000.0f / len;
  2104. }
  2105. m_host.ApplyImpulse(v, local != 0);
  2106. }
  2107. public void llApplyRotationalImpulse(LSL_Vector force, int local)
  2108. {
  2109. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  2110. m_host.ApplyAngularImpulse(new Vector3((float)force.x, (float)force.y, (float)force.z), local != 0);
  2111. }
  2112. public void llSetTorque(LSL_Vector torque, int local)
  2113. {
  2114. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  2115. m_host.SetAngularImpulse(new Vector3((float)torque.x, (float)torque.y, (float)torque.z), local != 0);
  2116. }
  2117. public LSL_Vector llGetTorque()
  2118. {
  2119. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
  2120. Vector3 torque = m_host.ParentEntity.GetTorque();
  2121. return new LSL_Vector(torque.X, torque.Y, torque.Z);
  2122. }
  2123. public void llSetForceAndTorque(LSL_Vector force, LSL_Vector torque, int local)
  2124. {
  2125. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  2126. llSetForce(force, local);
  2127. llSetTorque(torque, local);
  2128. }
  2129. public LSL_Vector llGetVel()
  2130. {
  2131. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
  2132. Vector3 tmp = m_host.IsAttachment ? m_host.ParentEntity.Scene.GetScenePresence(m_host.AttachedAvatar).Velocity : m_host.Velocity;
  2133. return new LSL_Vector(tmp.X, tmp.Y, tmp.Z);
  2134. }
  2135. public void llSetVelocity(LSL_Vector force, LSL_Integer local)
  2136. {
  2137. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  2138. Vector3 velocity = new Vector3((float)force.x, (float)force.y, (float)force.z);
  2139. if (local == 1)
  2140. {
  2141. Quaternion grot = m_host.GetWorldRotation();
  2142. Quaternion AXgrot = grot;
  2143. Vector3 AXimpulsei = velocity;
  2144. Vector3 newimpulse = AXimpulsei * AXgrot;
  2145. velocity = newimpulse;
  2146. }
  2147. if (m_host.ParentEntity.RootChild.PhysActor != null)
  2148. m_host.ParentEntity.RootChild.PhysActor.Velocity = velocity;
  2149. }
  2150. public void llSetAngularVelocity(LSL_Vector force, LSL_Integer local)
  2151. {
  2152. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  2153. Vector3 rotvelocity = new Vector3((float)force.x, (float)force.y, (float)force.z);
  2154. if (local == 1)
  2155. {
  2156. Quaternion grot = m_host.GetWorldRotation();
  2157. Quaternion AXgrot = grot;
  2158. Vector3 AXimpulsei = rotvelocity;
  2159. Vector3 newimpulse = AXimpulsei * AXgrot;
  2160. rotvelocity = newimpulse;
  2161. }
  2162. if (m_host.ParentEntity.RootChild.PhysActor != null)
  2163. m_host.ParentEntity.RootChild.PhysActor.RotationalVelocity = rotvelocity;
  2164. }
  2165. public LSL_Vector llGetAccel()
  2166. {
  2167. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
  2168. Vector3 tmp = m_host.Acceleration;
  2169. return new LSL_Vector(tmp.X, tmp.Y, tmp.Z);
  2170. }
  2171. public LSL_Vector llGetOmega()
  2172. {
  2173. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
  2174. Vector3 tmp = m_host.AngularVelocity;
  2175. return new LSL_Vector(tmp.X, tmp.Y, tmp.Z);
  2176. }
  2177. public LSL_Float llGetTimeOfDay() // this is not sl compatible see wiki
  2178. {
  2179. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
  2180. return (DateTime.Now.TimeOfDay.TotalMilliseconds / 1000) % (3600 * 4);
  2181. }
  2182. public LSL_Float llGetWallclock()
  2183. {
  2184. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
  2185. return DateTime.Now.TimeOfDay.TotalSeconds;
  2186. }
  2187. public LSL_Float llGetTime()
  2188. {
  2189. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
  2190. TimeSpan ScriptTime = DateTime.Now - m_timer;
  2191. return ScriptTime.TotalMilliseconds / 1000;
  2192. }
  2193. public void llResetTime()
  2194. {
  2195. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  2196. m_timer = DateTime.Now;
  2197. }
  2198. public LSL_Float llGetAndResetTime()
  2199. {
  2200. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
  2201. TimeSpan ScriptTime = DateTime.Now - m_timer;
  2202. m_timer = DateTime.Now;
  2203. return ScriptTime.TotalMilliseconds / 1000;
  2204. }
  2205. public void llSound(string sound, double volume, int queue, int loop)
  2206. {
  2207. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  2208. // This function has been deprecated
  2209. // see http://www.lslwiki.net/lslwiki/wakka.php?wakka=llSound
  2210. Deprecated("llSound");
  2211. if (loop == 1)
  2212. llLoopSound(sound, volume);
  2213. else
  2214. llPlaySound(sound, volume);
  2215. llSetSoundQueueing(queue);
  2216. }
  2217. // Xantor 20080528 PlaySound updated so it accepts an objectinventory name -or- a key to a sound
  2218. // 20080530 Updated to remove code duplication
  2219. public void llPlaySound(string sound, double volume)
  2220. {
  2221. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  2222. // send the sound, once, to all clients in range
  2223. m_host.SendSound(KeyOrName(sound, true).ToString(), volume, false, 0, 0, false, false);
  2224. }
  2225. // Xantor 20080528 we should do this differently.
  2226. // 1) apply the sound to the object
  2227. // 2) schedule full update
  2228. // just sending the sound out once doesn't work so well when other avatars come in view later on
  2229. // or when the prim gets moved, changed, sat on, whatever
  2230. // see large number of mantises (mantes?)
  2231. // 20080530 Updated to remove code duplication
  2232. // 20080530 Stop sound if there is one, otherwise volume only changes don't work
  2233. public void llLoopSound(string sound, double volume)
  2234. {
  2235. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  2236. if (m_host.Sound == KeyOrName(sound, true))
  2237. return;
  2238. if (m_host.Sound != UUID.Zero)
  2239. llStopSound();
  2240. m_host.Sound = KeyOrName(sound, true);
  2241. m_host.SoundGain = volume;
  2242. m_host.SoundFlags = (byte)SoundFlags.Loop; // looping
  2243. if (m_host.SoundRadius == 0)
  2244. m_host.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable?
  2245. m_host.ScheduleUpdate(PrimUpdateFlags.FindBest);
  2246. }
  2247. public void llLoopSoundMaster(string sound, double volume)
  2248. {
  2249. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  2250. m_host.ParentEntity.LoopSoundMasterPrim = m_host;
  2251. lock (m_host.ParentEntity.LoopSoundSlavePrims)
  2252. {
  2253. foreach (ISceneChildEntity prim in m_host.ParentEntity.LoopSoundSlavePrims)
  2254. {
  2255. if (prim.Sound != UUID.Zero)
  2256. llStopSound();
  2257. prim.Sound = KeyOrName(sound, true);
  2258. prim.SoundGain = volume;
  2259. prim.SoundFlags = (byte)SoundFlags.Loop; // looping
  2260. if (prim.SoundRadius == 0)
  2261. prim.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable?
  2262. prim.ScheduleUpdate(PrimUpdateFlags.FindBest);
  2263. }
  2264. }
  2265. if (m_host.Sound != UUID.Zero)
  2266. llStopSound();
  2267. m_host.Sound = KeyOrName(sound, true);
  2268. m_host.SoundGain = volume;
  2269. m_host.SoundFlags = (byte)SoundFlags.Loop; // looping
  2270. if (m_host.SoundRadius == 0)
  2271. m_host.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable?
  2272. m_host.ScheduleUpdate(PrimUpdateFlags.FindBest);
  2273. }
  2274. public void llLoopSoundSlave(string sound, double volume)
  2275. {
  2276. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  2277. lock (m_host.ParentEntity.LoopSoundSlavePrims)
  2278. {
  2279. m_host.ParentEntity.LoopSoundSlavePrims.Add(m_host);
  2280. }
  2281. }
  2282. public void llPlaySoundSlave(string sound, double volume)
  2283. {
  2284. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  2285. // send the sound, once, to all clients in range
  2286. m_host.SendSound(KeyOrName(sound, true).ToString(), volume, false, 0, 0, true, false);
  2287. }
  2288. public void llTriggerSound(string sound, double volume)
  2289. {
  2290. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  2291. // send the sound, once, to all clients in range
  2292. m_host.SendSound(KeyOrName(sound, true).ToString(), volume, true, 0, 0, false, false);
  2293. }
  2294. // Xantor 20080528: Clear prim data of sound instead
  2295. public void llStopSound()
  2296. {
  2297. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  2298. if (m_host.ParentEntity.LoopSoundSlavePrims.Contains(m_host))
  2299. {
  2300. if (m_host.ParentEntity.LoopSoundMasterPrim == m_host)
  2301. {
  2302. foreach (ISceneChildEntity part in m_host.ParentEntity.LoopSoundSlavePrims)
  2303. {
  2304. part.Sound = UUID.Zero;
  2305. part.SoundGain = 0;
  2306. part.SoundFlags = (byte)SoundFlags.None;
  2307. part.ScheduleUpdate(PrimUpdateFlags.FindBest);
  2308. }
  2309. m_host.ParentEntity.LoopSoundMasterPrim = null;
  2310. m_host.ParentEntity.LoopSoundSlavePrims.Clear();
  2311. }
  2312. else
  2313. {
  2314. m_host.Sound = UUID.Zero;
  2315. m_host.SoundGain = 0;
  2316. m_host.SoundFlags = (byte)SoundFlags.None;
  2317. m_host.ScheduleUpdate(PrimUpdateFlags.FindBest);
  2318. }
  2319. }
  2320. else
  2321. {
  2322. m_host.Sound = UUID.Zero;
  2323. m_host.SoundGain = 0;
  2324. m_host.SoundFlags = (byte)SoundFlags.Stop | (byte)SoundFlags.None;
  2325. m_host.ScheduleUpdate(PrimUpdateFlags.FindBest);
  2326. }
  2327. }
  2328. public DateTime llPreloadSound(string sound)
  2329. {
  2330. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return DateTime.Now;
  2331. m_host.PreloadSound(sound);
  2332. return PScriptSleep(1000);
  2333. }
  2334. /// <summary>
  2335. /// Return a portion of the designated string bounded by
  2336. /// inclusive indices (start and end). As usual, the negative
  2337. /// indices, and the tolerance for out-of-bound values, makes
  2338. /// this more complicated than it might otherwise seem.
  2339. /// </summary>
  2340. public LSL_String llGetSubString(string src, int start, int end)
  2341. {
  2342. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_String();
  2343. // Normalize indices (if negative).
  2344. // After normlaization they may still be
  2345. // negative, but that is now relative to
  2346. // the start, rather than the end, of the
  2347. // sequence.
  2348. if (start < 0)
  2349. {
  2350. start = src.Length + start;
  2351. }
  2352. if (end < 0)
  2353. {
  2354. end = src.Length + end;
  2355. }
  2356. // Conventional substring
  2357. if (start <= end)
  2358. {
  2359. // Implies both bounds are out-of-range.
  2360. if (end < 0 || start >= src.Length)
  2361. {
  2362. return String.Empty;
  2363. }
  2364. // If end is positive, then it directly
  2365. // corresponds to the lengt of the substring
  2366. // needed (plus one of course). BUT, it
  2367. // must be within bounds.
  2368. if (end >= src.Length)
  2369. {
  2370. end = src.Length - 1;
  2371. }
  2372. if (start < 0)
  2373. {
  2374. return src.Substring(0, end + 1);
  2375. }
  2376. // Both indices are positive
  2377. return src.Substring(start, (end + 1) - start);
  2378. }
  2379. // Inverted substring (end < start)
  2380. // Implies both indices are below the
  2381. // lower bound. In the inverted case, that
  2382. // means the entire string will be returned
  2383. // unchanged.
  2384. if (start < 0)
  2385. {
  2386. return src;
  2387. }
  2388. // If both indices are greater than the upper
  2389. // bound the result may seem initially counter
  2390. // intuitive.
  2391. if (end >= src.Length)
  2392. {
  2393. return src;
  2394. }
  2395. if (end < 0)
  2396. {
  2397. return start < src.Length ? src.Substring(start) : String.Empty;
  2398. }
  2399. if (start < src.Length)
  2400. {
  2401. return src.Substring(0, end + 1) + src.Substring(start);
  2402. }
  2403. return src.Substring(0, end + 1);
  2404. }
  2405. /// <summary>
  2406. /// Delete substring removes the specified substring bounded
  2407. /// by the inclusive indices start and end. Indices may be
  2408. /// negative (indicating end-relative) and may be inverted,
  2409. /// i.e. end < start./>
  2410. /// </summary>
  2411. public LSL_String llDeleteSubString(string src, int start, int end)
  2412. {
  2413. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_String();
  2414. // Normalize indices (if negative).
  2415. // After normlaization they may still be
  2416. // negative, but that is now relative to
  2417. // the start, rather than the end, of the
  2418. // sequence.
  2419. if (start < 0)
  2420. {
  2421. start = src.Length + start;
  2422. }
  2423. if (end < 0)
  2424. {
  2425. end = src.Length + end;
  2426. }
  2427. // Conventionally delimited substring
  2428. if (start <= end)
  2429. {
  2430. // If both bounds are outside of the existing
  2431. // string, then return unchanges.
  2432. if (end < 0 || start >= src.Length)
  2433. {
  2434. return src;
  2435. }
  2436. // At least one bound is in-range, so we
  2437. // need to clip the out-of-bound argument.
  2438. if (start < 0)
  2439. {
  2440. start = 0;
  2441. }
  2442. if (end >= src.Length)
  2443. {
  2444. end = src.Length - 1;
  2445. }
  2446. return src.Remove(start, end - start + 1);
  2447. }
  2448. // Inverted substring
  2449. // In this case, out of bounds means that
  2450. // the existing string is part of the cut.
  2451. if (start < 0 || end >= src.Length)
  2452. {
  2453. return String.Empty;
  2454. }
  2455. if (end > 0)
  2456. {
  2457. if (start < src.Length)
  2458. {
  2459. return src.Remove(start).Remove(0, end + 1);
  2460. }
  2461. return src.Remove(0, end + 1);
  2462. }
  2463. if (start < src.Length)
  2464. {
  2465. return src.Remove(start);
  2466. }
  2467. return src;
  2468. }
  2469. /// <summary>
  2470. /// Insert string inserts the specified string identified by src
  2471. /// at the index indicated by index. Index may be negative, in
  2472. /// which case it is end-relative. The index may exceed either
  2473. /// string bound, with the result being a concatenation.
  2474. /// </summary>
  2475. public LSL_String llInsertString(string dest, int index, string src)
  2476. {
  2477. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_String();
  2478. // Normalize indices (if negative).
  2479. // After normlaization they may still be
  2480. // negative, but that is now relative to
  2481. // the start, rather than the end, of the
  2482. // sequence.
  2483. if (index < 0)
  2484. {
  2485. index = dest.Length + index;
  2486. // Negative now means it is less than the lower
  2487. // bound of the string.
  2488. if (index < 0)
  2489. {
  2490. return src + dest;
  2491. }
  2492. }
  2493. if (index >= dest.Length)
  2494. {
  2495. return dest + src;
  2496. }
  2497. // The index is in bounds.
  2498. // In this case the index refers to the index that will
  2499. // be assigned to the first character of the inserted string.
  2500. // So unlike the other string operations, we do not add one
  2501. // to get the correct string length.
  2502. return dest.Substring(0, index) + src + dest.Substring(index);
  2503. }
  2504. public LSL_String llToUpper(string src)
  2505. {
  2506. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_String();
  2507. return src.ToUpper();
  2508. }
  2509. public LSL_String llToLower(string src)
  2510. {
  2511. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_String();
  2512. return src.ToLower();
  2513. }
  2514. public LSL_Integer llGiveMoney(string destination, int amount)
  2515. {
  2516. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Integer();
  2517. UUID invItemID = InventorySelf();
  2518. if (invItemID == UUID.Zero)
  2519. return 0;
  2520. TaskInventoryItem item = m_host.TaskInventory[invItemID];
  2521. if (item.PermsGranter == UUID.Zero)
  2522. return 0;
  2523. if ((item.PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0)
  2524. {
  2525. LSLError("No permissions to give money");
  2526. return 0;
  2527. }
  2528. UUID toID = new UUID();
  2529. if (!UUID.TryParse(destination, out toID))
  2530. {
  2531. LSLError("Bad key in llGiveMoney");
  2532. return 0;
  2533. }
  2534. IMoneyModule money = World.RequestModuleInterface<IMoneyModule>();
  2535. if (money == null)
  2536. {
  2537. NotImplemented("llGiveMoney");
  2538. return 0;
  2539. }
  2540. bool result = money.ObjectGiveMoney(
  2541. m_host.ParentEntity.UUID, m_host.OwnerID, toID, amount);
  2542. if (result)
  2543. return 1;
  2544. return 0;
  2545. }
  2546. public DateTime llMakeExplosion(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset)
  2547. {
  2548. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return DateTime.Now;
  2549. /*llParticleSystem([
  2550. PSYS_PART_FLAGS, PSYS_PART_INTERP_COLOR_MASK | PSYS_PART_INTERP_SCALE_MASK | PSYS_PART_EMISSIVE_MASK | PSYS_PART_WIND_MASK,
  2551. PSYS_SRC_PATTERN, PSYS_SRC_PATTERN_ANGLE_CONE,
  2552. PSYS_PART_START_COLOR, <1.0, 1.0, 1.0>,
  2553. PSYS_PART_END_COLOR, <1.0, 1.0, 1.0>,
  2554. PSYS_PART_START_ALPHA, 0.50,
  2555. PSYS_PART_END_ALPHA, 0.25,
  2556. PSYS_PART_START_SCALE, <particle_scale, particle_scale, 0.0>,
  2557. PSYS_PART_END_SCALE, <particle_scale * 2 + particle_lifetime, particle_scale * 2 + particle_lifetime, 0.0>,
  2558. PSYS_PART_MAX_AGE, particle_lifetime,
  2559. PSYS_SRC_ACCEL, <0.0, 0.0, 0.0>,
  2560. PSYS_SRC_TEXTURE, source_texture_id,
  2561. PSYS_SRC_BURST_RATE, 1.0,
  2562. PSYS_SRC_ANGLE_BEGIN, 0.0,
  2563. PSYS_SRC_ANGLE_END, source_cone * PI,
  2564. PSYS_SRC_BURST_PART_COUNT, particle_count / 2,
  2565. PSYS_SRC_BURST_RADIUS, 0.0,
  2566. PSYS_SRC_BURST_SPEED_MIN, particle_speed / 3,
  2567. PSYS_SRC_BURST_SPEED_MAX, particle_speed * 2/3,
  2568. PSYS_SRC_MAX_AGE, particle_lifetime / 2,
  2569. PSYS_SRC_OMEGA, <0.0, 0.0, 0.0>
  2570. ]);*/
  2571. List<object> list = new List<object>
  2572. {
  2573. ScriptBaseClass.PSYS_PART_FLAGS,
  2574. ScriptBaseClass.PSYS_PART_INTERP_COLOR_MASK |
  2575. ScriptBaseClass.PSYS_PART_INTERP_SCALE_MASK |
  2576. ScriptBaseClass.PSYS_PART_EMISSIVE_MASK | ScriptBaseClass.PSYS_PART_WIND_MASK,
  2577. ScriptBaseClass.PSYS_SRC_PATTERN,
  2578. ScriptBaseClass.PSYS_SRC_PATTERN_ANGLE_CONE,
  2579. ScriptBaseClass.PSYS_PART_START_COLOR,
  2580. new LSL_Vector(1, 1, 1),
  2581. ScriptBaseClass.PSYS_PART_END_COLOR,
  2582. new LSL_Vector(1, 1, 1),
  2583. ScriptBaseClass.PSYS_PART_START_ALPHA,
  2584. new LSL_Float(0.50),
  2585. ScriptBaseClass.PSYS_PART_END_ALPHA,
  2586. new LSL_Float(0.25),
  2587. ScriptBaseClass.PSYS_PART_START_SCALE,
  2588. new LSL_Vector(scale, scale, 0),
  2589. ScriptBaseClass.PSYS_PART_END_SCALE,
  2590. new LSL_Vector(scale*2 + lifetime, scale*2 + lifetime, 0),
  2591. ScriptBaseClass.PSYS_PART_MAX_AGE,
  2592. new LSL_Float(lifetime),
  2593. ScriptBaseClass.PSYS_SRC_ACCEL,
  2594. new LSL_Vector(0, 0, 0),
  2595. ScriptBaseClass.PSYS_SRC_TEXTURE,
  2596. new LSL_String(texture),
  2597. ScriptBaseClass.PSYS_SRC_BURST_RATE,
  2598. new LSL_Float(1),
  2599. ScriptBaseClass.PSYS_SRC_ANGLE_BEGIN,
  2600. new LSL_Float(0.0),
  2601. ScriptBaseClass.PSYS_SRC_ANGLE_END,
  2602. new LSL_Float(arc*Math.PI),
  2603. ScriptBaseClass.PSYS_SRC_BURST_PART_COUNT,
  2604. new LSL_Integer(particles/2),
  2605. ScriptBaseClass.PSYS_SRC_BURST_RADIUS,
  2606. new LSL_Float(0.0),
  2607. ScriptBaseClass.PSYS_SRC_BURST_SPEED_MIN,
  2608. new LSL_Float(vel/3),
  2609. ScriptBaseClass.PSYS_SRC_BURST_SPEED_MAX,
  2610. new LSL_Float(vel*2/3),
  2611. ScriptBaseClass.PSYS_SRC_MAX_AGE,
  2612. new LSL_Float(lifetime/2),
  2613. ScriptBaseClass.PSYS_SRC_OMEGA,
  2614. new LSL_Vector(0, 0, 0)
  2615. };
  2616. llParticleSystem(new LSL_Types.list(list.ToArray()));
  2617. return PScriptSleep(100);
  2618. }
  2619. public DateTime llMakeFountain(int particles, double scale, double vel, double lifetime, double arc, int bounce, string texture, LSL_Vector offset, double bounce_offset)
  2620. {
  2621. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return DateTime.Now;
  2622. /*llParticleSystem([
  2623. PSYS_PART_FLAGS, PSYS_PART_INTERP_COLOR_MASK | PSYS_PART_INTERP_SCALE_MASK | PSYS_PART_WIND_MASK | PSYS_PART_BOUNCE_MASK | PSYS_PART_EMISSIVE_MASK,
  2624. PSYS_SRC_PATTERN, PSYS_SRC_PATTERN_ANGLE_CONE,
  2625. PSYS_PART_START_COLOR, <1.0, 1.0, 1.0>,
  2626. PSYS_PART_END_COLOR, <1.0, 1.0, 1.0>,
  2627. PSYS_PART_START_ALPHA, 0.50,
  2628. PSYS_PART_END_ALPHA, 0.25,
  2629. PSYS_PART_START_SCALE, <particle_scale/1.5, particle_scale/1.5, 0.0>,
  2630. PSYS_PART_END_SCALE, <0.0, 0.0, 0.0>,
  2631. PSYS_PART_MAX_AGE, 3.0,
  2632. PSYS_SRC_ACCEL, <1.0, 0.0, -4>,
  2633. PSYS_SRC_TEXTURE, source_texture_id,
  2634. PSYS_SRC_BURST_RATE, 5/particle_count,
  2635. PSYS_SRC_ANGLE_BEGIN, 0.0,
  2636. PSYS_SRC_ANGLE_END, source_cone*PI,
  2637. PSYS_SRC_BURST_PART_COUNT, 1,
  2638. PSYS_SRC_BURST_RADIUS, 0.0,
  2639. PSYS_SRC_BURST_SPEED_MIN, particle_speed,
  2640. PSYS_SRC_BURST_SPEED_MAX, particle_speed,
  2641. PSYS_SRC_MAX_AGE, particle_lifetime/2,
  2642. PSYS_SRC_OMEGA, <0.0, 0.0, 0.0>
  2643. ]);*/
  2644. List<object> list = new List<object>
  2645. {
  2646. ScriptBaseClass.PSYS_PART_FLAGS,
  2647. ScriptBaseClass.PSYS_PART_INTERP_COLOR_MASK |
  2648. ScriptBaseClass.PSYS_PART_INTERP_SCALE_MASK | ScriptBaseClass.PSYS_PART_WIND_MASK |
  2649. ScriptBaseClass.PSYS_PART_BOUNCE_MASK | ScriptBaseClass.PSYS_PART_EMISSIVE_MASK,
  2650. ScriptBaseClass.PSYS_SRC_PATTERN,
  2651. ScriptBaseClass.PSYS_SRC_PATTERN_ANGLE_CONE,
  2652. ScriptBaseClass.PSYS_PART_START_COLOR,
  2653. new LSL_Vector(1, 1, 1),
  2654. ScriptBaseClass.PSYS_PART_END_COLOR,
  2655. new LSL_Vector(1, 1, 1),
  2656. ScriptBaseClass.PSYS_PART_START_ALPHA,
  2657. new LSL_Float(0.50),
  2658. ScriptBaseClass.PSYS_PART_END_ALPHA,
  2659. new LSL_Float(0.25),
  2660. ScriptBaseClass.PSYS_PART_START_SCALE,
  2661. new LSL_Vector(scale/1.5, scale/1.5, 0),
  2662. ScriptBaseClass.PSYS_PART_END_SCALE,
  2663. new LSL_Vector(0, 0, 0),
  2664. ScriptBaseClass.PSYS_PART_MAX_AGE,
  2665. new LSL_Float(3),
  2666. ScriptBaseClass.PSYS_SRC_ACCEL,
  2667. new LSL_Vector(1, 0, -4),
  2668. ScriptBaseClass.PSYS_SRC_TEXTURE,
  2669. new LSL_String(texture),
  2670. ScriptBaseClass.PSYS_SRC_BURST_RATE,
  2671. new LSL_Float(5/particles),
  2672. ScriptBaseClass.PSYS_SRC_ANGLE_BEGIN,
  2673. new LSL_Float(0.0),
  2674. ScriptBaseClass.PSYS_SRC_ANGLE_END,
  2675. new LSL_Float(arc*Math.PI),
  2676. ScriptBaseClass.PSYS_SRC_BURST_PART_COUNT,
  2677. new LSL_Integer(1),
  2678. ScriptBaseClass.PSYS_SRC_BURST_RADIUS,
  2679. new LSL_Float(0.0),
  2680. ScriptBaseClass.PSYS_SRC_BURST_SPEED_MIN,
  2681. new LSL_Float(vel),
  2682. ScriptBaseClass.PSYS_SRC_BURST_SPEED_MAX,
  2683. new LSL_Float(vel),
  2684. ScriptBaseClass.PSYS_SRC_MAX_AGE,
  2685. new LSL_Float(lifetime/2),
  2686. ScriptBaseClass.PSYS_SRC_OMEGA,
  2687. new LSL_Vector(0, 0, 0)
  2688. };
  2689. llParticleSystem(new LSL_Types.list(list.ToArray()));
  2690. return PScriptSleep(100);
  2691. }
  2692. public DateTime llMakeSmoke(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset)
  2693. {
  2694. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return DateTime.Now;
  2695. /*llParticleSystem([
  2696. PSYS_PART_FLAGS, PSYS_PART_INTERP_COLOR_MASK | PSYS_PART_INTERP_SCALE_MASK | PSYS_PART_EMISSIVE_MASK | PSYS_PART_WIND_MASK,
  2697. PSYS_SRC_PATTERN, PSYS_SRC_PATTERN_ANGLE_CONE,
  2698. PSYS_PART_START_COLOR, <1.0, 1.0, 1.0>,
  2699. PSYS_PART_END_COLOR, <1.0, 1.0, 1.0>,
  2700. PSYS_PART_START_ALPHA, 1.00,
  2701. PSYS_PART_END_ALPHA, 0.05,
  2702. PSYS_PART_START_SCALE, <particle_scale, particle_scale, 0.0>,
  2703. PSYS_PART_END_SCALE, <10, 10, 0.0>,
  2704. PSYS_PART_MAX_AGE, 3.0,
  2705. PSYS_SRC_ACCEL, <0.0, 0.0, 0.0>,
  2706. PSYS_SRC_TEXTURE, source_texture_id,
  2707. PSYS_SRC_BURST_RATE, 10.0 / particle_count,
  2708. PSYS_SRC_ANGLE_BEGIN, 0.0,
  2709. PSYS_SRC_ANGLE_END, source_cone * PI,
  2710. PSYS_SRC_BURST_PART_COUNT, 1,
  2711. PSYS_SRC_BURST_RADIUS, 0.0,
  2712. PSYS_SRC_BURST_SPEED_MIN, particle_speed,
  2713. PSYS_SRC_BURST_SPEED_MAX, particle_speed,
  2714. PSYS_SRC_MAX_AGE, particle_lifetime / 2,
  2715. PSYS_SRC_OMEGA, <0.0, 0.0, 0.0>
  2716. ]);*/
  2717. List<object> list = new List<object>
  2718. {
  2719. ScriptBaseClass.PSYS_PART_FLAGS,
  2720. ScriptBaseClass.PSYS_PART_INTERP_COLOR_MASK |
  2721. ScriptBaseClass.PSYS_PART_INTERP_SCALE_MASK |
  2722. ScriptBaseClass.PSYS_PART_EMISSIVE_MASK | ScriptBaseClass.PSYS_PART_WIND_MASK,
  2723. ScriptBaseClass.PSYS_SRC_PATTERN,
  2724. ScriptBaseClass.PSYS_SRC_PATTERN_ANGLE_CONE,
  2725. ScriptBaseClass.PSYS_PART_START_COLOR,
  2726. new LSL_Vector(1, 1, 1),
  2727. ScriptBaseClass.PSYS_PART_END_COLOR,
  2728. new LSL_Vector(1, 1, 1),
  2729. ScriptBaseClass.PSYS_PART_START_ALPHA,
  2730. new LSL_Float(1),
  2731. ScriptBaseClass.PSYS_PART_END_ALPHA,
  2732. new LSL_Float(0.05),
  2733. ScriptBaseClass.PSYS_PART_START_SCALE,
  2734. new LSL_Vector(scale, scale, 0),
  2735. ScriptBaseClass.PSYS_PART_END_SCALE,
  2736. new LSL_Vector(10, 10, 0),
  2737. ScriptBaseClass.PSYS_PART_MAX_AGE,
  2738. new LSL_Float(3),
  2739. ScriptBaseClass.PSYS_SRC_ACCEL,
  2740. new LSL_Vector(0, 0, 0),
  2741. ScriptBaseClass.PSYS_SRC_TEXTURE,
  2742. new LSL_String(texture),
  2743. ScriptBaseClass.PSYS_SRC_BURST_RATE,
  2744. new LSL_Float(10/particles),
  2745. ScriptBaseClass.PSYS_SRC_ANGLE_BEGIN,
  2746. new LSL_Float(0.0),
  2747. ScriptBaseClass.PSYS_SRC_ANGLE_END,
  2748. new LSL_Float(arc*Math.PI),
  2749. ScriptBaseClass.PSYS_SRC_BURST_PART_COUNT,
  2750. new LSL_Integer(1),
  2751. ScriptBaseClass.PSYS_SRC_BURST_RADIUS,
  2752. new LSL_Float(0.0),
  2753. ScriptBaseClass.PSYS_SRC_BURST_SPEED_MIN,
  2754. new LSL_Float(vel),
  2755. ScriptBaseClass.PSYS_SRC_BURST_SPEED_MAX,
  2756. new LSL_Float(vel),
  2757. ScriptBaseClass.PSYS_SRC_MAX_AGE,
  2758. new LSL_Float(lifetime/2),
  2759. ScriptBaseClass.PSYS_SRC_OMEGA,
  2760. new LSL_Vector(0, 0, 0)
  2761. };
  2762. llParticleSystem(new LSL_Types.list(list.ToArray()));
  2763. return PScriptSleep(100);
  2764. }
  2765. public DateTime llMakeFire(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset)
  2766. {
  2767. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return DateTime.Now;
  2768. /*llParticleSystem([
  2769. PSYS_PART_FLAGS, PSYS_PART_INTERP_COLOR_MASK | PSYS_PART_INTERP_SCALE_MASK | PSYS_PART_EMISSIVE_MASK | PSYS_PART_WIND_MASK,
  2770. PSYS_SRC_PATTERN, PSYS_SRC_PATTERN_ANGLE_CONE,
  2771. PSYS_PART_START_COLOR, <1.0, 1.0, 1.0>,
  2772. PSYS_PART_END_COLOR, <1.0, 1.0, 1.0>,
  2773. PSYS_PART_START_ALPHA, 0.50,
  2774. PSYS_PART_END_ALPHA, 0.10,
  2775. PSYS_PART_START_SCALE, <particle_scale/2, particle_scale/2, 0.0>,
  2776. PSYS_PART_END_SCALE, <particle_scale, particle_scale, 0.0>,
  2777. PSYS_PART_MAX_AGE, 0.5,
  2778. PSYS_SRC_ACCEL, <0.0, 0.0, 0.0>,
  2779. PSYS_SRC_TEXTURE, source_texture_id,
  2780. PSYS_SRC_BURST_RATE, 5 / particle_count,
  2781. PSYS_SRC_ANGLE_BEGIN, 0.0,
  2782. PSYS_SRC_ANGLE_END, source_cone * PI,
  2783. PSYS_SRC_BURST_PART_COUNT, 1,
  2784. PSYS_SRC_BURST_RADIUS, 0.0,
  2785. PSYS_SRC_BURST_SPEED_MIN, particle_speed,
  2786. PSYS_SRC_BURST_SPEED_MAX, particle_speed,
  2787. PSYS_SRC_MAX_AGE, particle_lifetime / 2,
  2788. PSYS_SRC_OMEGA, <0.0, 0.0, 0.0>
  2789. ]);*/
  2790. List<object> list = new List<object>
  2791. {
  2792. ScriptBaseClass.PSYS_PART_FLAGS,
  2793. ScriptBaseClass.PSYS_PART_INTERP_COLOR_MASK |
  2794. ScriptBaseClass.PSYS_PART_INTERP_SCALE_MASK |
  2795. ScriptBaseClass.PSYS_PART_EMISSIVE_MASK | ScriptBaseClass.PSYS_PART_WIND_MASK,
  2796. ScriptBaseClass.PSYS_SRC_PATTERN,
  2797. ScriptBaseClass.PSYS_SRC_PATTERN_ANGLE_CONE,
  2798. ScriptBaseClass.PSYS_PART_START_COLOR,
  2799. new LSL_Vector(1, 1, 1),
  2800. ScriptBaseClass.PSYS_PART_END_COLOR,
  2801. new LSL_Vector(1, 1, 1),
  2802. ScriptBaseClass.PSYS_PART_START_ALPHA,
  2803. new LSL_Float(0.50),
  2804. ScriptBaseClass.PSYS_PART_END_ALPHA,
  2805. new LSL_Float(0.10),
  2806. ScriptBaseClass.PSYS_PART_START_SCALE,
  2807. new LSL_Vector(scale/2, scale/2, 0),
  2808. ScriptBaseClass.PSYS_PART_END_SCALE,
  2809. new LSL_Vector(scale, scale, 0),
  2810. ScriptBaseClass.PSYS_PART_MAX_AGE,
  2811. new LSL_Float(0.50),
  2812. ScriptBaseClass.PSYS_SRC_ACCEL,
  2813. new LSL_Vector(0, 0, 0),
  2814. ScriptBaseClass.PSYS_SRC_TEXTURE,
  2815. new LSL_String(texture),
  2816. ScriptBaseClass.PSYS_SRC_BURST_RATE,
  2817. new LSL_Float(5/particles),
  2818. ScriptBaseClass.PSYS_SRC_ANGLE_BEGIN,
  2819. new LSL_Float(0.0),
  2820. ScriptBaseClass.PSYS_SRC_ANGLE_END,
  2821. new LSL_Float(arc*Math.PI),
  2822. ScriptBaseClass.PSYS_SRC_BURST_PART_COUNT,
  2823. new LSL_Integer(1),
  2824. ScriptBaseClass.PSYS_SRC_BURST_RADIUS,
  2825. new LSL_Float(0.0),
  2826. ScriptBaseClass.PSYS_SRC_BURST_SPEED_MIN,
  2827. new LSL_Float(vel),
  2828. ScriptBaseClass.PSYS_SRC_BURST_SPEED_MAX,
  2829. new LSL_Float(vel),
  2830. ScriptBaseClass.PSYS_SRC_MAX_AGE,
  2831. new LSL_Float(lifetime/2),
  2832. ScriptBaseClass.PSYS_SRC_OMEGA,
  2833. new LSL_Vector(0, 0, 0)
  2834. };
  2835. llParticleSystem(new LSL_Types.list(list.ToArray()));
  2836. return PScriptSleep(100);
  2837. }
  2838. public DateTime llRezAtRoot(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param)
  2839. {
  2840. return llRezPrim(inventory, pos, vel, rot, param, true, true, true, true);
  2841. }
  2842. /// <summary>
  2843. /// This isn't really an LSL function, just a way to merge llRezAtRoot and llRezObject into one
  2844. /// </summary>
  2845. /// <param name="inventory"></param>
  2846. /// <param name="pos"></param>
  2847. /// <param name="vel"></param>
  2848. /// <param name="rot"></param>
  2849. /// <param name="param"></param>
  2850. /// <param name="isRezAtRoot"></param>
  2851. /// <param name="SetDieAtEdge"></param>
  2852. /// <param name="CheckPos"></param>
  2853. /// <returns></returns>
  2854. public DateTime llRezPrim(string inventory, LSL_Types.Vector3 pos, LSL_Types.Vector3 vel, LSL_Types.Quaternion rot, int param, bool isRezAtRoot, bool SetDieAtEdge, bool CheckPos)
  2855. {
  2856. return llRezPrim(inventory, pos, vel, rot, param, isRezAtRoot, false, SetDieAtEdge, CheckPos);
  2857. }
  2858. /// <summary>
  2859. /// This isn't really an LSL function, just a way to merge llRezAtRoot and llRezObject into one
  2860. /// </summary>
  2861. /// <param name="inventory"></param>
  2862. /// <param name="pos"></param>
  2863. /// <param name="vel"></param>
  2864. /// <param name="rot"></param>
  2865. /// <param name="param"></param>
  2866. /// <param name="isRezAtRoot"></param>
  2867. /// <param name="doRecoil"></param>
  2868. /// <param name="SetDieAtEdge"></param>
  2869. /// <param name="CheckPos"></param>
  2870. /// <returns></returns>
  2871. public DateTime llRezPrim(string inventory, LSL_Types.Vector3 pos, LSL_Types.Vector3 vel, LSL_Types.Quaternion rot, int param, bool isRezAtRoot, bool doRecoil, bool SetDieAtEdge, bool CheckPos)
  2872. {
  2873. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.Low, "llRezPrim", m_host, "LSL", m_itemID)) return DateTime.Now;
  2874. if (m_ScriptEngine.Config.GetBoolean("AllowllRezObject", true))
  2875. {
  2876. if (Double.IsNaN(rot.x) || Double.IsNaN(rot.y) || Double.IsNaN(rot.z) || Double.IsNaN(rot.s))
  2877. return DateTime.Now;
  2878. if (CheckPos)
  2879. {
  2880. float dist = (float)llVecDist(llGetPos(), pos);
  2881. if (dist > m_ScriptDistanceFactor * 10.0f)
  2882. return DateTime.Now;
  2883. }
  2884. TaskInventoryDictionary partInventory = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
  2885. foreach (KeyValuePair<UUID, TaskInventoryItem> inv in partInventory)
  2886. {
  2887. if (inv.Value.Name == inventory)
  2888. {
  2889. // make sure we're an object.
  2890. if (inv.Value.InvType != (int)InventoryType.Object)
  2891. {
  2892. llSay(0, "Unable to create requested object. Object is missing from database.");
  2893. return DateTime.Now;
  2894. }
  2895. Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z);
  2896. Vector3 llvel = new Vector3((float)vel.x, (float)vel.y, (float)vel.z);
  2897. ISceneEntity new_group = RezObject(m_host, inv.Value, llpos, Rot2Quaternion(rot), llvel, param, m_host.UUID, isRezAtRoot);
  2898. new_group.OnFinishedPhysicalRepresentationBuilding += delegate()
  2899. {
  2900. //Do this after the physics engine has built the prim
  2901. float groupmass = new_group.GetMass();
  2902. //Recoil to the av
  2903. if (m_host.IsAttachment && doRecoil && (new_group.RootChild.Flags & PrimFlags.Physics) == PrimFlags.Physics)
  2904. {
  2905. IScenePresence SP = m_host.ParentEntity.Scene.GetScenePresence(m_host.OwnerID);
  2906. if (SP != null)
  2907. {
  2908. //Push the av backwards (For every action, there is an equal, but opposite reaction)
  2909. Vector3 impulse = llvel * groupmass;
  2910. impulse.X = impulse.X < 1 ? impulse.X : impulse.X > -1 ? impulse.X : -1;
  2911. impulse.Y = impulse.Y < 1 ? impulse.Y : impulse.Y > -1 ? impulse.Y : -1;
  2912. impulse.Z = impulse.Z < 1 ? impulse.Z : impulse.Z > -1 ? impulse.Z : -1;
  2913. SP.PushForce(impulse);
  2914. }
  2915. }
  2916. };
  2917. // If either of these are null, then there was an unknown error.
  2918. if (new_group == null || new_group.RootChild == null)
  2919. continue;
  2920. // objects rezzed with this method are die_at_edge by default.
  2921. if (SetDieAtEdge)
  2922. new_group.RootChild.SetDieAtEdge(true);
  2923. // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
  2924. return PScriptSleep(100);
  2925. }
  2926. }
  2927. llSay(0, "Could not find object " + inventory);
  2928. }
  2929. return DateTime.Now;
  2930. }
  2931. /// <summary>
  2932. /// Rez an object into the scene from a prim's inventory.
  2933. /// </summary>
  2934. /// <param name="sourcePart"></param>
  2935. /// <param name="item"></param>
  2936. /// <param name="pos"></param>
  2937. /// <param name="rot"></param>
  2938. /// <param name="vel"></param>
  2939. /// <param name="param"></param>
  2940. /// <param name="RezzedFrom"></param>
  2941. /// <param name="RezObjectAtRoot"></param>
  2942. /// <returns>The SceneObjectGroup rezzed or null if rez was unsuccessful</returns>
  2943. public ISceneEntity RezObject(
  2944. ISceneChildEntity sourcePart, TaskInventoryItem item,
  2945. Vector3 pos, Quaternion rot, Vector3 vel, int param, UUID RezzedFrom, bool RezObjectAtRoot)
  2946. {
  2947. if (item != null)
  2948. {
  2949. UUID ownerID = item.OwnerID;
  2950. AssetBase rezAsset = World.AssetService.Get(item.AssetID.ToString());
  2951. if (rezAsset != null)
  2952. {
  2953. string xmlData = Utils.BytesToString(rezAsset.Data);
  2954. SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData, World);
  2955. if (group == null)
  2956. return null;
  2957. string reason;
  2958. if (!World.Permissions.CanRezObject(group.ChildrenList.Count, ownerID, pos, out reason))
  2959. {
  2960. World.GetScenePresence(ownerID).ControllingClient.SendAlertMessage("You do not have permission to rez objects here: " + reason);
  2961. return null;
  2962. }
  2963. List<ISceneChildEntity> partList = group.ChildrenEntities();
  2964. // we set it's position in world.
  2965. // llRezObject sets the whole group at the position, while llRezAtRoot rezzes the group based on the root prim's position
  2966. // See: http://lslwiki.net/lslwiki/wakka.php?wakka=llRezAtRoot
  2967. // Shorthand: llRezAtRoot rezzes the root prim of the group at the position
  2968. // llRezObject rezzes the center of group at the position
  2969. if (RezObjectAtRoot)
  2970. //This sets it right...
  2971. group.AbsolutePosition = pos;
  2972. else
  2973. {
  2974. // center is on average of all positions
  2975. // less root prim position
  2976. #if (!ISWIN)
  2977. Vector3 offset = Vector3.Zero;
  2978. foreach (ISceneChildEntity child in partList)
  2979. {
  2980. offset += child.AbsolutePosition;
  2981. }
  2982. #else
  2983. Vector3 offset = partList.Aggregate(Vector3.Zero, (current, child) => current + child.AbsolutePosition);
  2984. #endif
  2985. offset /= partList.Count;
  2986. offset -= group.AbsolutePosition;
  2987. offset += pos;
  2988. group.AbsolutePosition = offset;
  2989. }
  2990. ISceneChildEntity rootPart = group.GetChildPart(group.UUID);
  2991. // Since renaming the item in the inventory does not affect the name stored
  2992. // in the serialization, transfer the correct name from the inventory to the
  2993. // object itself before we rez.
  2994. rootPart.Name = item.Name;
  2995. rootPart.Description = item.Description;
  2996. group.SetGroup(sourcePart.GroupID, group.OwnerID, false);
  2997. if (rootPart.OwnerID != item.OwnerID)
  2998. {
  2999. if (World.Permissions.PropagatePermissions())
  3000. {
  3001. if ((item.CurrentPermissions & 8) != 0)
  3002. {
  3003. foreach (ISceneChildEntity part in partList)
  3004. {
  3005. part.EveryoneMask = item.EveryonePermissions;
  3006. part.NextOwnerMask = item.NextPermissions;
  3007. }
  3008. }
  3009. group.ApplyNextOwnerPermissions();
  3010. }
  3011. }
  3012. foreach (ISceneChildEntity part in partList)
  3013. {
  3014. if (part.OwnerID != item.OwnerID)
  3015. {
  3016. part.LastOwnerID = part.OwnerID;
  3017. part.OwnerID = item.OwnerID;
  3018. part.Inventory.ChangeInventoryOwner(item.OwnerID);
  3019. }
  3020. else if ((item.CurrentPermissions & 8) != 0) // Slam!
  3021. {
  3022. part.EveryoneMask = item.EveryonePermissions;
  3023. part.NextOwnerMask = item.NextPermissions;
  3024. }
  3025. }
  3026. rootPart.TrimPermissions();
  3027. if (group.RootPart.Shape.PCode == (byte)PCode.Prim)
  3028. {
  3029. group.ClearPartAttachmentData();
  3030. }
  3031. group.UpdateGroupRotationR(rot);
  3032. //group.ApplyPhysics(m_physicalPrim);
  3033. World.SceneGraph.AddPrimToScene(group);
  3034. if ((group.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics)
  3035. {
  3036. group.RootPart.PhysActor.OnPhysicalRepresentationChanged += delegate
  3037. {
  3038. float groupmass = group.GetMass();
  3039. //Apply the velocity to the object
  3040. //llApplyImpulse(new LSL_Vector(llvel.X * groupmass, llvel.Y * groupmass, llvel.Z * groupmass), 0);
  3041. // @Above: Err.... no. Read http://lslwiki.net/lslwiki/wakka.php?wakka=llRezObject
  3042. // Notice the "Creates ("rezzes") object's inventory object centered at position pos (in region coordinates) with velocity vel"
  3043. // This means SET the velocity to X, not just temperarily add it!
  3044. // -- Revolution Smythe
  3045. llSetForce(new LSL_Vector(vel * groupmass), 0);
  3046. group.RootPart.PhysActor.ForceSetVelocity(vel * groupmass);
  3047. group.RootPart.PhysActor.Velocity = vel * groupmass;
  3048. };
  3049. }
  3050. group.CreateScriptInstances(param, true, StateSource.ScriptedRez, RezzedFrom, false);
  3051. if (!World.Permissions.BypassPermissions())
  3052. {
  3053. if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
  3054. sourcePart.Inventory.RemoveInventoryItem(item.ItemID);
  3055. }
  3056. group.ScheduleGroupUpdate(PrimUpdateFlags.FullUpdate);
  3057. return rootPart.ParentEntity;
  3058. }
  3059. }
  3060. return null;
  3061. }
  3062. public DateTime llRezObject(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param)
  3063. {
  3064. return llRezPrim(inventory, pos, vel, rot, param, false, true, true, true);
  3065. }
  3066. public void llLookAt(LSL_Vector target, double strength, double damping)
  3067. {
  3068. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3069. LookAt(target, strength, damping, m_host);
  3070. }
  3071. public void llLinkLookAt(LSL_Integer link, LSL_Vector target, double strength, double damping)
  3072. {
  3073. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3074. List<ISceneChildEntity> parts = GetLinkParts(link);
  3075. foreach (ISceneChildEntity part in parts)
  3076. LookAt(target, strength, damping, part);
  3077. }
  3078. private void LookAt(LSL_Vector target, double strength, double damping, ISceneChildEntity obj)
  3079. {
  3080. // Determine where we are looking from
  3081. LSL_Vector from = new LSL_Vector(obj.GetWorldPosition());
  3082. // Work out the normalised vector from the source to the target
  3083. LSL_Vector delta = llVecNorm(target - from);
  3084. LSL_Vector angle = new LSL_Vector(0, 0, 0)
  3085. {
  3086. x = llAtan2(delta.z, delta.y) - ScriptBaseClass.PI_BY_TWO,
  3087. y = llAtan2(delta.x, llSqrt((delta.y * delta.y) + (delta.z * delta.z)))
  3088. };
  3089. // Calculate the yaw
  3090. // subtracting PI_BY_TWO is required to compensate for the odd SL co-ordinate system
  3091. // Calculate pitch
  3092. // we need to convert from a vector describing
  3093. // the angles of rotation in radians into rotation value
  3094. LSL_Types.Quaternion rot = llEuler2Rot(angle);
  3095. //If the strength is 0, or we are non-physical, set the rotation
  3096. if (strength == 0 || obj.PhysActor == null || !obj.PhysActor.IsPhysical)
  3097. SetLinkRot(obj, rot);
  3098. else
  3099. obj.startLookAt(Rot2Quaternion(rot), (float)strength, (float)damping);
  3100. }
  3101. public void llRotLookAt(LSL_Rotation target, double strength, double damping)
  3102. {
  3103. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3104. Quaternion rot = new Quaternion((float)target.x, (float)target.y, (float)target.z, (float)target.s);
  3105. m_host.RotLookAt(rot, (float)strength, (float)damping);
  3106. }
  3107. public void llLinkRotLookAt(LSL_Integer link, LSL_Rotation target, double strength, double damping)
  3108. {
  3109. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3110. Quaternion rot = new Quaternion((float)target.x, (float)target.y, (float)target.z, (float)target.s);
  3111. List<ISceneChildEntity> parts = GetLinkParts(link);
  3112. foreach (ISceneChildEntity part in parts)
  3113. part.RotLookAt(rot, (float)strength, (float)damping);
  3114. }
  3115. public void llStopLookAt()
  3116. {
  3117. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3118. m_host.StopLookAt();
  3119. }
  3120. public void llSetTimerEvent(double sec)
  3121. {
  3122. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3123. if (sec != 0.0 && sec < m_MinTimerInterval)
  3124. sec = m_MinTimerInterval;
  3125. // Setting timer repeat
  3126. TimerPlugin timerPlugin = (TimerPlugin)m_ScriptEngine.GetScriptPlugin("Timer");
  3127. timerPlugin.SetTimerEvent(m_host.UUID, m_itemID, sec);
  3128. }
  3129. public virtual DateTime llSleep(double sec)
  3130. {
  3131. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return DateTime.Now;
  3132. return PScriptSleep((int)(sec * 1000));
  3133. }
  3134. public LSL_Float llGetObjectMass(string id)
  3135. {
  3136. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
  3137. UUID key = new UUID();
  3138. if (UUID.TryParse(id, out key))
  3139. {
  3140. try
  3141. {
  3142. ISceneChildEntity obj = World.GetSceneObjectPart(key);
  3143. if (obj != null)
  3144. return obj.GetMass();
  3145. // the object is null so the key is for an avatar
  3146. IScenePresence avatar = World.GetScenePresence(key);
  3147. if (avatar != null)
  3148. if (avatar.IsChildAgent)
  3149. // reference http://www.lslwiki.net/lslwiki/wakka.php?wakka=llGetObjectMass
  3150. // child agents have a mass of 1.0
  3151. return 1;
  3152. else
  3153. return avatar.PhysicsActor.Mass;
  3154. }
  3155. catch (KeyNotFoundException)
  3156. {
  3157. return 0; // The Object/Agent not in the region so just return zero
  3158. }
  3159. }
  3160. return 0;
  3161. }
  3162. public LSL_Float llGetMassMKS()
  3163. {
  3164. return llGetMass() * 100;
  3165. }
  3166. public LSL_Float llGetMass()
  3167. {
  3168. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
  3169. if (m_host.IsAttachment)
  3170. {
  3171. IScenePresence SP = m_host.ParentEntity.Scene.GetScenePresence(m_host.OwnerID);
  3172. return SP != null ? SP.PhysicsActor.Mass : 0.0;
  3173. }
  3174. return m_host.GetMass();
  3175. }
  3176. public void llCollisionFilter(string name, string id, int accept)
  3177. {
  3178. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3179. m_host.CollisionFilter.Clear();
  3180. m_host.CollisionFilter.Add(accept, id ?? name);
  3181. }
  3182. public void llTakeControls(int controls, int accept, int pass_on)
  3183. {
  3184. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3185. TaskInventoryItem item;
  3186. lock (m_host.TaskInventory)
  3187. {
  3188. if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
  3189. return;
  3190. item = m_host.TaskInventory[InventorySelf()];
  3191. }
  3192. if (item.PermsGranter != UUID.Zero)
  3193. {
  3194. IScenePresence presence = World.GetScenePresence(item.PermsGranter);
  3195. if (presence != null)
  3196. {
  3197. if ((item.PermsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0)
  3198. {
  3199. IScriptControllerModule m = presence.RequestModuleInterface<IScriptControllerModule>();
  3200. if (m != null)
  3201. m.RegisterControlEventsToScript(controls, accept, pass_on, m_host, m_itemID);
  3202. }
  3203. }
  3204. }
  3205. }
  3206. public void llReleaseControls()
  3207. {
  3208. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3209. TaskInventoryItem item;
  3210. lock (m_host.TaskInventory)
  3211. {
  3212. if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
  3213. return;
  3214. item = m_host.TaskInventory[InventorySelf()];
  3215. }
  3216. if (item.PermsGranter != UUID.Zero)
  3217. {
  3218. IScenePresence presence = World.GetScenePresence(item.PermsGranter);
  3219. if (presence != null)
  3220. {
  3221. if ((item.PermsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0)
  3222. {
  3223. // Unregister controls from Presence
  3224. IScriptControllerModule m = presence.RequestModuleInterface<IScriptControllerModule>();
  3225. if (m != null)
  3226. m.UnRegisterControlEventsToScript(m_localID, m_itemID);
  3227. // Remove Take Control permission.
  3228. item.PermsMask &= ~ScriptBaseClass.PERMISSION_TAKE_CONTROLS;
  3229. }
  3230. }
  3231. }
  3232. }
  3233. public void llReleaseURL(string url)
  3234. {
  3235. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3236. if (m_UrlModule != null)
  3237. m_UrlModule.ReleaseURL(url);
  3238. }
  3239. /// <summary>
  3240. /// Attach the object containing this script to the avatar that owns it.
  3241. /// </summary>
  3242. /// <returns>true if the attach suceeded, false if it did not</returns>
  3243. public bool AttachToAvatar(int attachmentPoint, bool temp)
  3244. {
  3245. var grp = (SceneObjectGroup) m_host.ParentEntity;
  3246. ScenePresence presence = (ScenePresence) World.GetScenePresence(m_host.OwnerID);
  3247. IAttachmentsModule attachmentsModule = World.RequestModuleInterface<IAttachmentsModule>();
  3248. if (attachmentsModule != null)
  3249. return attachmentsModule.AttachObjectFromInworldObject(m_localID, presence.ControllingClient, grp, attachmentPoint, temp);
  3250. else
  3251. return false;
  3252. }
  3253. /// <summary>
  3254. /// Detach the object containing this script from the avatar it is attached to.
  3255. /// </summary>
  3256. /// <remarks>
  3257. /// Nothing happens if the object is not attached.
  3258. /// </remarks>
  3259. public void DetachFromAvatar()
  3260. {
  3261. Util.FireAndForget(DetachWrapper, m_host);
  3262. }
  3263. private void DetachWrapper(object o)
  3264. {
  3265. SceneObjectPart host = (SceneObjectPart)o;
  3266. SceneObjectGroup grp = host.ParentGroup;
  3267. UUID itemID = grp.GroupID;
  3268. ScenePresence presence = (ScenePresence) World.GetScenePresence(host.OwnerID);
  3269. IAttachmentsModule attachmentsModule = World.RequestModuleInterface<IAttachmentsModule>();
  3270. if (attachmentsModule != null)
  3271. attachmentsModule.DetachSingleAttachmentToInventory(itemID, presence.ControllingClient);
  3272. }
  3273. public void llAttachToAvatarTemp(int attachmentPoint)
  3274. {
  3275. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3276. if (m_host.ParentEntity.RootChild.AttachmentPoint != 0)
  3277. return;
  3278. TaskInventoryItem item;
  3279. lock (m_host.TaskInventory)
  3280. {
  3281. if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
  3282. return;
  3283. item = m_host.TaskInventory[InventorySelf()];
  3284. }
  3285. if (item.PermsGranter != m_host.OwnerID)
  3286. return;
  3287. if ((item.NextPermissions & (uint)PermissionMask.Transfer) != (uint)PermissionMask.Transfer)
  3288. {
  3289. ShoutError("No permission to transfer");
  3290. return;
  3291. }
  3292. if ((item.PermsMask & ScriptBaseClass.PERMISSION_ATTACH) != 0)
  3293. {
  3294. AttachToAvatar(attachmentPoint, true);
  3295. }
  3296. }
  3297. public void llAttachToAvatar(int attachmentPoint)
  3298. {
  3299. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3300. if (m_host.ParentEntity.RootChild.AttachmentPoint != 0)
  3301. return;
  3302. TaskInventoryItem item;
  3303. lock (m_host.TaskInventory)
  3304. {
  3305. if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
  3306. return;
  3307. item = m_host.TaskInventory[InventorySelf()];
  3308. }
  3309. if (item.PermsGranter != m_host.OwnerID)
  3310. return;
  3311. if ((item.PermsMask & ScriptBaseClass.PERMISSION_ATTACH) != 0)
  3312. {
  3313. AttachToAvatar(attachmentPoint, false);
  3314. }
  3315. }
  3316. public void llDetachFromAvatar()
  3317. {
  3318. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3319. if (m_host.ParentEntity.RootChild.AttachmentPoint == 0)
  3320. return;
  3321. TaskInventoryItem item;
  3322. lock (m_host.TaskInventory)
  3323. {
  3324. if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
  3325. return;
  3326. item = m_host.TaskInventory[InventorySelf()];
  3327. }
  3328. if (item.PermsGranter != m_host.OwnerID)
  3329. return;
  3330. if ((item.PermsMask & ScriptBaseClass.PERMISSION_ATTACH) != 0)
  3331. DetachFromAvatar();
  3332. }
  3333. public void llTakeCamera(string avatar)
  3334. {
  3335. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3336. Deprecated("llTakeCamera");
  3337. }
  3338. public void llReleaseCamera(string avatar)
  3339. {
  3340. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3341. Deprecated("llReleaseCamera");
  3342. llClearCameraParams();
  3343. }
  3344. public LSL_String llGetOwner()
  3345. {
  3346. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_String();
  3347. return m_host.OwnerID.ToString();
  3348. }
  3349. public DateTime llInstantMessage(string user, string message)
  3350. {
  3351. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return DateTime.Now;
  3352. // We may be able to use ClientView.SendInstantMessage here, but we need a client instance.
  3353. // InstantMessageModule.OnInstantMessage searches through a list of scenes for a client matching the toAgent,
  3354. // but I don't think we have a list of scenes available from here.
  3355. // (We also don't want to duplicate the code in OnInstantMessage if we can avoid it.)
  3356. UUID friendTransactionID = UUID.Random();
  3357. GridInstantMessage msg = new GridInstantMessage
  3358. {
  3359. fromAgentID = m_host.UUID,
  3360. toAgentID = UUID.Parse(user),
  3361. imSessionID = friendTransactionID,
  3362. fromAgentName = m_host.Name
  3363. };
  3364. // This is the item we're mucking with here
  3365. // Cap the message length at 1024.
  3366. if (message != null && message.Length > 1024)
  3367. msg.message = message.Substring(0, 1024);
  3368. else
  3369. msg.message = message;
  3370. msg.dialog = (byte)InstantMessageDialog.MessageFromObject;
  3371. msg.fromGroup = false;
  3372. msg.offline = 0;
  3373. msg.ParentEstateID = 0;
  3374. msg.Position = m_host.AbsolutePosition;
  3375. msg.RegionID = World.RegionInfo.RegionID;
  3376. msg.binaryBucket
  3377. = Util.StringToBytes256(
  3378. "{0}/{1}/{2}/{3}",
  3379. World.RegionInfo.RegionName,
  3380. (int)Math.Floor(m_host.AbsolutePosition.X),
  3381. (int)Math.Floor(m_host.AbsolutePosition.Y),
  3382. (int)Math.Floor(m_host.AbsolutePosition.Z));
  3383. if (m_TransferModule != null)
  3384. {
  3385. m_TransferModule.SendInstantMessage(msg);
  3386. }
  3387. return PScriptSleep(2000);
  3388. }
  3389. public DateTime llEmail(string address, string subject, string message)
  3390. {
  3391. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.Low, "llEmail", m_host, "LSL", m_itemID)) return DateTime.Now;
  3392. IEmailModule emailModule = World.RequestModuleInterface<IEmailModule>();
  3393. if (emailModule == null)
  3394. {
  3395. ShoutError("llEmail: email module not configured");
  3396. return DateTime.Now;
  3397. }
  3398. emailModule.SendEmail(m_host.UUID, address, subject, message, World);
  3399. return PScriptSleep(20000);
  3400. }
  3401. public void llGetNextEmail(string address, string subject)
  3402. {
  3403. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3404. IEmailModule emailModule = World.RequestModuleInterface<IEmailModule>();
  3405. if (emailModule == null)
  3406. {
  3407. ShoutError("llGetNextEmail: email module not configured");
  3408. return;
  3409. }
  3410. emailModule.GetNextEmailAsync(m_host.UUID, address, subject, email =>
  3411. {
  3412. if (email == null)
  3413. return;
  3414. m_ScriptEngine.PostScriptEvent(m_itemID, m_host.UUID, "email",
  3415. new Object[] {
  3416. new LSL_String(email.time),
  3417. new LSL_String(email.sender),
  3418. new LSL_String(email.subject),
  3419. new LSL_String(email.message),
  3420. new LSL_Integer(email.numLeft)}
  3421. );
  3422. }, World);
  3423. }
  3424. public LSL_String llGetKey()
  3425. {
  3426. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  3427. return m_host.UUID.ToString();
  3428. }
  3429. public void llSetBuoyancy(double buoyancy)
  3430. {
  3431. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3432. if (m_host.ParentEntity != null)
  3433. {
  3434. if (!m_host.ParentEntity.IsDeleted)
  3435. {
  3436. m_host.ParentEntity.RootChild.SetBuoyancy((float)buoyancy);
  3437. }
  3438. }
  3439. }
  3440. /// <summary>
  3441. /// Attempt to clamp the object on the Z axis at the given height over tau seconds.
  3442. /// </summary>
  3443. /// <param name="height">Height to hover. Height of zero disables hover.</param>
  3444. /// <param name="water">False if height is calculated just from ground, otherwise uses ground or water depending on whichever is higher</param>
  3445. /// <param name="tau">Number of seconds over which to reach target</param>
  3446. public void llSetHoverHeight(double height, int water, double tau)
  3447. {
  3448. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3449. if (m_host.PhysActor != null)
  3450. {
  3451. PIDHoverType hoverType = PIDHoverType.Ground;
  3452. if (water != 0)
  3453. {
  3454. hoverType = PIDHoverType.GroundAndWater;
  3455. }
  3456. m_host.SetHoverHeight((float)height, hoverType, (float)tau);
  3457. }
  3458. }
  3459. public void llStopHover()
  3460. {
  3461. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3462. if (m_host.PhysActor != null)
  3463. {
  3464. m_host.SetHoverHeight(0f, PIDHoverType.Ground, 0f);
  3465. }
  3466. }
  3467. public void llMinEventDelay(double delay)
  3468. {
  3469. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3470. m_ScriptEngine.SetMinEventDelay(m_itemID, m_host.UUID, delay);
  3471. }
  3472. /// <summary>
  3473. /// llSoundPreload is deprecated. In SL this appears to do absolutely nothing
  3474. /// and is documented to have no delay.
  3475. /// </summary>
  3476. public void llSoundPreload(string sound)
  3477. {
  3478. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3479. }
  3480. public LSL_Integer llStringLength(string str)
  3481. {
  3482. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  3483. if (str.Length > 0)
  3484. {
  3485. return str.Length;
  3486. }
  3487. return 0;
  3488. }
  3489. public void llStartAnimation(string anim)
  3490. {
  3491. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3492. UUID invItemID = InventorySelf();
  3493. if (invItemID == UUID.Zero)
  3494. return;
  3495. TaskInventoryItem item;
  3496. lock (m_host.TaskInventory)
  3497. {
  3498. if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
  3499. return;
  3500. item = m_host.TaskInventory[InventorySelf()];
  3501. }
  3502. if (item.PermsGranter == UUID.Zero)
  3503. return;
  3504. if ((item.PermsMask & ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION) != 0)
  3505. {
  3506. IScenePresence presence = World.GetScenePresence(item.PermsGranter);
  3507. if (presence != null)
  3508. {
  3509. // Do NOT try to parse UUID, animations cannot be triggered by ID
  3510. UUID animID = InventoryKey(anim, (int)AssetType.Animation);
  3511. if (animID == UUID.Zero)
  3512. {
  3513. if (UUID.TryParse(anim, out animID))
  3514. presence.Animator.AddAnimation(animID, m_host.UUID);
  3515. else
  3516. {
  3517. bool RetVal = presence.Animator.AddAnimation(anim, m_host.UUID);
  3518. if (!RetVal)
  3519. {
  3520. IChatModule chatModule = World.RequestModuleInterface<IChatModule>();
  3521. if (chatModule != null)
  3522. chatModule.SimChat("Could not find animation '" + anim + "'.",
  3523. ChatTypeEnum.DebugChannel, 2147483647, m_host.AbsolutePosition,
  3524. m_host.Name, m_host.UUID, false, World);
  3525. }
  3526. }
  3527. }
  3528. else
  3529. presence.Animator.AddAnimation(animID, m_host.UUID);
  3530. }
  3531. }
  3532. }
  3533. public void llStopAnimation(string anim)
  3534. {
  3535. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3536. UUID invItemID = InventorySelf();
  3537. if (invItemID == UUID.Zero)
  3538. return;
  3539. TaskInventoryItem item;
  3540. lock (m_host.TaskInventory)
  3541. {
  3542. if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
  3543. return;
  3544. item = m_host.TaskInventory[InventorySelf()];
  3545. }
  3546. if (item.PermsGranter == UUID.Zero)
  3547. return;
  3548. if ((item.PermsMask & ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION) != 0)
  3549. {
  3550. UUID animID = new UUID();
  3551. if (!UUID.TryParse(anim, out animID))
  3552. {
  3553. animID = InventoryKey(anim, false);
  3554. }
  3555. IScenePresence presence = World.GetScenePresence(item.PermsGranter);
  3556. if (presence != null)
  3557. {
  3558. if (animID == UUID.Zero)
  3559. {
  3560. if (UUID.TryParse(anim, out animID))
  3561. presence.Animator.RemoveAnimation(animID);
  3562. else
  3563. {
  3564. bool RetVal = presence.Animator.RemoveAnimation(anim);
  3565. if (!RetVal)
  3566. {
  3567. IChatModule chatModule = World.RequestModuleInterface<IChatModule>();
  3568. if (chatModule != null)
  3569. chatModule.SimChat("Could not find animation '" + anim + "'.",
  3570. ChatTypeEnum.DebugChannel, 2147483647, m_host.AbsolutePosition,
  3571. m_host.Name, m_host.UUID, false, World);
  3572. }
  3573. }
  3574. }
  3575. else
  3576. presence.Animator.RemoveAnimation(animID);
  3577. }
  3578. }
  3579. }
  3580. public void llPointAt(LSL_Vector pos)
  3581. {
  3582. }
  3583. public void llStopPointAt()
  3584. {
  3585. }
  3586. public void llTargetOmega(LSL_Vector axis, LSL_Float spinrate, LSL_Float gain)
  3587. {
  3588. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3589. m_host.OmegaAxis = new Vector3((float)axis.x, (float)axis.y, (float)axis.z);
  3590. m_host.OmegaGain = gain;
  3591. m_host.OmegaSpinRate = spinrate;
  3592. m_host.GenerateRotationalVelocityFromOmega();
  3593. ScriptData script = ScriptProtection.GetScript(m_itemID);
  3594. if (script != null)
  3595. script.TargetOmegaWasSet = true;
  3596. m_host.ScheduleTerseUpdate();
  3597. //m_host.SendTerseUpdateToAllClients();
  3598. }
  3599. public LSL_Integer llGetStartParameter()
  3600. {
  3601. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  3602. return m_ScriptEngine.GetStartParameter(m_itemID, m_host.UUID);
  3603. }
  3604. public void llGodLikeRezObject(string inventory, LSL_Vector pos)
  3605. {
  3606. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3607. if (m_ScriptEngine.Config.GetBoolean("AllowGodFunctions", false))
  3608. {
  3609. if (World.Permissions.CanRunConsoleCommand(m_host.OwnerID))
  3610. {
  3611. AssetBase asset = World.AssetService.Get(inventory);
  3612. SceneObjectGroup group
  3613. = SceneObjectSerializer.FromOriginalXmlFormat(UUID.Zero, Utils.BytesToString(asset.Data), World);
  3614. if (group == null)
  3615. return;
  3616. group.IsDeleted = false;
  3617. group.m_isLoaded = true;
  3618. foreach (SceneObjectPart part in group.ChildrenList)
  3619. {
  3620. part.IsLoading = false;
  3621. }
  3622. group.OwnerID = m_host.OwnerID;
  3623. group.RootPart.AddFlag(PrimFlags.CreateSelected);
  3624. // If we're rezzing an attachment then don't ask AddNewSceneObject() to update the client since
  3625. // we'll be doing that later on. Scheduling more than one full update during the attachment
  3626. // process causes some clients to fail to display the attachment properly.
  3627. World.SceneGraph.AddPrimToScene(group);
  3628. // if attachment we set it's asset id so object updates can reflect that
  3629. // if not, we set it's position in world.
  3630. group.AbsolutePosition = new Vector3((float)pos.x, (float)pos.y, (float)pos.z);
  3631. IScenePresence SP = World.GetScenePresence(m_host.OwnerID);
  3632. if (SP != null)
  3633. group.SetGroup(m_host.GroupID, SP.UUID, false);
  3634. if (group.RootPart.Shape.PCode == (byte)PCode.Prim)
  3635. group.ClearPartAttachmentData();
  3636. // Fire on_rez
  3637. group.CreateScriptInstances(0, true, StateSource.ScriptedRez, UUID.Zero, false);
  3638. group.ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate);
  3639. }
  3640. }
  3641. }
  3642. public void llRequestPermissions(string agent, int perm)
  3643. {
  3644. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3645. UUID agentID = new UUID();
  3646. if (!UUID.TryParse(agent, out agentID))
  3647. return;
  3648. UUID invItemID = InventorySelf();
  3649. if (invItemID == UUID.Zero)
  3650. return; // Not in a prim? How??
  3651. TaskInventoryItem item;
  3652. lock (m_host.TaskInventory)
  3653. {
  3654. item = m_host.TaskInventory[invItemID];
  3655. }
  3656. if (agentID == UUID.Zero || perm == 0) // Releasing permissions
  3657. {
  3658. llReleaseControls();
  3659. item.PermsGranter = UUID.Zero;
  3660. item.PermsMask = 0;
  3661. m_ScriptEngine.PostScriptEvent(m_itemID, m_host.UUID, new EventParams(
  3662. "run_time_permissions", new Object[] {
  3663. new LSL_Integer(0) },
  3664. new DetectParams[0]), EventPriority.FirstStart);
  3665. return;
  3666. }
  3667. if (item.PermsGranter != agentID || (perm & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0)
  3668. llReleaseControls();
  3669. if (m_host.ParentEntity.IsAttachment && (UUID)agent == m_host.ParentEntity.RootChild.AttachedAvatar)
  3670. {
  3671. // When attached, certain permissions are implicit if requested from owner
  3672. int implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS |
  3673. ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
  3674. ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
  3675. ScriptBaseClass.PERMISSION_ATTACH |
  3676. ScriptBaseClass.PERMISSION_TRACK_CAMERA;
  3677. if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
  3678. {
  3679. lock (m_host.TaskInventory)
  3680. {
  3681. m_host.TaskInventory[invItemID].PermsGranter = agentID;
  3682. m_host.TaskInventory[invItemID].PermsMask = perm;
  3683. }
  3684. m_ScriptEngine.PostScriptEvent(m_itemID, m_host.UUID, new EventParams(
  3685. "run_time_permissions", new Object[] {
  3686. new LSL_Integer(perm) },
  3687. new DetectParams[0]), EventPriority.FirstStart);
  3688. return;
  3689. }
  3690. }
  3691. else if (m_host.ParentEntity.SitTargetAvatar.Contains(agentID)) // Sitting avatar
  3692. {
  3693. // When agent is sitting, certain permissions are implicit if requested from sitting agent
  3694. int implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
  3695. ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
  3696. ScriptBaseClass.PERMISSION_TRACK_CAMERA |
  3697. ScriptBaseClass.PERMISSION_TAKE_CONTROLS;
  3698. if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
  3699. {
  3700. lock (m_host.TaskInventory)
  3701. {
  3702. m_host.TaskInventory[invItemID].PermsGranter = agentID;
  3703. m_host.TaskInventory[invItemID].PermsMask = perm;
  3704. }
  3705. m_ScriptEngine.PostScriptEvent(m_itemID, m_host.UUID, new EventParams(
  3706. "run_time_permissions", new Object[] {
  3707. new LSL_Integer(perm) },
  3708. new DetectParams[0]), EventPriority.FirstStart);
  3709. return;
  3710. }
  3711. }
  3712. IScenePresence presence = World.GetScenePresence(agentID);
  3713. if (presence != null)
  3714. {
  3715. string ownerName = "";
  3716. IScenePresence ownerPresence = World.GetScenePresence(m_host.ParentEntity.RootChild.OwnerID);
  3717. ownerName = ownerPresence == null ? resolveName(m_host.OwnerID) : ownerPresence.Name;
  3718. if (ownerName == String.Empty)
  3719. ownerName = "(hippos)";
  3720. if (!m_waitingForScriptAnswer)
  3721. {
  3722. lock (m_host.TaskInventory)
  3723. {
  3724. m_host.TaskInventory[invItemID].PermsGranter = agentID;
  3725. m_host.TaskInventory[invItemID].PermsMask = 0;
  3726. }
  3727. presence.ControllingClient.OnScriptAnswer += handleScriptAnswer;
  3728. m_waitingForScriptAnswer = true;
  3729. }
  3730. presence.ControllingClient.SendScriptQuestion(
  3731. m_host.UUID, m_host.ParentEntity.RootChild.Name, ownerName, invItemID, perm);
  3732. return;
  3733. }
  3734. // Requested agent is not in range, refuse perms
  3735. m_ScriptEngine.PostScriptEvent(m_itemID, m_host.UUID, new EventParams(
  3736. "run_time_permissions", new Object[] {
  3737. new LSL_Integer(0) },
  3738. new DetectParams[0]), EventPriority.FirstStart);
  3739. }
  3740. void handleScriptAnswer(IClientAPI client, UUID taskID, UUID itemID, int answer)
  3741. {
  3742. if (taskID != m_host.UUID)
  3743. return;
  3744. UUID invItemID = InventorySelf();
  3745. if (invItemID == UUID.Zero)
  3746. return;
  3747. client.OnScriptAnswer -= handleScriptAnswer;
  3748. m_waitingForScriptAnswer = false;
  3749. if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0)
  3750. llReleaseControls();
  3751. lock (m_host.TaskInventory)
  3752. {
  3753. m_host.TaskInventory[invItemID].PermsMask = answer;
  3754. }
  3755. m_ScriptEngine.PostScriptEvent(m_itemID, m_host.UUID, new EventParams(
  3756. "run_time_permissions", new Object[] {
  3757. new LSL_Integer(answer) },
  3758. new DetectParams[0]), EventPriority.FirstStart);
  3759. }
  3760. public LSL_String llGetPermissionsKey()
  3761. {
  3762. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  3763. lock (m_host.TaskInventory)
  3764. {
  3765. foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
  3766. {
  3767. if (item.Type == 10 && item.ItemID == m_itemID)
  3768. {
  3769. return item.PermsGranter.ToString();
  3770. }
  3771. }
  3772. }
  3773. return UUID.Zero.ToString();
  3774. }
  3775. public LSL_Integer llGetPermissions()
  3776. {
  3777. lock (m_host.TaskInventory)
  3778. {
  3779. foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
  3780. {
  3781. if (item.Type == 10 && item.ItemID == m_itemID)
  3782. {
  3783. int perms = item.PermsMask;
  3784. if (m_automaticLinkPermission)
  3785. perms |= ScriptBaseClass.PERMISSION_CHANGE_LINKS;
  3786. return perms;
  3787. }
  3788. }
  3789. }
  3790. return 0;
  3791. }
  3792. public LSL_Integer llGetLinkNumber()
  3793. {
  3794. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  3795. if (m_host.ParentEntity.ChildrenEntities().Count > 1)
  3796. {
  3797. return m_host.LinkNum;
  3798. }
  3799. return 0;
  3800. }
  3801. public void llSetLinkColor(int linknumber, LSL_Vector color, int face)
  3802. {
  3803. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3804. List<ISceneChildEntity> parts = GetLinkParts(linknumber);
  3805. foreach (ISceneChildEntity part in parts)
  3806. part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face);
  3807. }
  3808. public DateTime llCreateLink(string target, int parent)
  3809. {
  3810. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  3811. return DateTime.Now;
  3812. UUID invItemID = InventorySelf();
  3813. UUID targetID;
  3814. if (!UUID.TryParse(target, out targetID))
  3815. return DateTime.Now;
  3816. TaskInventoryItem item;
  3817. lock (m_host.TaskInventory)
  3818. {
  3819. item = m_host.TaskInventory[invItemID];
  3820. }
  3821. if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
  3822. && !m_automaticLinkPermission)
  3823. {
  3824. ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
  3825. return DateTime.Now;
  3826. }
  3827. IClientAPI client = null;
  3828. IScenePresence sp = World.GetScenePresence(item.PermsGranter);
  3829. if (sp != null)
  3830. client = sp.ControllingClient;
  3831. ISceneChildEntity targetPart = World.GetSceneObjectPart(targetID);
  3832. if (targetPart.ParentEntity.RootChild.AttachmentPoint != 0)
  3833. return DateTime.Now;
  3834. // Fail silently if attached
  3835. ISceneEntity parentPrim = null;
  3836. ISceneEntity childPrim = null;
  3837. if (parent != 0)
  3838. {
  3839. parentPrim = m_host.ParentEntity;
  3840. childPrim = targetPart.ParentEntity;
  3841. }
  3842. else
  3843. {
  3844. parentPrim = targetPart.ParentEntity;
  3845. childPrim = m_host.ParentEntity;
  3846. }
  3847. // byte uf = childPrim.RootPart.UpdateFlag;
  3848. parentPrim.LinkToGroup(childPrim);
  3849. // if (uf != (Byte)0)
  3850. // parent.RootPart.UpdateFlag = uf;
  3851. parentPrim.TriggerScriptChangedEvent(Changed.LINK);
  3852. parentPrim.RootChild.CreateSelected = true;
  3853. parentPrim.ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate);
  3854. if (client != null)
  3855. parentPrim.GetProperties(client);
  3856. return PScriptSleep(1000);
  3857. }
  3858. public void llBreakLink(int linknum)
  3859. {
  3860. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3861. UUID invItemID = InventorySelf();
  3862. lock (m_host.TaskInventory)
  3863. {
  3864. if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
  3865. && !m_automaticLinkPermission)
  3866. {
  3867. ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
  3868. return;
  3869. }
  3870. }
  3871. if (linknum < ScriptBaseClass.LINK_THIS)
  3872. return;
  3873. ISceneEntity parentPrim = m_host.ParentEntity;
  3874. if (parentPrim.RootChild.AttachmentPoint != 0)
  3875. return; // Fail silently if attached
  3876. ISceneChildEntity childPrim = null;
  3877. if (linknum == ScriptBaseClass.LINK_ROOT)
  3878. {
  3879. }
  3880. else if (linknum == ScriptBaseClass.LINK_SET ||
  3881. ScriptBaseClass.LINK_ALL_OTHERS ||
  3882. ScriptBaseClass.LINK_ALL_CHILDREN ||
  3883. ScriptBaseClass.LINK_THIS)
  3884. {
  3885. foreach (ISceneChildEntity part in parentPrim.ChildrenEntities())
  3886. {
  3887. if (part.UUID != m_host.UUID)
  3888. {
  3889. childPrim = part;
  3890. break;
  3891. }
  3892. }
  3893. }
  3894. else
  3895. {
  3896. IEntity target = m_host.ParentEntity.GetLinkNumPart(linknum);
  3897. if (target is ISceneChildEntity)
  3898. {
  3899. childPrim = target as ISceneChildEntity;
  3900. }
  3901. else
  3902. return;
  3903. if (childPrim.UUID == m_host.UUID)
  3904. childPrim = null;
  3905. }
  3906. if (linknum == ScriptBaseClass.LINK_ROOT)
  3907. {
  3908. // Restructuring Multiple Prims.
  3909. List<ISceneChildEntity> parts = new List<ISceneChildEntity>(parentPrim.ChildrenEntities());
  3910. parts.Remove(parentPrim.RootChild);
  3911. foreach (ISceneChildEntity part in parts)
  3912. {
  3913. parentPrim.DelinkFromGroup(part, true);
  3914. }
  3915. parentPrim.ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate);
  3916. parentPrim.TriggerScriptChangedEvent(Changed.LINK);
  3917. if (parts.Count > 0)
  3918. {
  3919. ISceneChildEntity newRoot = parts[0];
  3920. parts.Remove(newRoot);
  3921. foreach (ISceneChildEntity part in parts)
  3922. {
  3923. newRoot.ParentEntity.LinkToGroup(part.ParentEntity);
  3924. }
  3925. newRoot.ParentEntity.ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate);
  3926. }
  3927. }
  3928. else
  3929. {
  3930. if (childPrim == null)
  3931. return;
  3932. parentPrim.DelinkFromGroup(childPrim, true);
  3933. childPrim.ParentEntity.ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate);
  3934. parentPrim.ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate);
  3935. parentPrim.TriggerScriptChangedEvent(Changed.LINK);
  3936. }
  3937. }
  3938. public void llBreakAllLinks()
  3939. {
  3940. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3941. ISceneEntity parentPrim = m_host.ParentEntity;
  3942. if (parentPrim.RootChild.AttachmentPoint != 0)
  3943. return; // Fail silently if attached
  3944. List<ISceneChildEntity> parts = new List<ISceneChildEntity>(parentPrim.ChildrenEntities());
  3945. parts.Remove(parentPrim.RootChild);
  3946. foreach (ISceneChildEntity part in parts)
  3947. {
  3948. parentPrim.DelinkFromGroup(part, true);
  3949. parentPrim.TriggerScriptChangedEvent(Changed.LINK);
  3950. part.ParentEntity.ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate);
  3951. }
  3952. parentPrim.ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate);
  3953. }
  3954. public LSL_String llGetLinkKey(int linknum)
  3955. {
  3956. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  3957. IEntity target = m_host.ParentEntity.GetLinkNumPart(linknum);
  3958. if (target != null)
  3959. {
  3960. return target.UUID.ToString();
  3961. }
  3962. return UUID.Zero.ToString();
  3963. }
  3964. /// <summary>
  3965. /// The rules governing the returned name are not simple. The only
  3966. /// time a blank name is returned is if the target prim has a blank
  3967. /// name. If no prim with the given link number can be found then
  3968. /// usually NULL_KEY is returned but there are exceptions.
  3969. ///
  3970. /// In a single unlinked prim, A call with 0 returns the name, all
  3971. /// other values for link number return NULL_KEY
  3972. ///
  3973. /// In link sets it is more complicated.
  3974. ///
  3975. /// If the script is in the root prim:-
  3976. /// A zero link number returns NULL_KEY.
  3977. /// Positive link numbers return the name of the prim, or NULL_KEY
  3978. /// if a prim does not exist at that position.
  3979. /// Negative link numbers return the name of the first child prim.
  3980. ///
  3981. /// If the script is in a child prim:-
  3982. /// Link numbers 0 or 1 return the name of the root prim.
  3983. /// Positive link numbers return the name of the prim or NULL_KEY
  3984. /// if a prim does not exist at that position.
  3985. /// Negative numbers return the name of the root prim.
  3986. ///
  3987. /// References
  3988. /// http://lslwiki.net/lslwiki/wakka.php?wakka=llGetLinkName
  3989. /// Mentions NULL_KEY being returned
  3990. /// http://wiki.secondlife.com/wiki/LlGetLinkName
  3991. /// Mentions using the LINK_* constants, some of which are negative
  3992. /// </summary>
  3993. public LSL_String llGetLinkName(int linknum)
  3994. {
  3995. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  3996. // simplest case, this prims link number
  3997. if (linknum == m_host.LinkNum)
  3998. return m_host.Name;
  3999. // Single prim
  4000. if (m_host.LinkNum == 0)
  4001. {
  4002. if (linknum == 1)
  4003. return m_host.Name;
  4004. IEntity entity = m_host.ParentEntity.GetLinkNumPart(linknum);
  4005. if (entity != null)
  4006. return entity.Name;
  4007. return UUID.Zero.ToString();
  4008. }
  4009. // Link set
  4010. IEntity part = null;
  4011. part = m_host.LinkNum == 1 ? m_host.ParentEntity.GetLinkNumPart(linknum < 0 ? 2 : linknum) : m_host.ParentEntity.GetLinkNumPart(linknum < 2 ? 1 : linknum);
  4012. if (part != null)
  4013. return part.Name;
  4014. return UUID.Zero.ToString();
  4015. }
  4016. public LSL_Integer llGetInventoryNumber(int type)
  4017. {
  4018. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  4019. int count = 0;
  4020. lock (m_host.TaskInventory)
  4021. {
  4022. #if (!ISWIN)
  4023. foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
  4024. if (item.Type == type || type == -1)
  4025. count++;
  4026. #else
  4027. count += m_host.TaskInventory.Values.Count(item => item.Type == type || type == -1);
  4028. #endif
  4029. }
  4030. return count;
  4031. }
  4032. public LSL_String llGetInventoryName(int type, int number)
  4033. {
  4034. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  4035. ArrayList keys = new ArrayList();
  4036. lock (m_host.TaskInventory)
  4037. {
  4038. foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
  4039. {
  4040. if (inv.Value.Type == type || type == -1)
  4041. {
  4042. keys.Add(inv.Value.Name);
  4043. }
  4044. }
  4045. }
  4046. if (keys.Count == 0)
  4047. return String.Empty;
  4048. keys.Sort();
  4049. if (keys.Count > number)
  4050. {
  4051. return (string)keys[number];
  4052. }
  4053. return String.Empty;
  4054. }
  4055. public LSL_Float llGetEnergy()
  4056. {
  4057. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
  4058. return 1.0f;
  4059. }
  4060. public DateTime llGiveInventory(string destination, string inventory)
  4061. {
  4062. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return DateTime.Now;
  4063. bool found = false;
  4064. UUID destId = UUID.Zero;
  4065. UUID objId = UUID.Zero;
  4066. int assetType = 0;
  4067. string objName = String.Empty;
  4068. if (!UUID.TryParse(destination, out destId))
  4069. {
  4070. llSay(0, "Could not parse key " + destination);
  4071. return DateTime.Now;
  4072. }
  4073. // move the first object found with this inventory name
  4074. lock (m_host.TaskInventory)
  4075. {
  4076. foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
  4077. {
  4078. if (inv.Value.Name == inventory)
  4079. {
  4080. found = true;
  4081. objId = inv.Key;
  4082. assetType = inv.Value.Type;
  4083. objName = inv.Value.Name;
  4084. break;
  4085. }
  4086. }
  4087. }
  4088. if (!found)
  4089. {
  4090. llSay(0, String.Format("Could not find object '{0}'", inventory));
  4091. throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory));
  4092. }
  4093. // check if destination is an avatar
  4094. if (World.GetScenePresence(destId) != null || m_host.ParentEntity.Scene.RequestModuleInterface<IAgentInfoService>().GetUserInfo(destId.ToString()) != null)
  4095. {
  4096. // destination is an avatar
  4097. InventoryItemBase agentItem = null;
  4098. ILLClientInventory inventoryModule = World.RequestModuleInterface<ILLClientInventory>();
  4099. if (inventoryModule != null)
  4100. agentItem = inventoryModule.MoveTaskInventoryItemToUserInventory(destId, UUID.Zero, m_host, objId, false);
  4101. if (agentItem == null)
  4102. return DateTime.Now;
  4103. byte[] bucket = new byte[17];
  4104. bucket[0] = (byte)assetType;
  4105. byte[] objBytes = agentItem.ID.GetBytes();
  4106. Array.Copy(objBytes, 0, bucket, 1, 16);
  4107. GridInstantMessage msg = new GridInstantMessage(World,
  4108. m_host.UUID, m_host.Name + ", an object owned by " +
  4109. resolveName(m_host.OwnerID) + ",", destId,
  4110. (byte)InstantMessageDialog.InventoryOffered,
  4111. false, objName + "'\n'" + m_host.Name + "' is located at " +
  4112. m_host.AbsolutePosition.ToString() + " in '" + World.RegionInfo.RegionName,
  4113. agentItem.ID, true, m_host.AbsolutePosition,
  4114. bucket);
  4115. if (m_TransferModule != null)
  4116. m_TransferModule.SendInstantMessage(msg);
  4117. }
  4118. else
  4119. {
  4120. // destination is an object
  4121. ILLClientInventory inventoryModule = World.RequestModuleInterface<ILLClientInventory>();
  4122. if (inventoryModule != null)
  4123. inventoryModule.MoveTaskInventoryItemToObject(destId, m_host, objId);
  4124. }
  4125. return PScriptSleep(3000);
  4126. }
  4127. public void llRemoveInventory(string name)
  4128. {
  4129. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  4130. lock (m_host.TaskInventory)
  4131. {
  4132. foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
  4133. {
  4134. if (item.Name == name)
  4135. {
  4136. if (item.ItemID == m_itemID)
  4137. throw new ScriptDeleteException();
  4138. m_host.Inventory.RemoveInventoryItem(item.ItemID);
  4139. return;
  4140. }
  4141. }
  4142. }
  4143. }
  4144. public void llSetText(string text, LSL_Vector color, LSL_Float alpha)
  4145. {
  4146. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  4147. Vector3 av3 = new Vector3(Util.Clip((float)color.x, 0.0f, 1.0f),
  4148. Util.Clip((float)color.y, 0.0f, 1.0f),
  4149. Util.Clip((float)color.z, 0.0f, 1.0f));
  4150. m_host.SetText(text.Length > 254 ? text.Remove(254) : text, av3, Util.Clip((float)alpha, 0.0f, 1.0f));
  4151. //m_host.ParentGroup.HasGroupChanged = true;
  4152. //m_host.ParentGroup.ScheduleGroupForFullUpdate();
  4153. }
  4154. public LSL_Float llWater(LSL_Vector offset)
  4155. {
  4156. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
  4157. return World.RegionInfo.RegionSettings.WaterHeight;
  4158. }
  4159. public void llPassTouches(int pass)
  4160. {
  4161. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  4162. m_host.PassTouch = pass;
  4163. }
  4164. public LSL_Key llRequestAgentData(string id, int data)
  4165. {
  4166. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  4167. UUID uuid = (UUID)id;
  4168. UserInfo pinfo = null;
  4169. UserAccount account;
  4170. UserInfoCacheEntry ce;
  4171. if (!m_userInfoCache.TryGetValue(uuid, out ce))
  4172. {
  4173. account = World.UserAccountService.GetUserAccount(World.RegionInfo.AllScopeIDs, uuid);
  4174. if (account == null)
  4175. {
  4176. m_userInfoCache[uuid] = null; // Cache negative
  4177. return UUID.Zero.ToString();
  4178. }
  4179. ce = new UserInfoCacheEntry { time = Util.EnvironmentTickCount(), account = account };
  4180. pinfo = World.RequestModuleInterface<IAgentInfoService>().GetUserInfo(uuid.ToString());
  4181. ce.pinfo = pinfo;
  4182. m_userInfoCache[uuid] = ce;
  4183. }
  4184. else
  4185. {
  4186. if (ce == null)
  4187. {
  4188. return UUID.Zero.ToString();
  4189. }
  4190. account = ce.account;
  4191. pinfo = ce.pinfo;
  4192. }
  4193. if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) >= 20000)
  4194. {
  4195. ce.time = Util.EnvironmentTickCount();
  4196. ce.pinfo = World.RequestModuleInterface<IAgentInfoService>().GetUserInfo(uuid.ToString());
  4197. pinfo = ce.pinfo;
  4198. }
  4199. string reply = String.Empty;
  4200. switch (data)
  4201. {
  4202. case 1: // DATA_ONLINE (0|1)
  4203. if (pinfo != null && pinfo.IsOnline)
  4204. reply = "1";
  4205. else
  4206. reply = "0";
  4207. break;
  4208. case 2: // DATA_NAME (First Last)
  4209. reply = account.Name;
  4210. break;
  4211. case 3: // DATA_BORN (YYYY-MM-DD)
  4212. DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0);
  4213. born = born.AddSeconds(account.Created);
  4214. reply = born.ToString("yyyy-MM-dd");
  4215. break;
  4216. case 4: // DATA_RATING (0,0,0,0,0,0)
  4217. reply = "0,0,0,0,0,0";
  4218. break;
  4219. case 8: // DATA_PAYINFO (0|1|2|3)
  4220. if ((account.UserFlags & ScriptBaseClass.PAYMENT_INFO_ON_FILE) == ScriptBaseClass.PAYMENT_INFO_ON_FILE)
  4221. reply = ScriptBaseClass.PAYMENT_INFO_ON_FILE.ToString();
  4222. if ((account.UserFlags & ScriptBaseClass.PAYMENT_INFO_USED) == ScriptBaseClass.PAYMENT_INFO_USED)
  4223. reply = ScriptBaseClass.PAYMENT_INFO_USED.ToString();
  4224. reply = "0";
  4225. break;
  4226. default:
  4227. return UUID.Zero.ToString(); // Raise no event
  4228. }
  4229. UUID rq = UUID.Random();
  4230. DataserverPlugin dataserverPlugin = (DataserverPlugin)m_ScriptEngine.GetScriptPlugin("Dataserver");
  4231. UUID tid = dataserverPlugin.RegisterRequest(m_host.UUID,
  4232. m_itemID, rq.ToString());
  4233. dataserverPlugin.AddReply(rq.ToString(), reply, 100);
  4234. ScriptSleep(200);
  4235. return tid.ToString();
  4236. }
  4237. public LSL_Key llRequestInventoryData(string name)
  4238. {
  4239. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  4240. TaskInventoryDictionary itemDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone();
  4241. foreach (TaskInventoryItem item in itemDictionary.Values)
  4242. {
  4243. if (item.Type == 3 && item.Name == name)
  4244. {
  4245. UUID rq = UUID.Random();
  4246. DataserverPlugin dataserverPlugin = (DataserverPlugin)m_ScriptEngine.GetScriptPlugin("Dataserver");
  4247. UUID tid = dataserverPlugin.RegisterRequest(m_host.UUID,
  4248. m_itemID, rq.ToString());
  4249. Vector3 region = new Vector3(
  4250. World.RegionInfo.RegionLocX,
  4251. World.RegionInfo.RegionLocY,
  4252. 0);
  4253. World.AssetService.Get(item.AssetID.ToString(), this,
  4254. delegate(string i, object sender, AssetBase a)
  4255. {
  4256. AssetLandmark lm = new AssetLandmark(a);
  4257. float rx = (uint)(lm.RegionHandle >> 32);
  4258. float ry = (uint)lm.RegionHandle;
  4259. region = lm.Position + new Vector3(rx, ry, 0) - region;
  4260. string reply = region.ToString();
  4261. dataserverPlugin.AddReply(rq.ToString(),
  4262. reply, 1000);
  4263. });
  4264. ScriptSleep(1000);
  4265. return tid.ToString();
  4266. }
  4267. }
  4268. ScriptSleep(1000);
  4269. return String.Empty;
  4270. }
  4271. public void llSetDamage(double damage)
  4272. {
  4273. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  4274. m_host.ParentEntity.Damage = (float)damage;
  4275. ICombatModule combatModule = World.RequestModuleInterface<ICombatModule>();
  4276. if (combatModule != null)
  4277. combatModule.AddDamageToPrim(m_host.ParentEntity);
  4278. }
  4279. public DateTime llTeleportAgentHome(LSL_Key _agent)
  4280. {
  4281. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return DateTime.Now;
  4282. string agent = _agent.ToString();
  4283. UUID agentId = new UUID();
  4284. if (UUID.TryParse(agent, out agentId))
  4285. {
  4286. IScenePresence presence = World.GetScenePresence(agentId);
  4287. if (presence != null)
  4288. {
  4289. // agent must be over the owners land
  4290. IParcelManagementModule parcelManagement = World.RequestModuleInterface<IParcelManagementModule>();
  4291. if (parcelManagement != null)
  4292. {
  4293. if (m_host.OwnerID != parcelManagement.GetLandObject(
  4294. presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID &&
  4295. !World.Permissions.CanIssueEstateCommand(m_host.OwnerID, false))
  4296. {
  4297. return PScriptSleep(5000);
  4298. }
  4299. }
  4300. //Send disable cancel so that the agent cannot attempt to stay in the region
  4301. presence.ControllingClient.SendTeleportStart((uint)TeleportFlags.DisableCancel);
  4302. IEntityTransferModule transferModule = World.RequestModuleInterface<IEntityTransferModule>();
  4303. if (transferModule != null)
  4304. transferModule.TeleportHome(agentId, presence.ControllingClient);
  4305. else
  4306. presence.ControllingClient.SendTeleportFailed("Unable to perform teleports on this simulator.");
  4307. }
  4308. }
  4309. return PScriptSleep(5000);
  4310. }
  4311. public DateTime llTextBox(string agent, string message, int chatChannel)
  4312. {
  4313. IDialogModule dm = World.RequestModuleInterface<IDialogModule>();
  4314. if (dm == null)
  4315. return DateTime.Now;
  4316. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return DateTime.Now;
  4317. UUID av = new UUID();
  4318. if (!UUID.TryParse(agent, out av))
  4319. {
  4320. LSLError("First parameter to llDialog needs to be a key");
  4321. return DateTime.Now;
  4322. }
  4323. if (message != null && message.Length > 1024)
  4324. message = message.Substring(0, 1024);
  4325. dm.SendTextBoxToUser(av, message, chatChannel, m_host.Name, m_host.UUID, m_host.OwnerID);
  4326. return PScriptSleep(1000);
  4327. }
  4328. public void llModifyLand(int action, int brush)
  4329. {
  4330. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  4331. ITerrainModule tm = World.RequestModuleInterface<ITerrainModule>();
  4332. if (tm != null)
  4333. {
  4334. tm.ModifyTerrain(m_host.OwnerID, m_host.AbsolutePosition, (byte)brush, (byte)action, m_host.OwnerID);
  4335. }
  4336. }
  4337. public void llCollisionSound(string impact_sound, double impact_volume)
  4338. {
  4339. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  4340. UUID soundId = UUID.Zero;
  4341. if (!UUID.TryParse(impact_sound, out soundId))
  4342. {
  4343. lock (m_host.TaskInventory)
  4344. {
  4345. foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
  4346. {
  4347. if (item.Type == (int)AssetType.Sound && item.Name == impact_sound)
  4348. {
  4349. soundId = item.AssetID;
  4350. break;
  4351. }
  4352. }
  4353. }
  4354. }
  4355. //We do allow UUID.Zero here for scripts that want to disable the collision sound (such as "")
  4356. m_host.CollisionSound = soundId;
  4357. m_host.CollisionSoundVolume = (float)impact_volume;
  4358. }
  4359. public void llCollisionSprite(string impact_sprite)
  4360. {
  4361. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  4362. // Since this is broken in SL, we can do this however we want, until they fix it.
  4363. m_host.CollisionSprite = UUID.Parse(impact_sprite);
  4364. }
  4365. public LSL_String llGetAnimation(string id)
  4366. {
  4367. // This should only return a value if the avatar is in the same region
  4368. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  4369. UUID avatar = (UUID)id;
  4370. IScenePresence presence = World.GetScenePresence(avatar);
  4371. if (presence == null)
  4372. return "";
  4373. if (m_host.ParentEntity.Scene.RegionInfo.RegionHandle == presence.Scene.RegionInfo.RegionHandle)
  4374. {
  4375. Dictionary<UUID, string> animationstateNames = AnimationSet.Animations.AnimStateNames;
  4376. AnimationSet currentAnims = presence.Animator.Animations;
  4377. string currentAnimationState = String.Empty;
  4378. if (animationstateNames.TryGetValue(currentAnims.ImplicitDefaultAnimation.AnimID, out currentAnimationState))
  4379. return currentAnimationState;
  4380. }
  4381. return String.Empty;
  4382. }
  4383. public void llMessageLinked(int linknumber, int num, string msg, string id)
  4384. {
  4385. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  4386. List<ISceneChildEntity> parts = GetLinkParts(linknumber);
  4387. foreach (ISceneChildEntity part in parts)
  4388. {
  4389. int linkNumber = m_host.LinkNum;
  4390. if (m_host.ParentEntity.ChildrenEntities().Count == 1)
  4391. linkNumber = 0;
  4392. object[] resobj = new object[]
  4393. {
  4394. new LSL_Integer(linkNumber), new LSL_Integer(num), new LSL_String(msg), new LSL_String(id)
  4395. };
  4396. m_ScriptEngine.PostObjectEvent(part.UUID, "link_message", resobj);
  4397. }
  4398. }
  4399. public void llPushObject(string target, LSL_Vector impulse, LSL_Vector ang_impulse, int local)
  4400. {
  4401. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  4402. bool pushAllowed = false;
  4403. bool pusheeIsAvatar = false;
  4404. UUID targetID = UUID.Zero;
  4405. if (!UUID.TryParse(target, out targetID))
  4406. return;
  4407. IScenePresence pusheeav = null;
  4408. Vector3 PusheePos = Vector3.Zero;
  4409. ISceneChildEntity pusheeob = null;
  4410. IScenePresence avatar = World.GetScenePresence(targetID);
  4411. if (avatar != null)
  4412. {
  4413. pusheeIsAvatar = true;
  4414. // Pushee is in GodMode this pushing object isn't owned by them
  4415. if (avatar.GodLevel > 0 && m_host.OwnerID != targetID)
  4416. return;
  4417. pusheeav = avatar;
  4418. // Find pushee position
  4419. // Pushee Linked?
  4420. if (pusheeav.ParentID != UUID.Zero)
  4421. {
  4422. ISceneChildEntity parentobj = World.GetSceneObjectPart(pusheeav.ParentID);
  4423. PusheePos = parentobj != null ? parentobj.AbsolutePosition : pusheeav.AbsolutePosition;
  4424. }
  4425. else
  4426. {
  4427. PusheePos = pusheeav.AbsolutePosition;
  4428. }
  4429. }
  4430. if (!pusheeIsAvatar)
  4431. {
  4432. // not an avatar so push is not affected by parcel flags
  4433. pusheeob = World.GetSceneObjectPart(UUID.Parse(target));
  4434. // We can't find object
  4435. if (pusheeob == null)
  4436. return;
  4437. // Object not pushable. Not an attachment and has no physics component
  4438. if (!pusheeob.IsAttachment && pusheeob.PhysActor == null)
  4439. return;
  4440. PusheePos = pusheeob.AbsolutePosition;
  4441. pushAllowed = true;
  4442. }
  4443. else
  4444. {
  4445. IParcelManagementModule parcelManagement = World.RequestModuleInterface<IParcelManagementModule>();
  4446. if (World.RegionInfo.RegionSettings.RestrictPushing)
  4447. {
  4448. pushAllowed = m_host.OwnerID == targetID || m_host.ParentEntity.Scene.Permissions.IsGod(m_host.OwnerID);
  4449. }
  4450. else
  4451. {
  4452. if (parcelManagement != null)
  4453. {
  4454. ILandObject targetlandObj = parcelManagement.GetLandObject(PusheePos.X, PusheePos.Y);
  4455. if (targetlandObj == null)
  4456. // We didn't find the parcel but region isn't push restricted so assume it's ok
  4457. pushAllowed = true;
  4458. else
  4459. {
  4460. // Parcel push restriction
  4461. pushAllowed = (targetlandObj.LandData.Flags & (uint)ParcelFlags.RestrictPushObject) !=
  4462. (uint)ParcelFlags.RestrictPushObject ||
  4463. m_host.ParentEntity.Scene.Permissions.CanPushObject(m_host.OwnerID,
  4464. targetlandObj);
  4465. }
  4466. }
  4467. }
  4468. }
  4469. if (pushAllowed)
  4470. {
  4471. float distance = (PusheePos - m_host.AbsolutePosition).Length();
  4472. float distance_term = distance * distance * distance; // Script Energy
  4473. float pusher_mass = m_host.GetMass();
  4474. const float PUSH_ATTENUATION_DISTANCE = 17f;
  4475. const float PUSH_ATTENUATION_SCALE = 5f;
  4476. float distance_attenuation = 1f;
  4477. if (distance > PUSH_ATTENUATION_DISTANCE)
  4478. {
  4479. float normalized_units = 1f + (distance - PUSH_ATTENUATION_DISTANCE) / PUSH_ATTENUATION_SCALE;
  4480. distance_attenuation = 1f / normalized_units;
  4481. }
  4482. Vector3 applied_linear_impulse = new Vector3((float)impulse.x, (float)impulse.y, (float)impulse.z);
  4483. {
  4484. float impulse_length = applied_linear_impulse.Length();
  4485. float desired_energy = impulse_length * pusher_mass;
  4486. if (desired_energy > 0f)
  4487. desired_energy += distance_term;
  4488. float scaling_factor = 1f;
  4489. scaling_factor *= distance_attenuation;
  4490. applied_linear_impulse *= scaling_factor;
  4491. }
  4492. if (pusheeIsAvatar)
  4493. {
  4494. if (pusheeav != null)
  4495. {
  4496. PhysicsActor pa = pusheeav.PhysicsActor;
  4497. if (pa != null)
  4498. {
  4499. if (local != 0)
  4500. {
  4501. applied_linear_impulse *= m_host.GetWorldRotation();
  4502. }
  4503. //Put a limit on it...
  4504. int MaxPush = (int)pusheeav.PhysicsActor.Mass * 25;
  4505. if (applied_linear_impulse.X > 0 &&
  4506. Math.Abs(applied_linear_impulse.X) > MaxPush)
  4507. applied_linear_impulse.X = MaxPush;
  4508. if (applied_linear_impulse.X < 0 &&
  4509. Math.Abs(applied_linear_impulse.X) > MaxPush)
  4510. applied_linear_impulse.X = -MaxPush;
  4511. if (applied_linear_impulse.Y > 0 &&
  4512. Math.Abs(applied_linear_impulse.X) > MaxPush)
  4513. applied_linear_impulse.Y = MaxPush;
  4514. if (applied_linear_impulse.Y < 0 &&
  4515. Math.Abs(applied_linear_impulse.X) > MaxPush)
  4516. applied_linear_impulse.Y = -MaxPush;
  4517. if (applied_linear_impulse.Z > 0 &&
  4518. Math.Abs(applied_linear_impulse.X) > MaxPush)
  4519. applied_linear_impulse.Z = MaxPush;
  4520. if (applied_linear_impulse.Z < 0 &&
  4521. Math.Abs(applied_linear_impulse.Z) > MaxPush)
  4522. applied_linear_impulse.Z = -MaxPush;
  4523. pa.AddForce(applied_linear_impulse, true);
  4524. }
  4525. }
  4526. }
  4527. else
  4528. {
  4529. if (pusheeob.PhysActor != null)
  4530. {
  4531. pusheeob.ApplyImpulse(applied_linear_impulse, local != 0);
  4532. }
  4533. }
  4534. }
  4535. }
  4536. public void llPassCollisions(int pass)
  4537. {
  4538. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  4539. m_host.PassCollisions = pass;
  4540. }
  4541. public LSL_String llGetScriptName()
  4542. {
  4543. string result = String.Empty;
  4544. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  4545. lock (m_host.TaskInventory)
  4546. {
  4547. foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
  4548. {
  4549. if (item.Type == 10 && item.ItemID == m_itemID)
  4550. {
  4551. result = item.Name ?? String.Empty;
  4552. break;
  4553. }
  4554. }
  4555. }
  4556. return result;
  4557. }
  4558. public LSL_Integer llGetNumberOfSides()
  4559. {
  4560. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  4561. return GetNumberOfSides(m_host);
  4562. }
  4563. protected int GetNumberOfSides(ISceneChildEntity part)
  4564. {
  4565. int sides = part.GetNumberOfSides();
  4566. if (part.GetPrimType() == PrimType.SPHERE && part.Shape.ProfileHollow > 0)
  4567. {
  4568. // Make up for a bug where LSL shows 4 sides rather than 2
  4569. sides += 2;
  4570. }
  4571. return sides;
  4572. }
  4573. /* The new / changed functions were tested with the following LSL script:
  4574. default
  4575. {
  4576. state_entry()
  4577. {
  4578. rotation rot = llEuler2Rot(<0,70,0> * DEG_TO_RAD);
  4579. llOwnerSay("to get here, we rotate over: "+ (string) llRot2Axis(rot));
  4580. llOwnerSay("and we rotate for: "+ (llRot2Angle(rot) * RAD_TO_DEG));
  4581. // convert back and forth between quaternion <-> vector and angle
  4582. rotation newrot = llAxisAngle2Rot(llRot2Axis(rot),llRot2Angle(rot));
  4583. llOwnerSay("Old rotation was: "+(string) rot);
  4584. llOwnerSay("re-converted rotation is: "+(string) newrot);
  4585. llSetRot(rot); // to check the parameters in the prim
  4586. }
  4587. }
  4588. */
  4589. // Xantor 29/apr/2008
  4590. // Returns rotation described by rotating angle radians about axis.
  4591. // q = cos(a/2) + i (x * sin(a/2)) + j (y * sin(a/2)) + k (z * sin(a/2))
  4592. public LSL_Rotation llAxisAngle2Rot(LSL_Vector axis, LSL_Float angle)
  4593. {
  4594. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Rotation();
  4595. double s = Math.Cos(angle * 0.5);
  4596. double t = Math.Sin(angle * 0.5);
  4597. double x = axis.x * t;
  4598. double y = axis.y * t;
  4599. double z = axis.z * t;
  4600. return new LSL_Rotation(x, y, z, s);
  4601. }
  4602. // Xantor 29/apr/2008
  4603. // converts a Quaternion to X,Y,Z axis rotations
  4604. public LSL_Vector llRot2Axis(LSL_Rotation rot)
  4605. {
  4606. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
  4607. double x, y, z;
  4608. if (rot.s > 1) // normalization needed
  4609. {
  4610. double length = Math.Sqrt(rot.x * rot.x + rot.y * rot.y +
  4611. rot.z * rot.z + rot.s * rot.s);
  4612. if (length == 0)
  4613. return new LSL_Vector(0, 0, 0);
  4614. length = 1 / length;
  4615. rot.x *= length;
  4616. rot.y *= length;
  4617. rot.z *= length;
  4618. rot.s *= length;
  4619. }
  4620. // double angle = 2 * Math.Acos(rot.s);
  4621. double s = Math.Sqrt(1 - rot.s * rot.s);
  4622. if (s < 0.001)
  4623. {
  4624. x = 1;
  4625. y = z = 0;
  4626. }
  4627. else
  4628. {
  4629. s = 1 / s;
  4630. x = rot.x * s; // normalise axis
  4631. y = rot.y * s;
  4632. z = rot.z * s;
  4633. }
  4634. return new LSL_Vector(x, y, z);
  4635. }
  4636. // Returns the angle of a quaternion (see llRot2Axis for the axis)
  4637. public LSL_Float llRot2Angle(LSL_Rotation rot)
  4638. {
  4639. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
  4640. if (rot.s > 1) // normalization needed
  4641. {
  4642. double length = Math.Sqrt(rot.x * rot.x + rot.y * rot.y +
  4643. rot.z * rot.z + rot.s * rot.s);
  4644. if (length == 0)
  4645. return 0;
  4646. // rot.x /= length;
  4647. // rot.y /= length;
  4648. // rot.z /= length;
  4649. rot.s /= length;
  4650. }
  4651. double angle = 2 * Math.Acos(rot.s);
  4652. return angle;
  4653. }
  4654. public LSL_Float llAcos(double val)
  4655. {
  4656. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
  4657. return Math.Acos(val);
  4658. }
  4659. public LSL_Float llAsin(double val)
  4660. {
  4661. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
  4662. return Math.Asin(val);
  4663. }
  4664. public LSL_Float llAngleBetween(LSL_Rotation a, LSL_Rotation b)
  4665. {
  4666. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
  4667. double aa = (a.x * a.x + a.y * a.y + a.z * a.z + a.s * a.s);
  4668. double bb = (b.x * b.x + b.y * b.y + b.z * b.z + b.s * b.s);
  4669. double aa_bb = aa * bb;
  4670. if (aa_bb == 0) return 0.0;
  4671. double ab = (a.x * b.x + a.y * b.y + a.z * b.z + a.s * b.s);
  4672. double quotient = (ab * ab) / aa_bb;
  4673. if (quotient >= 1.0) return 0.0;
  4674. return Math.Acos(2 * quotient - 1);
  4675. }
  4676. public LSL_String llGetInventoryKey(string name)
  4677. {
  4678. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_String();
  4679. lock (m_host.TaskInventory)
  4680. {
  4681. foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
  4682. {
  4683. if (inv.Value.Name == name)
  4684. {
  4685. return (inv.Value.CurrentPermissions &
  4686. (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) ==
  4687. (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)
  4688. ? inv.Value.AssetID.ToString()
  4689. : UUID.Zero.ToString();
  4690. }
  4691. }
  4692. }
  4693. return UUID.Zero.ToString();
  4694. }
  4695. public void llAllowInventoryDrop(int add)
  4696. {
  4697. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  4698. m_host.ParentEntity.RootChild.AllowedDrop = add != 0;
  4699. // Update the object flags
  4700. m_host.ParentEntity.RootChild.aggregateScriptEvents();
  4701. }
  4702. public LSL_Vector llGetSunDirection()
  4703. {
  4704. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
  4705. LSL_Vector SunDoubleVector3;
  4706. // sunPosition estate setting is set in OpenSim.Region.CoreModules.SunModule
  4707. // have to convert from Vector3 (float) to LSL_Vector (double)
  4708. Vector3 SunFloatVector3 = World.RegionInfo.RegionSettings.SunVector;
  4709. SunDoubleVector3.x = SunFloatVector3.X;
  4710. SunDoubleVector3.y = SunFloatVector3.Y;
  4711. SunDoubleVector3.z = SunFloatVector3.Z;
  4712. return SunDoubleVector3;
  4713. }
  4714. public LSL_Vector llGetTextureOffset(int face)
  4715. {
  4716. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
  4717. return GetTextureOffset(m_host, face);
  4718. }
  4719. protected LSL_Vector GetTextureOffset(ISceneChildEntity part, int face)
  4720. {
  4721. Primitive.TextureEntry tex = part.Shape.Textures;
  4722. LSL_Vector offset = new LSL_Vector();
  4723. if (face == ScriptBaseClass.ALL_SIDES)
  4724. {
  4725. face = 0;
  4726. }
  4727. if (face >= 0 && face < GetNumberOfSides(part))
  4728. {
  4729. offset.x = tex.GetFace((uint)face).OffsetU;
  4730. offset.y = tex.GetFace((uint)face).OffsetV;
  4731. offset.z = 0.0;
  4732. return offset;
  4733. }
  4734. return offset;
  4735. }
  4736. public LSL_Vector llGetTextureScale(int side)
  4737. {
  4738. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
  4739. Primitive.TextureEntry tex = m_host.Shape.Textures;
  4740. LSL_Vector scale;
  4741. if (side == -1)
  4742. {
  4743. side = 0;
  4744. }
  4745. scale.x = tex.GetFace((uint)side).RepeatU;
  4746. scale.y = tex.GetFace((uint)side).RepeatV;
  4747. scale.z = 0.0;
  4748. return scale;
  4749. }
  4750. public LSL_Float llGetTextureRot(int face)
  4751. {
  4752. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
  4753. return GetTextureRot(m_host, face);
  4754. }
  4755. protected LSL_Float GetTextureRot(ISceneChildEntity part, int face)
  4756. {
  4757. Primitive.TextureEntry tex = part.Shape.Textures;
  4758. if (face == -1)
  4759. {
  4760. face = 0;
  4761. }
  4762. if (face >= 0 && face < GetNumberOfSides(part))
  4763. {
  4764. return tex.GetFace((uint)face).Rotation;
  4765. }
  4766. return 0.0;
  4767. }
  4768. public LSL_Integer llSubStringIndex(string source, string pattern)
  4769. {
  4770. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  4771. return source.IndexOf(pattern);
  4772. }
  4773. public LSL_String llGetOwnerKey(string id)
  4774. {
  4775. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  4776. UUID key = new UUID();
  4777. if (UUID.TryParse(id, out key))
  4778. {
  4779. try
  4780. {
  4781. ISceneChildEntity obj = World.GetSceneObjectPart(key);
  4782. if (obj == null)
  4783. return id; // the key is for an agent so just return the key
  4784. return obj.OwnerID.ToString();
  4785. }
  4786. catch (KeyNotFoundException)
  4787. {
  4788. return id; // The Object/Agent not in the region so just return the key
  4789. }
  4790. }
  4791. return UUID.Zero.ToString();
  4792. }
  4793. public LSL_Vector llGetCenterOfMass()
  4794. {
  4795. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
  4796. Vector3 center = m_host.GetGeometricCenter();
  4797. return new LSL_Vector(center.X, center.Y, center.Z);
  4798. }
  4799. public LSL_List llListSort(LSL_List src, int stride, int ascending)
  4800. {
  4801. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_List();
  4802. if (stride <= 0)
  4803. {
  4804. stride = 1;
  4805. }
  4806. return src.Sort(stride, ascending);
  4807. }
  4808. public LSL_Integer llGetListLength(LSL_List src)
  4809. {
  4810. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  4811. if (src == new LSL_List(new object[0]))
  4812. {
  4813. return 0;
  4814. }
  4815. return src.Length;
  4816. }
  4817. public LSL_Integer llList2Integer(LSL_List src, int index)
  4818. {
  4819. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  4820. if (index < 0)
  4821. {
  4822. index = src.Length + index;
  4823. }
  4824. if (index >= src.Length || index < 0)
  4825. {
  4826. return 0;
  4827. }
  4828. try
  4829. {
  4830. if (src.Data[index] is LSL_Integer)
  4831. return (LSL_Integer)src.Data[index];
  4832. if (src.Data[index] is LSL_Float)
  4833. return Convert.ToInt32(((LSL_Float)src.Data[index]).value);
  4834. return new LSL_Integer(src.Data[index].ToString());
  4835. }
  4836. catch (FormatException)
  4837. {
  4838. return 0;
  4839. }
  4840. catch (InvalidCastException)
  4841. {
  4842. return 0;
  4843. }
  4844. }
  4845. public LSL_Float llList2Float(LSL_List src, int index)
  4846. {
  4847. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
  4848. if (index < 0)
  4849. {
  4850. index = src.Length + index;
  4851. }
  4852. if (index >= src.Length || index < 0)
  4853. {
  4854. return 0.0;
  4855. }
  4856. try
  4857. {
  4858. if (src.Data[index] is LSL_Integer)
  4859. return Convert.ToDouble(((LSL_Integer)src.Data[index]).value);
  4860. if (src.Data[index] is LSL_Float)
  4861. return Convert.ToDouble(((LSL_Float)src.Data[index]).value);
  4862. if (src.Data[index] is LSL_String)
  4863. return Convert.ToDouble(((LSL_String)src.Data[index]).m_string);
  4864. return Convert.ToDouble(src.Data[index]);
  4865. }
  4866. catch (FormatException)
  4867. {
  4868. return 0.0;
  4869. }
  4870. catch (InvalidCastException)
  4871. {
  4872. return 0.0;
  4873. }
  4874. }
  4875. public LSL_String llList2String(LSL_List src, int index)
  4876. {
  4877. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  4878. if (index < 0)
  4879. {
  4880. index = src.Length + index;
  4881. }
  4882. if (index >= src.Length || index < 0)
  4883. {
  4884. return String.Empty;
  4885. }
  4886. return new LSL_String(src.Data[index].ToString());
  4887. }
  4888. public LSL_String llList2Key(LSL_List src, int index)
  4889. {
  4890. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  4891. if (index < 0)
  4892. {
  4893. index = src.Length + index;
  4894. }
  4895. if (index >= src.Length || index < 0)
  4896. {
  4897. return "";
  4898. }
  4899. return src.Data[index].ToString();
  4900. }
  4901. public LSL_Vector llList2Vector(LSL_List src, int index)
  4902. {
  4903. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
  4904. if (index < 0)
  4905. {
  4906. index = src.Length + index;
  4907. }
  4908. if (index >= src.Length || index < 0)
  4909. {
  4910. return new LSL_Vector(0, 0, 0);
  4911. }
  4912. if (src.Data[index] is LSL_Vector)
  4913. {
  4914. return (LSL_Vector)src.Data[index];
  4915. }
  4916. return new LSL_Vector(src.Data[index].ToString());
  4917. }
  4918. public LSL_Rotation llList2Rot(LSL_List src, int index)
  4919. {
  4920. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Rotation();
  4921. if (index < 0)
  4922. {
  4923. index = src.Length + index;
  4924. }
  4925. if (index >= src.Length || index < 0)
  4926. {
  4927. return new LSL_Rotation(0, 0, 0, 1);
  4928. }
  4929. if (src.Data[index] is LSL_Rotation)
  4930. {
  4931. return (LSL_Rotation)src.Data[index];
  4932. }
  4933. return new LSL_Rotation(src.Data[index].ToString());
  4934. }
  4935. public LSL_List llList2List(LSL_List src, int start, int end)
  4936. {
  4937. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_List();
  4938. return src.GetSublist(start, end);
  4939. }
  4940. public LSL_List llDeleteSubList(LSL_List src, int start, int end)
  4941. {
  4942. return src.DeleteSublist(start, end);
  4943. }
  4944. public LSL_Integer llGetListEntryType(LSL_List src, int index)
  4945. {
  4946. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  4947. if (index < 0)
  4948. {
  4949. index = src.Length + index;
  4950. }
  4951. if (index >= src.Length)
  4952. {
  4953. return 0;
  4954. }
  4955. if (src.Data[index] is LSL_Integer || src.Data[index] is Int32)
  4956. return ScriptBaseClass.TYPE_INTEGER;
  4957. if (src.Data[index] is LSL_Float || src.Data[index] is Single || src.Data[index] is Double)
  4958. return ScriptBaseClass.TYPE_FLOAT;
  4959. if (src.Data[index] is LSL_String || src.Data[index] is String)
  4960. {
  4961. UUID tuuid;
  4962. if (UUID.TryParse(src.Data[index].ToString(), out tuuid))
  4963. {
  4964. return ScriptBaseClass.TYPE_KEY;
  4965. }
  4966. return ScriptBaseClass.TYPE_STRING;
  4967. }
  4968. if (src.Data[index] is LSL_Vector)
  4969. return ScriptBaseClass.TYPE_VECTOR;
  4970. if (src.Data[index] is LSL_Rotation)
  4971. return ScriptBaseClass.TYPE_ROTATION;
  4972. if (src.Data[index] is LSL_List)
  4973. return 7; //Extension of LSL by us
  4974. return ScriptBaseClass.TYPE_INVALID;
  4975. }
  4976. /// <summary>
  4977. /// Process the supplied list and return the
  4978. /// content of the list formatted as a comma
  4979. /// separated list. There is a space after
  4980. /// each comma.
  4981. /// </summary>
  4982. public LSL_String llList2CSV(LSL_List src)
  4983. {
  4984. string ret = String.Empty;
  4985. int x = 0;
  4986. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  4987. if (src.Data.Length > 0)
  4988. {
  4989. ret = src.Data[x++].ToString();
  4990. for (; x < src.Data.Length; x++)
  4991. {
  4992. ret += ", " + src.Data[x].ToString();
  4993. }
  4994. }
  4995. return ret;
  4996. }
  4997. /// <summary>
  4998. /// The supplied string is scanned for commas
  4999. /// and converted into a list. Commas are only
  5000. /// effective if they are encountered outside
  5001. /// of '<' '>' delimiters. Any whitespace
  5002. /// before or after an element is trimmed.
  5003. /// </summary>
  5004. public LSL_List llCSV2List(string src)
  5005. {
  5006. LSL_List result = new LSL_List();
  5007. int parens = 0;
  5008. int start = 0;
  5009. int length = 0;
  5010. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_List();
  5011. for (int i = 0; i < src.Length; i++)
  5012. {
  5013. switch (src[i])
  5014. {
  5015. case '<':
  5016. parens++;
  5017. length++;
  5018. break;
  5019. case '>':
  5020. if (parens > 0)
  5021. parens--;
  5022. length++;
  5023. break;
  5024. case ',':
  5025. if (parens == 0)
  5026. {
  5027. result.Add(new LSL_String(src.Substring(start, length).Trim()));
  5028. start += length + 1;
  5029. length = 0;
  5030. }
  5031. else
  5032. {
  5033. length++;
  5034. }
  5035. break;
  5036. default:
  5037. length++;
  5038. break;
  5039. }
  5040. }
  5041. result.Add(new LSL_String(src.Substring(start, length).Trim()));
  5042. return result;
  5043. }
  5044. /// <summary>
  5045. /// Randomizes the list, be arbitrarily reordering
  5046. /// sublists of stride elements. As the stride approaches
  5047. /// the size of the list, the options become very
  5048. /// limited.
  5049. /// </summary>
  5050. /// <remarks>
  5051. /// This could take a while for very large list
  5052. /// sizes.
  5053. /// </remarks>
  5054. public LSL_List llListRandomize(LSL_List src, int stride)
  5055. {
  5056. LSL_List result;
  5057. Random rand = new Random();
  5058. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_List();
  5059. if (stride <= 0)
  5060. {
  5061. stride = 1;
  5062. }
  5063. // Stride MUST be a factor of the list length
  5064. // If not, then return the src list. This also
  5065. // traps those cases where stride > length.
  5066. if (src.Length != stride && src.Length % stride == 0)
  5067. {
  5068. int chunkk = src.Length / stride;
  5069. int[] chunks = new int[chunkk];
  5070. for (int i = 0; i < chunkk; i++)
  5071. chunks[i] = i;
  5072. // Knuth shuffle the chunkk index
  5073. for (int i = chunkk - 1; i >= 1; i--)
  5074. {
  5075. // Elect an unrandomized chunk to swap
  5076. int index = rand.Next(i + 1);
  5077. // and swap position with first unrandomized chunk
  5078. int tmp = chunks[i];
  5079. chunks[i] = chunks[index];
  5080. chunks[index] = tmp;
  5081. }
  5082. // Construct the randomized list
  5083. result = new LSL_List();
  5084. for (int i = 0; i < chunkk; i++)
  5085. {
  5086. for (int j = 0; j < stride; j++)
  5087. {
  5088. result.Add(src.Data[chunks[i] * stride + j]);
  5089. }
  5090. }
  5091. }
  5092. else
  5093. {
  5094. object[] array = new object[src.Length];
  5095. Array.Copy(src.Data, 0, array, 0, src.Length);
  5096. result = new LSL_List(array);
  5097. }
  5098. return result;
  5099. }
  5100. /// <summary>
  5101. /// Elements in the source list starting with 0 and then
  5102. /// every i+stride. If the stride is negative then the scan
  5103. /// is backwards producing an inverted result.
  5104. /// Only those elements that are also in the specified
  5105. /// range are included in the result.
  5106. /// </summary>
  5107. public LSL_List llList2ListStrided(LSL_List src, int start, int end, int stride)
  5108. {
  5109. LSL_List result = new LSL_List();
  5110. int[] si = new int[2];
  5111. int[] ei = new int[2];
  5112. bool twopass = false;
  5113. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_List();
  5114. // First step is always to deal with negative indices
  5115. if (start < 0)
  5116. start = src.Length + start;
  5117. if (end < 0)
  5118. end = src.Length + end;
  5119. // Out of bounds indices are OK, just trim them
  5120. // accordingly
  5121. if (start > src.Length)
  5122. start = src.Length;
  5123. if (end > src.Length)
  5124. end = src.Length;
  5125. if (stride == 0)
  5126. stride = 1;
  5127. // There may be one or two ranges to be considered
  5128. if (start != end)
  5129. {
  5130. if (start <= end)
  5131. {
  5132. si[0] = start;
  5133. ei[0] = end;
  5134. }
  5135. else
  5136. {
  5137. si[1] = start;
  5138. ei[1] = src.Length;
  5139. si[0] = 0;
  5140. ei[0] = end;
  5141. twopass = true;
  5142. }
  5143. // The scan always starts from the beginning of the
  5144. // source list, but members are only selected if they
  5145. // fall within the specified sub-range. The specified
  5146. // range values are inclusive.
  5147. // A negative stride reverses the direction of the
  5148. // scan producing an inverted list as a result.
  5149. if (stride > 0)
  5150. {
  5151. for (int i = 0; i < src.Length; i += stride)
  5152. {
  5153. if (i <= ei[0] && i >= si[0])
  5154. result.Add(src.Data[i]);
  5155. if (twopass && i >= si[1] && i <= ei[1])
  5156. result.Add(src.Data[i]);
  5157. }
  5158. }
  5159. else if (stride < 0)
  5160. {
  5161. for (int i = src.Length - 1; i >= 0; i += stride)
  5162. {
  5163. if (i <= ei[0] && i >= si[0])
  5164. result.Add(src.Data[i]);
  5165. if (twopass && i >= si[1] && i <= ei[1])
  5166. result.Add(src.Data[i]);
  5167. }
  5168. }
  5169. }
  5170. else
  5171. {
  5172. if (start % stride == 0)
  5173. {
  5174. result.Add(src.Data[start]);
  5175. }
  5176. }
  5177. return result;
  5178. }
  5179. public LSL_Integer llGetRegionAgentCount()
  5180. {
  5181. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  5182. IEntityCountModule entityCountModule = World.RequestModuleInterface<IEntityCountModule>();
  5183. if (entityCountModule != null)
  5184. return new LSL_Integer(entityCountModule.RootAgents);
  5185. else
  5186. return new LSL_Integer(0);
  5187. }
  5188. public LSL_Vector llGetRegionCorner()
  5189. {
  5190. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
  5191. return new LSL_Vector(World.RegionInfo.RegionLocX, World.RegionInfo.RegionLocY, 0);
  5192. }
  5193. /// <summary>
  5194. /// Insert the list identified by <src> into the
  5195. /// list designated by <dest> such that the first
  5196. /// new element has the index specified by <index>
  5197. /// </summary>
  5198. public LSL_List llListInsertList(LSL_List dest, LSL_List src, int index)
  5199. {
  5200. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_List();
  5201. LSL_List pref = null;
  5202. LSL_List suff = null;
  5203. if (index < 0)
  5204. {
  5205. index = index + dest.Length;
  5206. if (index < 0)
  5207. {
  5208. index = 0;
  5209. }
  5210. }
  5211. if (index != 0)
  5212. {
  5213. pref = dest.GetSublist(0, index - 1);
  5214. if (index < dest.Length)
  5215. {
  5216. suff = dest.GetSublist(index, -1);
  5217. return pref + src + suff;
  5218. }
  5219. return pref + src;
  5220. }
  5221. if (index < dest.Length)
  5222. {
  5223. suff = dest.GetSublist(index, -1);
  5224. return src + suff;
  5225. }
  5226. return src;
  5227. }
  5228. /// <summary>
  5229. /// Returns the index of the first occurrence of test
  5230. /// in src.
  5231. /// </summary>
  5232. public LSL_Integer llListFindList(LSL_List src, LSL_List test)
  5233. {
  5234. int index = -1;
  5235. int length = src.Length - test.Length + 1;
  5236. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  5237. // If either list is empty, do not match
  5238. if (src.Length != 0 && test.Length != 0)
  5239. {
  5240. for (int i = 0; i < length; i++)
  5241. {
  5242. if (src.Data[i].Equals(test.Data[0]) || test.Data[0].Equals(src.Data[i]))
  5243. {
  5244. int j;
  5245. for (j = 1; j < test.Length; j++)
  5246. if (!(src.Data[i + j].Equals(test.Data[j]) || test.Data[j].Equals(src.Data[i + j])))
  5247. break;
  5248. if (j == test.Length)
  5249. {
  5250. index = i;
  5251. break;
  5252. }
  5253. }
  5254. }
  5255. }
  5256. return index;
  5257. }
  5258. public LSL_String llGetObjectName()
  5259. {
  5260. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  5261. return m_host.Name ?? String.Empty;
  5262. }
  5263. public void llSetObjectName(string name)
  5264. {
  5265. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  5266. m_host.Name = name ?? String.Empty;
  5267. }
  5268. public LSL_String llGetDate()
  5269. {
  5270. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  5271. DateTime date = DateTime.Now.ToUniversalTime();
  5272. string result = date.ToString("yyyy-MM-dd");
  5273. return result;
  5274. }
  5275. public LSL_Integer llEdgeOfWorld(LSL_Vector pos, LSL_Vector dir)
  5276. {
  5277. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  5278. // edge will be used to pass the Region Coordinates offset
  5279. // we want to check for a neighboring sim
  5280. LSL_Vector edge = new LSL_Vector(0, 0, 0);
  5281. if (dir.x == 0)
  5282. {
  5283. if (dir.y == 0)
  5284. {
  5285. // Direction vector is 0,0 so return
  5286. // false since we're staying in the sim
  5287. return 0;
  5288. }
  5289. // Y is the only valid direction
  5290. edge.y = dir.y / Math.Abs(dir.y);
  5291. }
  5292. else
  5293. {
  5294. LSL_Float mag;
  5295. if (dir.x > 0)
  5296. {
  5297. mag = (World.RegionInfo.RegionSizeX - pos.x) / dir.x;
  5298. }
  5299. else
  5300. {
  5301. mag = (pos.x / dir.x);
  5302. }
  5303. mag = Math.Abs(mag);
  5304. edge.y = pos.y + (dir.y * mag);
  5305. if (edge.y > World.RegionInfo.RegionSizeY || edge.y < 0)
  5306. {
  5307. // Y goes out of bounds first
  5308. edge.y = dir.y / Math.Abs(dir.y);
  5309. }
  5310. else
  5311. {
  5312. // X goes out of bounds first or its a corner exit
  5313. edge.y = 0;
  5314. edge.x = dir.x / Math.Abs(dir.x);
  5315. }
  5316. }
  5317. IGridRegisterModule service = World.RequestModuleInterface<IGridRegisterModule>();
  5318. List<GridRegion> neighbors = new List<GridRegion>();
  5319. if (service != null)
  5320. neighbors = service.GetNeighbors(World);
  5321. int neighborX = World.RegionInfo.RegionLocX + (int)dir.x;
  5322. int neighborY = World.RegionInfo.RegionLocY + (int)dir.y;
  5323. #if (!ISWIN)
  5324. foreach (GridRegion neighbor in neighbors)
  5325. if (neighbor.RegionLocX == neighborX && neighbor.RegionLocY == neighborY)
  5326. return LSL_Integer.TRUE;
  5327. #else
  5328. if (neighbors.Any(neighbor => neighbor.RegionLocX == neighborX && neighbor.RegionLocY == neighborY))
  5329. {
  5330. return LSL_Integer.TRUE;
  5331. }
  5332. #endif
  5333. return LSL_Integer.FALSE;
  5334. }
  5335. /// <summary>
  5336. /// Fully implemented
  5337. /// </summary>
  5338. public LSL_Integer llGetAgentInfo(string id)
  5339. {
  5340. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  5341. UUID key = new UUID();
  5342. if (!UUID.TryParse(id, out key))
  5343. {
  5344. return 0;
  5345. }
  5346. int flags = 0;
  5347. IScenePresence agent = World.GetScenePresence(key);
  5348. if (agent == null)
  5349. {
  5350. return 0;
  5351. }
  5352. if (agent.IsChildAgent)
  5353. return 0; // Fail if they are not in the same region
  5354. // note: in OpenSim, sitting seems to cancel AGENT_ALWAYS_RUN, unlike SL
  5355. if (agent.SetAlwaysRun)
  5356. {
  5357. flags |= ScriptBaseClass.AGENT_ALWAYS_RUN;
  5358. }
  5359. IAttachmentsModule attachMod = World.RequestModuleInterface<IAttachmentsModule>();
  5360. if (attachMod != null)
  5361. {
  5362. ISceneEntity[] att = attachMod.GetAttachmentsForAvatar(agent.UUID);
  5363. if (att.Length > 0)
  5364. {
  5365. flags |= ScriptBaseClass.AGENT_ATTACHMENTS;
  5366. #if (!ISWIN)
  5367. foreach (ISceneEntity gobj in att)
  5368. {
  5369. if (gobj != null)
  5370. {
  5371. if (gobj.RootChild.Inventory.ContainsScripts())
  5372. {
  5373. flags |= ScriptBaseClass.AGENT_SCRIPTED;
  5374. break;
  5375. }
  5376. }
  5377. }
  5378. #else
  5379. if (att.Where(gobj => gobj != null).Any(gobj => gobj.RootChild.Inventory.ContainsScripts()))
  5380. {
  5381. flags |= ScriptBaseClass.AGENT_SCRIPTED;
  5382. }
  5383. #endif
  5384. }
  5385. }
  5386. if ((agent.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0)
  5387. {
  5388. flags |= ScriptBaseClass.AGENT_FLYING;
  5389. flags |= ScriptBaseClass.AGENT_IN_AIR; // flying always implies in-air, even if colliding with e.g. a wall
  5390. }
  5391. if ((agent.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_AWAY) != 0)
  5392. {
  5393. flags |= ScriptBaseClass.AGENT_AWAY;
  5394. }
  5395. // seems to get unset, even if in mouselook, when avatar is sitting on a prim???
  5396. if ((agent.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0)
  5397. {
  5398. flags |= ScriptBaseClass.AGENT_MOUSELOOK;
  5399. }
  5400. if ((agent.State & (byte)AgentState.Typing) != 0)
  5401. {
  5402. flags |= ScriptBaseClass.AGENT_TYPING;
  5403. }
  5404. if (agent.IsBusy)
  5405. {
  5406. flags |= ScriptBaseClass.AGENT_BUSY;
  5407. }
  5408. string agentMovementAnimation = agent.Animator.CurrentMovementAnimation;
  5409. if (agentMovementAnimation == "CROUCH")
  5410. {
  5411. flags |= ScriptBaseClass.AGENT_CROUCHING;
  5412. }
  5413. if (agentMovementAnimation == "WALK" || agentMovementAnimation == "CROUCHWALK")
  5414. {
  5415. flags |= ScriptBaseClass.AGENT_WALKING;
  5416. }
  5417. // not colliding implies in air. Note: flying also implies in-air, even if colliding (see above)
  5418. // note: AGENT_IN_AIR and AGENT_WALKING seem to be mutually exclusive states in SL.
  5419. // note: this may need some tweaking when walking downhill. you "fall down" for a brief instant
  5420. // and don't collide when walking downhill, which instantly registers as in-air, briefly. should
  5421. // there be some minimum non-collision threshold time before claiming the avatar is in-air?
  5422. if ((flags & ScriptBaseClass.AGENT_WALKING) == 0 &&
  5423. agent.PhysicsActor != null &&
  5424. !agent.PhysicsActor.IsColliding)
  5425. {
  5426. flags |= ScriptBaseClass.AGENT_IN_AIR;
  5427. }
  5428. if (agent.ParentID != UUID.Zero)
  5429. {
  5430. flags |= ScriptBaseClass.AGENT_ON_OBJECT;
  5431. flags |= ScriptBaseClass.AGENT_SITTING;
  5432. }
  5433. if (agent.Animator.Animations.ImplicitDefaultAnimation.AnimID
  5434. == AnimationSet.Animations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
  5435. {
  5436. flags |= ScriptBaseClass.AGENT_SITTING;
  5437. }
  5438. return flags;
  5439. }
  5440. public LSL_String llGetAgentLanguage(string id)
  5441. {
  5442. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  5443. IAgentConnector AgentFrontend = DataManager.DataManager.RequestPlugin<IAgentConnector>();
  5444. if (AgentFrontend == null)
  5445. return "en-us";
  5446. IAgentInfo Agent = AgentFrontend.GetAgent(new UUID(id));
  5447. if (Agent == null)
  5448. return "en-us";
  5449. if (Agent.LanguageIsPublic)
  5450. {
  5451. return Agent.Language;
  5452. }
  5453. return "en-us";
  5454. }
  5455. /// <summary>
  5456. /// http://wiki.secondlife.com/wiki/LlGetAgentList
  5457. /// The list of options is currently not used in SL
  5458. /// scope is one of:-
  5459. /// AGENT_LIST_REGION - all in the region
  5460. /// AGENT_LIST_PARCEL - all in the same parcel as the scripted object
  5461. /// AGENT_LIST_PARCEL_OWNER - all in any parcel owned by the owner of the
  5462. /// current parcel.
  5463. /// </summary>
  5464. public LSL_List llGetAgentList(LSL_Integer scope, LSL_List options)
  5465. {
  5466. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  5467. return new LSL_List();
  5468. // the constants are 1, 2 and 4 so bits are being set, but you
  5469. // get an error "INVALID_SCOPE" if it is anything but 1, 2 and 4
  5470. bool regionWide = scope == ScriptBaseClass.AGENT_LIST_REGION;
  5471. bool parcelOwned = scope == ScriptBaseClass.AGENT_LIST_PARCEL_OWNER;
  5472. bool parcel = scope == ScriptBaseClass.AGENT_LIST_PARCEL;
  5473. LSL_List result = new LSL_List();
  5474. if (!regionWide && !parcelOwned && !parcel)
  5475. {
  5476. result.Add("INVALID_SCOPE");
  5477. return result;
  5478. }
  5479. Vector3 pos;
  5480. UUID id = UUID.Zero;
  5481. if (parcel || parcelOwned)
  5482. {
  5483. pos = m_host.GetWorldPosition();
  5484. IParcelManagementModule parcelManagement = World.RequestModuleInterface<IParcelManagementModule>();
  5485. ILandObject land = parcelManagement.GetLandObject(pos.X, pos.Y);
  5486. if (land == null)
  5487. {
  5488. id = UUID.Zero;
  5489. }
  5490. else
  5491. {
  5492. if (parcelOwned)
  5493. {
  5494. id = land.LandData.OwnerID;
  5495. }
  5496. else
  5497. {
  5498. id = land.LandData.GlobalID;
  5499. }
  5500. }
  5501. }
  5502. World.ForEachScenePresence(delegate(IScenePresence ssp)
  5503. {
  5504. // Gods are not listed in SL
  5505. if (!ssp.IsDeleted && ssp.GodLevel == 0.0 && !ssp.IsChildAgent)
  5506. {
  5507. if (!regionWide)
  5508. {
  5509. pos = ssp.AbsolutePosition;
  5510. IParcelManagementModule parcelManagement = World.RequestModuleInterface<IParcelManagementModule>();
  5511. ILandObject land = parcelManagement.GetLandObject(pos.X, pos.Y);
  5512. if (land != null)
  5513. {
  5514. if (parcelOwned && land.LandData.OwnerID == id ||
  5515. parcel && land.LandData.GlobalID == id)
  5516. {
  5517. result.Add(ssp.UUID.ToString());
  5518. }
  5519. }
  5520. }
  5521. else
  5522. {
  5523. result.Add(ssp.UUID.ToString());
  5524. }
  5525. }
  5526. // Maximum of 100 results
  5527. if (result.Length > 99)
  5528. {
  5529. return;
  5530. }
  5531. });
  5532. return result;
  5533. }
  5534. public DateTime llAdjustSoundVolume(double volume)
  5535. {
  5536. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return DateTime.Now;
  5537. m_host.AdjustSoundGain(volume);
  5538. return PScriptSleep(100);
  5539. }
  5540. public void llSetSoundQueueing(int queue)
  5541. {
  5542. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  5543. m_host.SetSoundQueueing(queue);
  5544. }
  5545. public void llSetSoundRadius(double radius)
  5546. {
  5547. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  5548. m_host.SoundRadius = radius;
  5549. }
  5550. public LSL_String llGetDisplayName(string id)
  5551. {
  5552. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  5553. UUID key = new UUID();
  5554. if (UUID.TryParse(id, out key))
  5555. {
  5556. IScenePresence presence = World.GetScenePresence(key);
  5557. if (presence != null)
  5558. {
  5559. IProfileConnector connector = DataManager.DataManager.RequestPlugin<IProfileConnector>();
  5560. if (connector != null)
  5561. return connector.GetUserProfile(presence.UUID).DisplayName;
  5562. }
  5563. }
  5564. return String.Empty;
  5565. }
  5566. public LSL_String llGetUsername(string id)
  5567. {
  5568. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  5569. UUID key = new UUID();
  5570. if (UUID.TryParse(id, out key))
  5571. {
  5572. IScenePresence presence = World.GetScenePresence(key);
  5573. if (presence != null)
  5574. return presence.Name;
  5575. }
  5576. return String.Empty;
  5577. }
  5578. public LSL_String llKey2Name(string id)
  5579. {
  5580. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  5581. UUID key = new UUID();
  5582. if (UUID.TryParse(id, out key))
  5583. {
  5584. IScenePresence presence = World.GetScenePresence(key);
  5585. if (presence != null)
  5586. return presence.Name;
  5587. if (World.GetSceneObjectPart(key) != null)
  5588. {
  5589. return World.GetSceneObjectPart(key).Name;
  5590. }
  5591. }
  5592. return String.Empty;
  5593. }
  5594. public void llSetTextureAnim(int mode, int face, int sizex, int sizey, double start, double length, double rate)
  5595. {
  5596. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  5597. SetTextureAnim(m_host, mode, face, sizex, sizey, start, length, rate);
  5598. }
  5599. public void llSetLinkTextureAnim(int linknumber, int mode, int face, int sizex, int sizey, double start, double length, double rate)
  5600. {
  5601. List<ISceneChildEntity> parts = GetLinkParts(linknumber);
  5602. foreach (var part in parts)
  5603. {
  5604. SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate);
  5605. }
  5606. }
  5607. private void SetTextureAnim(ISceneChildEntity part, int mode, int face, int sizex, int sizey, double start, double length, double rate)
  5608. {
  5609. Primitive.TextureAnimation pTexAnim = new Primitive.TextureAnimation { Flags = (Primitive.TextureAnimMode)mode };
  5610. //ALL_SIDES
  5611. if (face == ScriptBaseClass.ALL_SIDES)
  5612. face = 255;
  5613. pTexAnim.Face = (uint)face;
  5614. pTexAnim.Length = (float)length;
  5615. pTexAnim.Rate = (float)rate;
  5616. pTexAnim.SizeX = (uint)sizex;
  5617. pTexAnim.SizeY = (uint)sizey;
  5618. pTexAnim.Start = (float)start;
  5619. part.AddTextureAnimation(pTexAnim);
  5620. part.ScheduleUpdate(PrimUpdateFlags.FindBest);
  5621. }
  5622. public void llTriggerSoundLimited(string sound, double volume, LSL_Vector top_north_east,
  5623. LSL_Vector bottom_south_west)
  5624. {
  5625. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  5626. double radius1 = (float)llVecDist(llGetPos(), top_north_east);
  5627. double radius2 = (float)llVecDist(llGetPos(), bottom_south_west);
  5628. double radius = Math.Abs(radius1 - radius2);
  5629. m_host.SendSound(KeyOrName(sound, true).ToString(), volume, true, 0, (float)radius, false, false);
  5630. }
  5631. public DateTime llEjectFromLand(string pest)
  5632. {
  5633. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return DateTime.Now;
  5634. UUID agentId = new UUID();
  5635. if (UUID.TryParse(pest, out agentId))
  5636. {
  5637. IScenePresence presence = World.GetScenePresence(agentId);
  5638. if (presence != null)
  5639. {
  5640. // agent must be over the owners land
  5641. IParcelManagementModule parcelManagement = World.RequestModuleInterface<IParcelManagementModule>();
  5642. if (parcelManagement != null)
  5643. {
  5644. if (m_host.OwnerID != parcelManagement.GetLandObject(
  5645. presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID &&
  5646. !World.Permissions.CanIssueEstateCommand(m_host.OwnerID, false))
  5647. {
  5648. return PScriptSleep(5000);
  5649. }
  5650. }
  5651. IEntityTransferModule transferModule = World.RequestModuleInterface<IEntityTransferModule>();
  5652. if (transferModule != null)
  5653. transferModule.TeleportHome(agentId, presence.ControllingClient);
  5654. else
  5655. presence.ControllingClient.SendTeleportFailed("Unable to perform teleports on this simulator.");
  5656. }
  5657. }
  5658. return PScriptSleep(5000);
  5659. }
  5660. public LSL_Integer llOverMyLand(string id)
  5661. {
  5662. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  5663. UUID key = new UUID();
  5664. if (UUID.TryParse(id, out key))
  5665. {
  5666. IScenePresence presence = World.GetScenePresence(key);
  5667. IParcelManagementModule parcelManagement = World.RequestModuleInterface<IParcelManagementModule>();
  5668. if (presence != null) // object is an avatar
  5669. {
  5670. if (parcelManagement != null)
  5671. {
  5672. if (m_host.OwnerID
  5673. == parcelManagement.GetLandObject(
  5674. presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID)
  5675. return 1;
  5676. }
  5677. }
  5678. else // object is not an avatar
  5679. {
  5680. ISceneChildEntity obj = World.GetSceneObjectPart(key);
  5681. if (obj != null)
  5682. if (parcelManagement != null)
  5683. {
  5684. if (m_host.OwnerID
  5685. == parcelManagement.GetLandObject(
  5686. obj.AbsolutePosition.X, obj.AbsolutePosition.Y).LandData.OwnerID)
  5687. return 1;
  5688. }
  5689. }
  5690. }
  5691. return 0;
  5692. }
  5693. public LSL_String llGetLandOwnerAt(LSL_Vector pos)
  5694. {
  5695. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  5696. IParcelManagementModule parcelManagement = World.RequestModuleInterface<IParcelManagementModule>();
  5697. if (parcelManagement != null)
  5698. {
  5699. ILandObject land = parcelManagement.GetLandObject((float)pos.x, (float)pos.y);
  5700. if (land != null)
  5701. return land.LandData.OwnerID.ToString();
  5702. }
  5703. return UUID.Zero.ToString();
  5704. }
  5705. /// <summary>
  5706. /// According to http://lslwiki.net/lslwiki/wakka.php?wakka=llGetAgentSize
  5707. /// only the height of avatars vary and that says:
  5708. /// Width (x) and depth (y) are constant. (0.45m and 0.6m respectively).
  5709. /// </summary>
  5710. public LSL_Vector llGetAgentSize(string id)
  5711. {
  5712. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
  5713. IScenePresence avatar = World.GetScenePresence((UUID)id);
  5714. LSL_Vector agentSize;
  5715. if (avatar == null || avatar.IsChildAgent) // Fail if not in the same region
  5716. {
  5717. agentSize = ScriptBaseClass.ZERO_VECTOR;
  5718. }
  5719. else
  5720. {
  5721. IAvatarAppearanceModule appearance = avatar.RequestModuleInterface<IAvatarAppearanceModule>();
  5722. agentSize = appearance != null ? new LSL_Vector(0.45, 0.6, appearance.Appearance.AvatarHeight) : ScriptBaseClass.ZERO_VECTOR;
  5723. }
  5724. return agentSize;
  5725. }
  5726. public LSL_Integer llSameGroup(string agent)
  5727. {
  5728. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Integer();
  5729. UUID agentId = new UUID();
  5730. if (!UUID.TryParse(agent, out agentId))
  5731. return new LSL_Integer(0);
  5732. IScenePresence presence = World.GetScenePresence(agentId);
  5733. if (presence == null || presence.IsChildAgent) // Return flase for child agents
  5734. return new LSL_Integer(0);
  5735. IClientAPI client = presence.ControllingClient;
  5736. if (m_host.GroupID == client.ActiveGroupId)
  5737. return new LSL_Integer(1);
  5738. return new LSL_Integer(0);
  5739. }
  5740. public void llUnSit(string id)
  5741. {
  5742. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  5743. UUID key = new UUID();
  5744. if (UUID.TryParse(id, out key))
  5745. {
  5746. IScenePresence av = World.GetScenePresence(key);
  5747. if (av != null)
  5748. {
  5749. if (m_host.ParentEntity.SitTargetAvatar.Contains(key))
  5750. {
  5751. // if the avatar is sitting on this object, then
  5752. // we can unsit them. We don't want random scripts unsitting random people
  5753. // Lets avoid the popcorn avatar scenario.
  5754. av.StandUp();
  5755. }
  5756. else
  5757. {
  5758. // If the object owner also owns the parcel
  5759. // or
  5760. // if the land is group owned and the object is group owned by the same group
  5761. // or
  5762. // if the object is owned by a person with estate access.
  5763. IParcelManagementModule parcelManagement = World.RequestModuleInterface<IParcelManagementModule>();
  5764. if (parcelManagement != null)
  5765. {
  5766. ILandObject parcel = parcelManagement.GetLandObject(av.AbsolutePosition.X, av.AbsolutePosition.Y);
  5767. if (parcel != null)
  5768. {
  5769. if (m_host.OwnerID == parcel.LandData.OwnerID ||
  5770. (m_host.OwnerID == m_host.GroupID && m_host.GroupID == parcel.LandData.GroupID
  5771. && parcel.LandData.IsGroupOwned) || World.Permissions.IsGod(m_host.OwnerID))
  5772. {
  5773. av.StandUp();
  5774. }
  5775. }
  5776. }
  5777. }
  5778. }
  5779. }
  5780. }
  5781. public LSL_Vector llGroundSlope(LSL_Vector offset)
  5782. {
  5783. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
  5784. //Get the slope normal. This gives us the equation of the plane tangent to the slope.
  5785. LSL_Vector vsn = llGroundNormal(offset);
  5786. //Plug the x,y coordinates of the slope normal into the equation of the plane to get
  5787. //the height of that point on the plane. The resulting vector gives the slope.
  5788. Vector3 vsl = new Vector3
  5789. {
  5790. X = (float)vsn.x,
  5791. Y = (float)vsn.y,
  5792. Z = (float)(((vsn.x * vsn.x) + (vsn.y * vsn.y)) / (-1 * vsn.z))
  5793. };
  5794. vsl.Normalize();
  5795. //Normalization might be overkill here
  5796. return new LSL_Vector(vsl.X, vsl.Y, vsl.Z);
  5797. }
  5798. public LSL_Vector llGroundNormal(LSL_Vector offset)
  5799. {
  5800. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
  5801. Vector3 pos = m_host.GetWorldPosition() + new Vector3((float)offset.x,
  5802. (float)offset.y,
  5803. (float)offset.z);
  5804. ITerrainChannel heightmap = World.RequestModuleInterface<ITerrainChannel>();
  5805. // Clamp to valid position
  5806. if (pos.X < 0)
  5807. pos.X = 0;
  5808. else if (pos.X >= heightmap.Width)
  5809. pos.X = heightmap.Width - 1;
  5810. if (pos.Y < 0)
  5811. pos.Y = 0;
  5812. else if (pos.Y >= heightmap.Height)
  5813. pos.Y = heightmap.Height - 1;
  5814. //Find two points in addition to the position to define a plane
  5815. Vector3 p0 = new Vector3(pos.X, pos.Y,
  5816. heightmap[(int)pos.X, (int)pos.Y]);
  5817. Vector3 p1 = new Vector3();
  5818. Vector3 p2 = new Vector3();
  5819. if ((pos.X + 1.0f) >= heightmap.Width)
  5820. p1 = new Vector3(pos.X + 1.0f, pos.Y,
  5821. heightmap[(int)pos.X, (int)pos.Y]);
  5822. else
  5823. p1 = new Vector3(pos.X + 1.0f, pos.Y,
  5824. heightmap[(int)(pos.X + 1.0f), (int)pos.Y]);
  5825. if ((pos.Y + 1.0f) >= heightmap.Height)
  5826. p2 = new Vector3(pos.X, pos.Y + 1.0f,
  5827. heightmap[(int)pos.X, (int)pos.Y]);
  5828. else
  5829. p2 = new Vector3(pos.X, pos.Y + 1.0f,
  5830. heightmap[(int)pos.X, (int)(pos.Y + 1.0f)]);
  5831. //Find normalized vectors from p0 to p1 and p0 to p2
  5832. Vector3 v0 = new Vector3(p1.X - p0.X, p1.Y - p0.Y, p1.Z - p0.Z);
  5833. Vector3 v1 = new Vector3(p2.X - p0.X, p2.Y - p0.Y, p2.Z - p0.Z);
  5834. // v0.Normalize();
  5835. // v1.Normalize();
  5836. //Find the cross product of the vectors (the slope normal).
  5837. Vector3 vsn = new Vector3
  5838. {
  5839. X = (v0.Y * v1.Z) - (v0.Z * v1.Y),
  5840. Y = (v0.Z * v1.X) - (v0.X * v1.Z),
  5841. Z = (v0.X * v1.Y) - (v0.Y * v1.X)
  5842. };
  5843. vsn.Normalize();
  5844. //I believe the crossproduct of two normalized vectors is a normalized vector so
  5845. //this normalization may be overkill
  5846. // then don't normalize them just the result
  5847. return new LSL_Vector(vsn.X, vsn.Y, vsn.Z);
  5848. }
  5849. public LSL_Vector llGroundContour(LSL_Vector offset)
  5850. {
  5851. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
  5852. LSL_Vector x = llGroundSlope(offset);
  5853. return new LSL_Vector(-x.y, x.x, 0.0);
  5854. }
  5855. public LSL_Integer llGetAttached()
  5856. {
  5857. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Integer();
  5858. return (int)m_host.ParentEntity.RootChild.AttachmentPoint;
  5859. }
  5860. public LSL_Integer llGetFreeMemory()
  5861. {
  5862. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Integer();
  5863. // Make scripts designed for LSO happy
  5864. return 16384;
  5865. }
  5866. public LSL_Integer llSetMemoryLimit(LSL_Integer limit)
  5867. {
  5868. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  5869. return new LSL_Integer();
  5870. // Make scripts designed for LSO happy
  5871. return 16384;
  5872. }
  5873. public LSL_Integer llGetMemoryLimit()
  5874. {
  5875. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  5876. return new LSL_Integer();
  5877. // Make scripts designed for LSO happy
  5878. return 16384;
  5879. }
  5880. public LSL_Integer llGetSPMaxMemory()
  5881. {
  5882. //TODO: Not implemented!
  5883. return 0;
  5884. }
  5885. public LSL_Integer llGetUsedMemory()
  5886. {
  5887. //TODO: Not implemented!
  5888. return 0;
  5889. }
  5890. public void llScriptProfiler(LSL_Integer profilerFlags)
  5891. {
  5892. //TODO: We don't support this, not implemented
  5893. }
  5894. public LSL_Integer llGetFreeURLs()
  5895. {
  5896. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Integer();
  5897. if (m_UrlModule != null)
  5898. return new LSL_Integer(m_UrlModule.GetFreeUrls());
  5899. return new LSL_Integer(0);
  5900. }
  5901. public LSL_String llGetRegionName()
  5902. {
  5903. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_String();
  5904. return World.RegionInfo.RegionName;
  5905. }
  5906. public LSL_Float llGetRegionTimeDilation()
  5907. {
  5908. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
  5909. return World.TimeDilation;
  5910. }
  5911. /// <summary>
  5912. /// Returns the value reported in the client Statistics window
  5913. /// </summary>
  5914. public LSL_Float llGetRegionFPS()
  5915. {
  5916. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
  5917. ISimFrameMonitor reporter = (ISimFrameMonitor)World.RequestModuleInterface<IMonitorModule>().GetMonitor(World.RegionInfo.RegionID.ToString(), MonitorModuleHelper.SimFrameStats);
  5918. if (reporter != null)
  5919. return reporter.LastReportedSimFPS;
  5920. return 0;
  5921. }
  5922. /* particle system rules should be coming into this routine as doubles, that is
  5923. rule[0] should be an integer from this list and rule[1] should be the arg
  5924. for the same integer. wiki.secondlife.com has most of this mapping, but some
  5925. came from http://www.caligari-designs.com/p4u2
  5926. We iterate through the list for 'Count' elements, incrementing by two for each
  5927. iteration and set the members of Primitive.ParticleSystem, one at a time.
  5928. */
  5929. public enum PrimitiveRule
  5930. {
  5931. PSYS_PART_FLAGS = 0,
  5932. PSYS_PART_START_COLOR = 1,
  5933. PSYS_PART_START_ALPHA = 2,
  5934. PSYS_PART_END_COLOR = 3,
  5935. PSYS_PART_END_ALPHA = 4,
  5936. PSYS_PART_START_SCALE = 5,
  5937. PSYS_PART_END_SCALE = 6,
  5938. PSYS_PART_MAX_AGE = 7,
  5939. PSYS_SRC_ACCEL = 8,
  5940. PSYS_SRC_PATTERN = 9,
  5941. PSYS_SRC_INNERANGLE = 10,
  5942. PSYS_SRC_OUTERANGLE = 11,
  5943. PSYS_SRC_TEXTURE = 12,
  5944. PSYS_SRC_BURST_RATE = 13,
  5945. PSYS_SRC_BURST_PART_COUNT = 15,
  5946. PSYS_SRC_BURST_RADIUS = 16,
  5947. PSYS_SRC_BURST_SPEED_MIN = 17,
  5948. PSYS_SRC_BURST_SPEED_MAX = 18,
  5949. PSYS_SRC_MAX_AGE = 19,
  5950. PSYS_SRC_TARGET_KEY = 20,
  5951. PSYS_SRC_OMEGA = 21,
  5952. PSYS_SRC_ANGLE_BEGIN = 22,
  5953. PSYS_SRC_ANGLE_END = 23
  5954. }
  5955. internal Primitive.ParticleSystem.ParticleDataFlags ConvertUINTtoFlags(uint flags)
  5956. {
  5957. const Primitive.ParticleSystem.ParticleDataFlags returnval = Primitive.ParticleSystem.ParticleDataFlags.None;
  5958. return returnval;
  5959. }
  5960. protected Primitive.ParticleSystem getNewParticleSystemWithSLDefaultValues()
  5961. {
  5962. Primitive.ParticleSystem ps = new Primitive.ParticleSystem
  5963. {
  5964. PartStartColor = new Color4(1.0f, 1.0f, 1.0f, 1.0f),
  5965. PartEndColor = new Color4(1.0f, 1.0f, 1.0f, 1.0f),
  5966. PartStartScaleX = 1.0f,
  5967. PartStartScaleY = 1.0f,
  5968. PartEndScaleX = 1.0f,
  5969. PartEndScaleY = 1.0f,
  5970. BurstSpeedMin = 1.0f,
  5971. BurstSpeedMax = 1.0f,
  5972. BurstRate = 0.1f,
  5973. PartMaxAge = 10.0f,
  5974. BurstPartCount = 10
  5975. };
  5976. // TODO find out about the other defaults and add them here
  5977. return ps;
  5978. }
  5979. public void llLinkParticleSystem(int linknumber, LSL_List rules)
  5980. {
  5981. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  5982. List<ISceneChildEntity> parts = GetLinkParts(linknumber);
  5983. foreach (var part in parts)
  5984. {
  5985. SetParticleSystem(part, rules);
  5986. }
  5987. }
  5988. public void llParticleSystem(LSL_List rules)
  5989. {
  5990. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  5991. SetParticleSystem(m_host, rules);
  5992. }
  5993. private void SetParticleSystem(ISceneChildEntity part, LSL_List rules)
  5994. {
  5995. if (rules.Length == 0)
  5996. {
  5997. part.RemoveParticleSystem();
  5998. }
  5999. else
  6000. {
  6001. Primitive.ParticleSystem prules = getNewParticleSystemWithSLDefaultValues();
  6002. LSL_Vector tempv = new LSL_Vector();
  6003. for (int i = 0; i < rules.Length; i += 2)
  6004. {
  6005. LSL_Integer rule = rules.GetLSLIntegerItem(i);
  6006. if (rule == (int)ScriptBaseClass.PSYS_PART_FLAGS)
  6007. {
  6008. prules.PartDataFlags = (Primitive.ParticleSystem.ParticleDataFlags)(uint)rules.GetLSLIntegerItem(i + 1);
  6009. }
  6010. else if (rule == (int)ScriptBaseClass.PSYS_PART_START_COLOR)
  6011. {
  6012. tempv = rules.GetVector3Item(i + 1);
  6013. prules.PartStartColor.R = (float)tempv.x;
  6014. prules.PartStartColor.G = (float)tempv.y;
  6015. prules.PartStartColor.B = (float)tempv.z;
  6016. }
  6017. else
  6018. {
  6019. float tempf = 0;
  6020. if (rule == (int)ScriptBaseClass.PSYS_PART_START_ALPHA)
  6021. {
  6022. tempf = (float)rules.GetLSLFloatItem(i + 1);
  6023. prules.PartStartColor.A = tempf;
  6024. }
  6025. else if (rule == (int)ScriptBaseClass.PSYS_PART_END_COLOR)
  6026. {
  6027. tempv = rules.GetVector3Item(i + 1);
  6028. prules.PartEndColor.R = (float)tempv.x;
  6029. prules.PartEndColor.G = (float)tempv.y;
  6030. prules.PartEndColor.B = (float)tempv.z;
  6031. }
  6032. else if (rule == (int)ScriptBaseClass.PSYS_PART_END_ALPHA)
  6033. {
  6034. tempf = (float)rules.GetLSLFloatItem(i + 1);
  6035. prules.PartEndColor.A = tempf;
  6036. }
  6037. else if (rule == (int)ScriptBaseClass.PSYS_PART_START_SCALE)
  6038. {
  6039. tempv = rules.GetVector3Item(i + 1);
  6040. prules.PartStartScaleX = (float)tempv.x;
  6041. prules.PartStartScaleY = (float)tempv.y;
  6042. }
  6043. else if (rule == (int)ScriptBaseClass.PSYS_PART_END_SCALE)
  6044. {
  6045. tempv = rules.GetVector3Item(i + 1);
  6046. prules.PartEndScaleX = (float)tempv.x;
  6047. prules.PartEndScaleY = (float)tempv.y;
  6048. }
  6049. else if (rule == (int)ScriptBaseClass.PSYS_PART_MAX_AGE)
  6050. {
  6051. tempf = (float)rules.GetLSLFloatItem(i + 1);
  6052. prules.PartMaxAge = tempf;
  6053. }
  6054. else if (rule == (int)ScriptBaseClass.PSYS_SRC_ACCEL)
  6055. {
  6056. tempv = rules.GetVector3Item(i + 1);
  6057. prules.PartAcceleration.X = (float)tempv.x;
  6058. prules.PartAcceleration.Y = (float)tempv.y;
  6059. prules.PartAcceleration.Z = (float)tempv.z;
  6060. }
  6061. else if (rule == (int)ScriptBaseClass.PSYS_SRC_PATTERN)
  6062. {
  6063. int tmpi = rules.GetLSLIntegerItem(i + 1);
  6064. prules.Pattern = (Primitive.ParticleSystem.SourcePattern)tmpi;
  6065. }
  6066. // PSYS_SRC_INNERANGLE and PSYS_SRC_ANGLE_BEGIN use the same variables. The
  6067. // PSYS_SRC_OUTERANGLE and PSYS_SRC_ANGLE_END also use the same variable. The
  6068. // client tells the difference between the two by looking at the 0x02 bit in
  6069. // the PartFlags variable.
  6070. else if (rule == (int)ScriptBaseClass.PSYS_SRC_INNERANGLE)
  6071. {
  6072. tempf = (float)rules.GetLSLFloatItem(i + 1);
  6073. prules.InnerAngle = tempf;
  6074. prules.PartFlags &= 0xFFFFFFFD; // Make sure new angle format is off.
  6075. }
  6076. else if (rule == (int)ScriptBaseClass.PSYS_SRC_OUTERANGLE)
  6077. {
  6078. tempf = (float)rules.GetLSLFloatItem(i + 1);
  6079. prules.OuterAngle = tempf;
  6080. prules.PartFlags &= 0xFFFFFFFD; // Make sure new angle format is off.
  6081. }
  6082. else if (rule == (int)ScriptBaseClass.PSYS_SRC_TEXTURE)
  6083. {
  6084. prules.Texture = KeyOrName(rules.GetLSLStringItem(i + 1), false);
  6085. }
  6086. else if (rule == (int)ScriptBaseClass.PSYS_SRC_BURST_RATE)
  6087. {
  6088. tempf = (float)rules.GetLSLFloatItem(i + 1);
  6089. prules.BurstRate = tempf;
  6090. }
  6091. else if (rule == (int)ScriptBaseClass.PSYS_SRC_BURST_PART_COUNT)
  6092. {
  6093. prules.BurstPartCount = (byte)(int)rules.GetLSLIntegerItem(i + 1);
  6094. }
  6095. else if (rule == (int)ScriptBaseClass.PSYS_SRC_BURST_RADIUS)
  6096. {
  6097. tempf = (float)rules.GetLSLFloatItem(i + 1);
  6098. prules.BurstRadius = tempf;
  6099. }
  6100. else if (rule == (int)ScriptBaseClass.PSYS_SRC_BURST_SPEED_MIN)
  6101. {
  6102. tempf = (float)rules.GetLSLFloatItem(i + 1);
  6103. prules.BurstSpeedMin = tempf;
  6104. }
  6105. else if (rule == (int)ScriptBaseClass.PSYS_SRC_BURST_SPEED_MAX)
  6106. {
  6107. tempf = (float)rules.GetLSLFloatItem(i + 1);
  6108. prules.BurstSpeedMax = tempf;
  6109. }
  6110. else if (rule == (int)ScriptBaseClass.PSYS_SRC_MAX_AGE)
  6111. {
  6112. tempf = (float)rules.GetLSLFloatItem(i + 1);
  6113. prules.MaxAge = tempf;
  6114. }
  6115. else if (rule == (int)ScriptBaseClass.PSYS_SRC_TARGET_KEY)
  6116. {
  6117. UUID key = UUID.Zero;
  6118. prules.Target = UUID.TryParse(rules.Data[i + 1].ToString(), out key) ? key : part.UUID;
  6119. }
  6120. else if (rule == (int)ScriptBaseClass.PSYS_SRC_OMEGA)
  6121. {
  6122. // AL: This is an assumption, since it is the only thing that would match.
  6123. tempv = rules.GetVector3Item(i + 1);
  6124. prules.AngularVelocity.X = (float)tempv.x;
  6125. prules.AngularVelocity.Y = (float)tempv.y;
  6126. prules.AngularVelocity.Z = (float)tempv.z;
  6127. }
  6128. else if (rule == (int)ScriptBaseClass.PSYS_SRC_ANGLE_BEGIN)
  6129. {
  6130. tempf = (float)rules.GetLSLFloatItem(i + 1);
  6131. prules.InnerAngle = tempf;
  6132. prules.PartFlags |= 0x02; // Set new angle format.
  6133. }
  6134. else if (rule == (int)ScriptBaseClass.PSYS_SRC_ANGLE_END)
  6135. {
  6136. tempf = (float)rules.GetLSLFloatItem(i + 1);
  6137. prules.OuterAngle = tempf;
  6138. prules.PartFlags |= 0x02; // Set new angle format.
  6139. }
  6140. }
  6141. }
  6142. prules.CRC = 1;
  6143. part.AddNewParticleSystem(prules);
  6144. }
  6145. part.ScheduleUpdate(PrimUpdateFlags.Particles);
  6146. }
  6147. public void llGroundRepel(double height, int water, double tau)
  6148. {
  6149. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  6150. if (m_host.PhysActor != null)
  6151. {
  6152. float ground = (float)llGround(new LSL_Types.Vector3(0, 0, 0));
  6153. float waterLevel = (float)llWater(new LSL_Types.Vector3(0, 0, 0));
  6154. PIDHoverType hoverType = PIDHoverType.Ground;
  6155. if (water != 0)
  6156. {
  6157. hoverType = PIDHoverType.GroundAndWater;
  6158. if (ground < waterLevel)
  6159. height += waterLevel;
  6160. else
  6161. height += ground;
  6162. }
  6163. else
  6164. {
  6165. height += ground;
  6166. }
  6167. m_host.SetHoverHeight((float)height, hoverType, (float)tau);
  6168. }
  6169. }
  6170. protected UUID GetTaskInventoryItem(string name)
  6171. {
  6172. lock (m_host.TaskInventory)
  6173. {
  6174. foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
  6175. {
  6176. if (inv.Value.Name == name)
  6177. return inv.Key;
  6178. }
  6179. }
  6180. return UUID.Zero;
  6181. }
  6182. public void llGiveInventoryList(string destination, string category, LSL_List inventory)
  6183. {
  6184. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  6185. UUID destID;
  6186. if (!UUID.TryParse(destination, out destID))
  6187. return;
  6188. List<UUID> itemList = new List<UUID>();
  6189. foreach (Object item in inventory.Data)
  6190. {
  6191. UUID itemID;
  6192. if (UUID.TryParse(item.ToString(), out itemID))
  6193. {
  6194. itemList.Add(itemID);
  6195. }
  6196. else
  6197. {
  6198. itemID = GetTaskInventoryItem(item.ToString());
  6199. if (itemID != UUID.Zero)
  6200. itemList.Add(itemID);
  6201. }
  6202. }
  6203. if (itemList.Count == 0)
  6204. return;
  6205. UUID folderID = UUID.Zero;
  6206. ILLClientInventory inventoryModule = World.RequestModuleInterface<ILLClientInventory>();
  6207. if (inventoryModule != null)
  6208. folderID = inventoryModule.MoveTaskInventoryItemsToUserInventory(destID, category, m_host, itemList);
  6209. if (folderID == UUID.Zero)
  6210. return;
  6211. byte[] bucket = new byte[17];
  6212. bucket[0] = (byte)AssetType.Folder;
  6213. byte[] objBytes = folderID.GetBytes();
  6214. Array.Copy(objBytes, 0, bucket, 1, 16);
  6215. GridInstantMessage msg = new GridInstantMessage(World,
  6216. m_host.UUID, m_host.Name + ", an object owned by " +
  6217. resolveName(m_host.OwnerID) + ",", destID,
  6218. (byte)InstantMessageDialog.InventoryOffered,
  6219. false, category + "\n" + m_host.Name + " is located at " +
  6220. World.RegionInfo.RegionName + " " +
  6221. m_host.AbsolutePosition.ToString(),
  6222. folderID, true, m_host.AbsolutePosition,
  6223. bucket);
  6224. if (m_TransferModule != null)
  6225. m_TransferModule.SendInstantMessage(msg);
  6226. }
  6227. public void llSetVehicleType(int type)
  6228. {
  6229. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  6230. if (m_host.ParentEntity != null)
  6231. {
  6232. if (!m_host.ParentEntity.IsDeleted)
  6233. {
  6234. m_host.ParentEntity.RootChild.SetVehicleType(type);
  6235. }
  6236. }
  6237. }
  6238. //CFK 9/28: Most, but not all of the underlying plumbing between here and the physics modules is in
  6239. //CFK 9/28: so these are not complete yet.
  6240. public void llSetVehicleFloatParam(int param, LSL_Float value)
  6241. {
  6242. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  6243. if (m_host.ParentEntity != null)
  6244. {
  6245. if (!m_host.ParentEntity.IsDeleted)
  6246. {
  6247. m_host.ParentEntity.RootChild.SetVehicleFloatParam(param, (float)value);
  6248. }
  6249. }
  6250. }
  6251. //CFK 9/28: Most, but not all of the underlying plumbing between here and the physics modules is in
  6252. //CFK 9/28: so these are not complete yet.
  6253. public void llSetVehicleVectorParam(int param, LSL_Vector vec)
  6254. {
  6255. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  6256. if (m_host.ParentEntity != null)
  6257. {
  6258. if (!m_host.ParentEntity.IsDeleted)
  6259. {
  6260. m_host.ParentEntity.RootChild.SetVehicleVectorParam(param,
  6261. new Vector3((float)vec.x, (float)vec.y, (float)vec.z));
  6262. }
  6263. }
  6264. }
  6265. //CFK 9/28: Most, but not all of the underlying plumbing between here and the physics modules is in
  6266. //CFK 9/28: so these are not complete yet.
  6267. public void llSetVehicleRotationParam(int param, LSL_Rotation rot)
  6268. {
  6269. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  6270. if (m_host.ParentEntity != null)
  6271. {
  6272. if (!m_host.ParentEntity.IsDeleted)
  6273. {
  6274. m_host.ParentEntity.RootChild.SetVehicleRotationParam(param,
  6275. Rot2Quaternion(rot));
  6276. }
  6277. }
  6278. }
  6279. public void llSetVehicleFlags(int flags)
  6280. {
  6281. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  6282. if (m_host.ParentEntity != null)
  6283. {
  6284. if (!m_host.ParentEntity.IsDeleted)
  6285. {
  6286. m_host.ParentEntity.RootChild.SetVehicleFlags(flags, false);
  6287. }
  6288. }
  6289. }
  6290. public void llRemoveVehicleFlags(int flags)
  6291. {
  6292. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  6293. if (m_host.ParentEntity != null)
  6294. {
  6295. if (!m_host.ParentEntity.IsDeleted)
  6296. {
  6297. m_host.ParentEntity.RootChild.SetVehicleFlags(flags, true);
  6298. }
  6299. }
  6300. }
  6301. public void llSitTarget(LSL_Vector offset, LSL_Rotation rot)
  6302. {
  6303. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  6304. // LSL quaternions can normalize to 0, normal Quaternions can't.
  6305. if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0)
  6306. rot.z = 1; // ZERO_ROTATION = 0,0,0,1
  6307. m_host.SitTargetPosition = new Vector3((float)offset.x, (float)offset.y, (float)offset.z);
  6308. m_host.SitTargetOrientation = Rot2Quaternion(rot);
  6309. }
  6310. public void llLinkSitTarget(LSL_Integer link, LSL_Vector offset, LSL_Rotation rot)
  6311. {
  6312. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  6313. // LSL quaternions can normalize to 0, normal Quaternions can't.
  6314. if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0)
  6315. rot.z = 1; // ZERO_ROTATION = 0,0,0,1
  6316. List<ISceneChildEntity> entities = GetLinkParts(link);
  6317. if (entities.Count == 0)
  6318. return;
  6319. entities[0].SitTargetPosition = new Vector3((float)offset.x, (float)offset.y, (float)offset.z);
  6320. entities[0].SitTargetOrientation = Rot2Quaternion(rot);
  6321. }
  6322. public LSL_String llAvatarOnSitTarget()
  6323. {
  6324. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  6325. return m_host.SitTargetAvatar.Count > 0
  6326. ? new LSL_String(m_host.SitTargetAvatar[0].ToString())
  6327. : ScriptBaseClass.NULL_KEY;
  6328. }
  6329. public LSL_Key llAvatarOnLinkSitTarget()
  6330. {
  6331. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Key();
  6332. return m_host.SitTargetAvatar.Count > 0
  6333. ? new LSL_String(m_host.SitTargetAvatar[0].ToString())
  6334. : ScriptBaseClass.NULL_KEY;
  6335. }
  6336. public DateTime llAddToLandPassList(string avatar, double hours)
  6337. {
  6338. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return DateTime.Now;
  6339. IParcelManagementModule parcelManagement = World.RequestModuleInterface<IParcelManagementModule>();
  6340. if (parcelManagement != null)
  6341. {
  6342. LandData land = parcelManagement.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).LandData;
  6343. if (land.OwnerID == m_host.OwnerID)
  6344. {
  6345. ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
  6346. UUID key;
  6347. if (UUID.TryParse(avatar, out key))
  6348. {
  6349. entry.AgentID = key;
  6350. entry.Flags = AccessList.Access;
  6351. entry.Time = DateTime.Now.AddHours(hours);
  6352. land.ParcelAccessList.Add(entry);
  6353. }
  6354. }
  6355. }
  6356. return PScriptSleep(100);
  6357. }
  6358. public void llSetTouchText(string text)
  6359. {
  6360. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  6361. m_host.TouchName = text;
  6362. }
  6363. public void llSetSitText(string text)
  6364. {
  6365. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  6366. m_host.SitName = text;
  6367. }
  6368. public void llSetLinkCamera(LSL_Integer link, LSL_Vector eye, LSL_Vector at)
  6369. {
  6370. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  6371. List<ISceneChildEntity> entities = GetLinkParts(link);
  6372. if (entities.Count > 0)
  6373. {
  6374. entities[0].CameraEyeOffset = new Vector3((float)eye.x, (float)eye.y, (float)eye.z);
  6375. entities[0].CameraAtOffset = new Vector3((float)at.x, (float)at.y, (float)at.z);
  6376. }
  6377. }
  6378. public void llSetCameraEyeOffset(LSL_Vector offset)
  6379. {
  6380. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  6381. m_host.CameraEyeOffset = new Vector3((float)offset.x, (float)offset.y, (float)offset.z);
  6382. }
  6383. public void llSetCameraAtOffset(LSL_Vector offset)
  6384. {
  6385. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  6386. m_host.CameraAtOffset = new Vector3((float)offset.x, (float)offset.y, (float)offset.z);
  6387. }
  6388. public LSL_String llDumpList2String(LSL_List src, string seperator)
  6389. {
  6390. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  6391. if (src.Length == 0)
  6392. {
  6393. return String.Empty;
  6394. }
  6395. #if (!ISWIN)
  6396. string ret = "";
  6397. foreach (object o in src.Data)
  6398. ret += o.ToString() + seperator;
  6399. #else
  6400. string ret = src.Data.Aggregate("", (current, o) => current + (o.ToString() + seperator));
  6401. #endif
  6402. ret = ret.Substring(0, ret.Length - seperator.Length);
  6403. return ret;
  6404. }
  6405. public LSL_Integer llScriptDanger(LSL_Vector pos)
  6406. {
  6407. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  6408. bool result = m_ScriptEngine.PipeEventsForScript(m_host, new Vector3((float)pos.x, (float)pos.y, (float)pos.z));
  6409. if (result)
  6410. {
  6411. return 1;
  6412. }
  6413. return 0;
  6414. }
  6415. public DateTime llDialog(string avatar, string message, LSL_List buttons, int chat_channel)
  6416. {
  6417. IDialogModule dm = World.RequestModuleInterface<IDialogModule>();
  6418. if (dm == null)
  6419. return DateTime.Now;
  6420. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return DateTime.Now;
  6421. UUID av = new UUID();
  6422. if (!UUID.TryParse(avatar, out av))
  6423. {
  6424. //Silently accepted in in SL NOTE: it does sleep though!
  6425. //LSLError("First parameter to llDialog needs to be a key");
  6426. return PScriptSleep(1000);
  6427. }
  6428. if (buttons.Length > 12)
  6429. {
  6430. LSLError("No more than 12 buttons can be shown");
  6431. return DateTime.Now;
  6432. }
  6433. string[] buts = new string[buttons.Length];
  6434. for (int i = 0; i < buttons.Length; i++)
  6435. {
  6436. if (buttons.Data[i].ToString() == String.Empty)
  6437. {
  6438. LSLError("button label cannot be blank");
  6439. return DateTime.Now;
  6440. }
  6441. if (buttons.Data[i].ToString().Length > 24)
  6442. {
  6443. LSLError("button label cannot be longer than 24 characters");
  6444. return DateTime.Now;
  6445. }
  6446. buts[i] = buttons.Data[i].ToString();
  6447. }
  6448. if (buts.Length == 0)
  6449. buts = new[] { "OK" };
  6450. dm.SendDialogToUser(
  6451. av, m_host.Name, m_host.UUID, m_host.OwnerID,
  6452. message, new UUID("00000000-0000-2222-3333-100000001000"), chat_channel, buts);
  6453. return PScriptSleep(1000);
  6454. }
  6455. public void llVolumeDetect(int detect)
  6456. {
  6457. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  6458. if (m_host.ParentEntity != null)
  6459. {
  6460. if (!m_host.ParentEntity.IsDeleted)
  6461. {
  6462. m_host.ParentEntity.RootChild.ScriptSetVolumeDetect(detect != 0);
  6463. }
  6464. }
  6465. }
  6466. /// <summary>
  6467. /// This is a depecated function so this just replicates the result of
  6468. /// invoking it in SL
  6469. /// </summary>
  6470. public DateTime llRemoteLoadScript(string target, string name, int running, int start_param)
  6471. {
  6472. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return DateTime.Now;
  6473. // Report an error as it does in SL
  6474. ShoutError("Deprecated. Please use llRemoteLoadScriptPin instead.");
  6475. return PScriptSleep(3000);
  6476. }
  6477. public void llSetRemoteScriptAccessPin(int pin)
  6478. {
  6479. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  6480. m_host.ScriptAccessPin = pin;
  6481. }
  6482. public DateTime llRemoteLoadScriptPin(string target, string name, int pin, int running, int start_param)
  6483. {
  6484. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return DateTime.Now;
  6485. bool found = false;
  6486. UUID destId = UUID.Zero;
  6487. UUID srcId = UUID.Zero;
  6488. if (!UUID.TryParse(target, out destId))
  6489. {
  6490. llSay(0, "Could not parse key " + target);
  6491. return DateTime.Now;
  6492. }
  6493. // target must be a different prim than the one containing the script
  6494. if (m_host.UUID == destId)
  6495. {
  6496. return DateTime.Now;
  6497. }
  6498. // copy the first script found with this inventory name
  6499. lock (m_host.TaskInventory)
  6500. {
  6501. foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
  6502. {
  6503. if (inv.Value.Name == name)
  6504. {
  6505. // make sure the object is a script
  6506. if (10 == inv.Value.Type)
  6507. {
  6508. found = true;
  6509. srcId = inv.Key;
  6510. break;
  6511. }
  6512. }
  6513. }
  6514. }
  6515. if (!found)
  6516. {
  6517. llSay(0, "Could not find script " + name);
  6518. return DateTime.Now;
  6519. }
  6520. // the rest of the permission checks are done in RezScript, so check the pin there as well
  6521. ILLClientInventory inventoryModule = World.RequestModuleInterface<ILLClientInventory>();
  6522. if (inventoryModule != null)
  6523. inventoryModule.RezScript(srcId, m_host, destId, pin, running, start_param);
  6524. // this will cause the delay even if the script pin or permissions were wrong - seems ok
  6525. return PScriptSleep(3000);
  6526. }
  6527. public DateTime llOpenRemoteDataChannel()
  6528. {
  6529. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return DateTime.Now;
  6530. IXMLRPC xmlrpcMod = World.RequestModuleInterface<IXMLRPC>();
  6531. if (xmlrpcMod.IsEnabled())
  6532. {
  6533. UUID channelID = xmlrpcMod.OpenXMLRPCChannel(m_host.UUID, m_itemID, UUID.Zero);
  6534. IXmlRpcRouter xmlRpcRouter = World.RequestModuleInterface<IXmlRpcRouter>();
  6535. if (xmlRpcRouter != null)
  6536. {
  6537. string ExternalHostName = MainServer.Instance.HostName;
  6538. xmlRpcRouter.RegisterNewReceiver(m_ScriptEngine.ScriptModule, channelID, m_host.UUID,
  6539. m_itemID, String.Format("http://{0}:{1}/", ExternalHostName,
  6540. xmlrpcMod.Port.ToString()));
  6541. }
  6542. object[] resobj = new object[]
  6543. {
  6544. new LSL_Integer(1),
  6545. new LSL_String(channelID.ToString()),
  6546. new LSL_String(UUID.Zero.ToString()),
  6547. new LSL_String(String.Empty),
  6548. new LSL_Integer(0),
  6549. new LSL_String(String.Empty)
  6550. };
  6551. m_ScriptEngine.PostScriptEvent(m_itemID, m_host.UUID, new EventParams("remote_data", resobj,
  6552. new DetectParams[0]), EventPriority.FirstStart);
  6553. }
  6554. return PScriptSleep(1000);
  6555. }
  6556. public LSL_Key llSendRemoteData(string channel, string dest, int idata, string sdata)
  6557. {
  6558. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  6559. IXMLRPC xmlrpcMod = World.RequestModuleInterface<IXMLRPC>();
  6560. ScriptSleep(3000);
  6561. return (xmlrpcMod.SendRemoteData(m_host.UUID, m_itemID, channel, dest, idata, sdata)).ToString();
  6562. }
  6563. public DateTime llRemoteDataReply(string channel, string message_id, string sdata, int idata)
  6564. {
  6565. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return DateTime.Now;
  6566. IXMLRPC xmlrpcMod = World.RequestModuleInterface<IXMLRPC>();
  6567. xmlrpcMod.RemoteDataReply(channel, message_id, sdata, idata);
  6568. return PScriptSleep(100);
  6569. }
  6570. public DateTime llCloseRemoteDataChannel(object _channel)
  6571. {
  6572. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return DateTime.Now;
  6573. IXMLRPC xmlrpcMod = World.RequestModuleInterface<IXMLRPC>();
  6574. xmlrpcMod.CloseXMLRPCChannel(UUID.Parse(_channel.ToString()));
  6575. return PScriptSleep(100);
  6576. }
  6577. public LSL_String llMD5String(string src, int nonce)
  6578. {
  6579. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_String();
  6580. return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString()));
  6581. }
  6582. public LSL_String llSHA1String(string src)
  6583. {
  6584. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  6585. return Util.SHA1Hash(src).ToLower();
  6586. }
  6587. protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(ISceneChildEntity part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist)
  6588. {
  6589. ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
  6590. if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT &&
  6591. holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE &&
  6592. holeshape != (int)ScriptBaseClass.PRIM_HOLE_SQUARE &&
  6593. holeshape != (int)ScriptBaseClass.PRIM_HOLE_TRIANGLE)
  6594. {
  6595. holeshape = ScriptBaseClass.PRIM_HOLE_DEFAULT;
  6596. }
  6597. shapeBlock.ProfileCurve = (byte)holeshape;
  6598. if (cut.x < 0f)
  6599. {
  6600. cut.x = 0f;
  6601. }
  6602. if (cut.x > 1f)
  6603. {
  6604. cut.x = 1f;
  6605. }
  6606. if (cut.y < 0f)
  6607. {
  6608. cut.y = 0f;
  6609. }
  6610. if (cut.y > 1f)
  6611. {
  6612. cut.y = 1f;
  6613. }
  6614. if (cut.y - cut.x < 0.05f)
  6615. {
  6616. cut.x = cut.y - 0.05f;
  6617. if (cut.x < 0.0f)
  6618. {
  6619. cut.x = 0.0f;
  6620. cut.y = 0.05f;
  6621. }
  6622. }
  6623. shapeBlock.ProfileBegin = (ushort)(50000 * cut.x);
  6624. shapeBlock.ProfileEnd = (ushort)(50000 * (1 - cut.y));
  6625. if (hollow < 0f)
  6626. {
  6627. hollow = 0f;
  6628. }
  6629. if (hollow > 0.95)
  6630. {
  6631. hollow = 0.95f;
  6632. }
  6633. shapeBlock.ProfileHollow = (ushort)(50000 * hollow);
  6634. if (twist.x < -1.0f)
  6635. {
  6636. twist.x = -1.0f;
  6637. }
  6638. if (twist.x > 1.0f)
  6639. {
  6640. twist.x = 1.0f;
  6641. }
  6642. if (twist.y < -1.0f)
  6643. {
  6644. twist.y = -1.0f;
  6645. }
  6646. if (twist.y > 1.0f)
  6647. {
  6648. twist.y = 1.0f;
  6649. }
  6650. // A fairly large precision error occurs for some calculations,
  6651. // if a float or double is directly cast to a byte or sbyte
  6652. // variable, in both .Net and Mono. In .Net, coding
  6653. // "(sbyte)(float)(some expression)" corrects the precision
  6654. // errors. But this does not work for Mono. This longer coding
  6655. // form of creating a tempoary float variable from the
  6656. // expression first, then casting that variable to a byte or
  6657. // sbyte, works for both .Net and Mono. These types of
  6658. // assignments occur in SetPrimtiveBlockShapeParams and
  6659. // SetPrimitiveShapeParams in support of llSetPrimitiveParams.
  6660. float tempFloat = (float)(100.0d * twist.x);
  6661. shapeBlock.PathTwistBegin = (sbyte)tempFloat;
  6662. tempFloat = (float)(100.0d * twist.y);
  6663. shapeBlock.PathTwist = (sbyte)tempFloat;
  6664. shapeBlock.ObjectLocalID = part.LocalId;
  6665. // retain pathcurve
  6666. shapeBlock.PathCurve = part.Shape.PathCurve;
  6667. part.Shape.SculptEntry = false;
  6668. return shapeBlock;
  6669. }
  6670. protected void SetPrimitiveShapeParams(ISceneChildEntity part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector taper_b, LSL_Vector topshear, byte fudge)
  6671. {
  6672. ObjectShapePacket.ObjectDataBlock shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist);
  6673. shapeBlock.ProfileCurve += fudge;
  6674. if (taper_b.x < 0f)
  6675. {
  6676. taper_b.x = 0f;
  6677. }
  6678. if (taper_b.x > 2f)
  6679. {
  6680. taper_b.x = 2f;
  6681. }
  6682. if (taper_b.y < 0f)
  6683. {
  6684. taper_b.y = 0f;
  6685. }
  6686. if (taper_b.y > 2f)
  6687. {
  6688. taper_b.y = 2f;
  6689. }
  6690. float tempFloat = (float)(100.0d * (2.0d - taper_b.x));
  6691. shapeBlock.PathScaleX = (byte)tempFloat;
  6692. tempFloat = (float)(100.0d * (2.0d - taper_b.y));
  6693. shapeBlock.PathScaleY = (byte)tempFloat;
  6694. if (topshear.x < -0.5f)
  6695. {
  6696. topshear.x = -0.5f;
  6697. }
  6698. if (topshear.x > 0.5f)
  6699. {
  6700. topshear.x = 0.5f;
  6701. }
  6702. if (topshear.y < -0.5f)
  6703. {
  6704. topshear.y = -0.5f;
  6705. }
  6706. if (topshear.y > 0.5f)
  6707. {
  6708. topshear.y = 0.5f;
  6709. }
  6710. tempFloat = (float)(100.0d * topshear.x);
  6711. shapeBlock.PathShearX = (byte)tempFloat;
  6712. tempFloat = (float)(100.0d * topshear.y);
  6713. shapeBlock.PathShearY = (byte)tempFloat;
  6714. part.Shape.SculptEntry = false;
  6715. part.UpdateShape(shapeBlock);
  6716. }
  6717. protected void SetPrimitiveShapeParams(ISceneChildEntity part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte fudge)
  6718. {
  6719. ObjectShapePacket.ObjectDataBlock shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist);
  6720. // profile/path swapped for a sphere
  6721. shapeBlock.PathBegin = shapeBlock.ProfileBegin;
  6722. shapeBlock.PathEnd = shapeBlock.ProfileEnd;
  6723. shapeBlock.ProfileCurve += fudge;
  6724. shapeBlock.PathScaleX = 100;
  6725. shapeBlock.PathScaleY = 100;
  6726. if (dimple.x < 0f)
  6727. {
  6728. dimple.x = 0f;
  6729. }
  6730. if (dimple.x > 1f)
  6731. {
  6732. dimple.x = 1f;
  6733. }
  6734. if (dimple.y < 0f)
  6735. {
  6736. dimple.y = 0f;
  6737. }
  6738. if (dimple.y > 1f)
  6739. {
  6740. dimple.y = 1f;
  6741. }
  6742. if (dimple.y - cut.x < 0.05f)
  6743. {
  6744. dimple.x = cut.y - 0.05f;
  6745. }
  6746. shapeBlock.ProfileBegin = (ushort)(50000 * dimple.x);
  6747. shapeBlock.ProfileEnd = (ushort)(50000 * (1 - dimple.y));
  6748. part.Shape.SculptEntry = false;
  6749. part.UpdateShape(shapeBlock);
  6750. }
  6751. protected void SetPrimitiveShapeParams(ISceneChildEntity part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector holesize, LSL_Vector topshear, LSL_Vector profilecut, LSL_Vector taper_a, float revolutions, float radiusoffset, float skew, byte fudge)
  6752. {
  6753. ObjectShapePacket.ObjectDataBlock shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist);
  6754. shapeBlock.ProfileCurve += fudge;
  6755. // profile/path swapped for a torrus, tube, ring
  6756. shapeBlock.PathBegin = shapeBlock.ProfileBegin;
  6757. shapeBlock.PathEnd = shapeBlock.ProfileEnd;
  6758. if (holesize.x < 0.05f)
  6759. {
  6760. holesize.x = 0.05f;
  6761. }
  6762. if (holesize.x > 1f)
  6763. {
  6764. holesize.x = 1f;
  6765. }
  6766. if (holesize.y < 0.05f)
  6767. {
  6768. holesize.y = 0.05f;
  6769. }
  6770. if (holesize.y > 0.5f)
  6771. {
  6772. holesize.y = 0.5f;
  6773. }
  6774. float tempFloat = (float)(100.0d * (2.0d - holesize.x));
  6775. shapeBlock.PathScaleX = (byte)tempFloat;
  6776. tempFloat = (float)(100.0d * (2.0d - holesize.y));
  6777. shapeBlock.PathScaleY = (byte)tempFloat;
  6778. if (topshear.x < -0.5f)
  6779. {
  6780. topshear.x = -0.5f;
  6781. }
  6782. if (topshear.x > 0.5f)
  6783. {
  6784. topshear.x = 0.5f;
  6785. }
  6786. if (topshear.y < -0.5f)
  6787. {
  6788. topshear.y = -0.5f;
  6789. }
  6790. if (topshear.y > 0.5f)
  6791. {
  6792. topshear.y = 0.5f;
  6793. }
  6794. tempFloat = (float)(100.0d * topshear.x);
  6795. shapeBlock.PathShearX = (byte)tempFloat;
  6796. tempFloat = (float)(100.0d * topshear.y);
  6797. shapeBlock.PathShearY = (byte)tempFloat;
  6798. if (profilecut.x < 0f)
  6799. {
  6800. profilecut.x = 0f;
  6801. }
  6802. if (profilecut.x > 1f)
  6803. {
  6804. profilecut.x = 1f;
  6805. }
  6806. if (profilecut.y < 0f)
  6807. {
  6808. profilecut.y = 0f;
  6809. }
  6810. if (profilecut.y > 1f)
  6811. {
  6812. profilecut.y = 1f;
  6813. }
  6814. if (profilecut.y - profilecut.x < 0.05f)
  6815. {
  6816. profilecut.x = profilecut.y - 0.05f;
  6817. if (profilecut.x < 0.0f)
  6818. {
  6819. profilecut.x = 0.0f;
  6820. profilecut.y = 0.05f;
  6821. }
  6822. }
  6823. shapeBlock.ProfileBegin = (ushort)(50000 * profilecut.x);
  6824. shapeBlock.ProfileEnd = (ushort)(50000 * (1 - profilecut.y));
  6825. if (taper_a.x < -1f)
  6826. {
  6827. taper_a.x = -1f;
  6828. }
  6829. if (taper_a.x > 1f)
  6830. {
  6831. taper_a.x = 1f;
  6832. }
  6833. if (taper_a.y < -1f)
  6834. {
  6835. taper_a.y = -1f;
  6836. }
  6837. if (taper_a.y > 1f)
  6838. {
  6839. taper_a.y = 1f;
  6840. }
  6841. tempFloat = (float)(100.0d * taper_a.x);
  6842. shapeBlock.PathTaperX = (sbyte)tempFloat;
  6843. tempFloat = (float)(100.0d * taper_a.y);
  6844. shapeBlock.PathTaperY = (sbyte)tempFloat;
  6845. if (revolutions < 1f)
  6846. {
  6847. revolutions = 1f;
  6848. }
  6849. if (revolutions > 4f)
  6850. {
  6851. revolutions = 4f;
  6852. }
  6853. tempFloat = 66.66667f * (revolutions - 1.0f);
  6854. shapeBlock.PathRevolutions = (byte)tempFloat;
  6855. // limits on radiusoffset depend on revolutions and hole size (how?) seems like the maximum range is 0 to 1
  6856. if (radiusoffset < 0f)
  6857. {
  6858. radiusoffset = 0f;
  6859. }
  6860. if (radiusoffset > 1f)
  6861. {
  6862. radiusoffset = 1f;
  6863. }
  6864. tempFloat = 100.0f * radiusoffset;
  6865. shapeBlock.PathRadiusOffset = (sbyte)tempFloat;
  6866. if (skew < -0.95f)
  6867. {
  6868. skew = -0.95f;
  6869. }
  6870. if (skew > 0.95f)
  6871. {
  6872. skew = 0.95f;
  6873. }
  6874. tempFloat = 100.0f * skew;
  6875. shapeBlock.PathSkew = (sbyte)tempFloat;
  6876. part.Shape.SculptEntry = false;
  6877. part.UpdateShape(shapeBlock);
  6878. }
  6879. protected void SetPrimitiveShapeParams(ISceneChildEntity part, string map, int type)
  6880. {
  6881. ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
  6882. UUID sculptId;
  6883. if (!UUID.TryParse(map, out sculptId))
  6884. {
  6885. sculptId = InventoryKey(map, (int)AssetType.Texture);
  6886. }
  6887. if (sculptId == UUID.Zero)
  6888. return;
  6889. shapeBlock.ObjectLocalID = part.LocalId;
  6890. shapeBlock.PathScaleX = 100;
  6891. shapeBlock.PathScaleY = 150;
  6892. int onlytype = (type & (ScriptBaseClass.PRIM_SCULPT_FLAG_INVERT | ScriptBaseClass.PRIM_SCULPT_FLAG_MIRROR));//Removes the sculpt flags according to libOMV
  6893. if (onlytype != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_CYLINDER &&
  6894. onlytype != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_PLANE &&
  6895. onlytype != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE &&
  6896. onlytype != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS &&
  6897. onlytype != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_MESH)
  6898. {
  6899. // default
  6900. type |= ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE;
  6901. }
  6902. // retain pathcurve
  6903. shapeBlock.PathCurve = part.Shape.PathCurve;
  6904. bool changedTextureID = part.Shape.SculptTexture != sculptId;
  6905. part.Shape.SetSculptProperties((byte)type, sculptId);
  6906. part.Shape.SculptEntry = true;
  6907. part.UpdateShape(shapeBlock, changedTextureID);
  6908. }
  6909. public void llSetPrimitiveParams(LSL_List rules)
  6910. {
  6911. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  6912. SetPrimParams(m_host, rules);
  6913. }
  6914. public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules)
  6915. {
  6916. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  6917. List<IEntity> parts = GetLinkPartsAndEntities(linknumber);
  6918. foreach (IEntity part in parts)
  6919. SetPrimParams(part, rules);
  6920. }
  6921. public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules)
  6922. {
  6923. List<ISceneChildEntity> parts = GetLinkParts(linknumber);
  6924. foreach (ISceneChildEntity part in parts)
  6925. SetPrimParams(part, rules);
  6926. }
  6927. public LSL_Integer llGetLinkNumberOfSides(int LinkNum)
  6928. {
  6929. List<ISceneChildEntity> Parts = GetLinkParts(LinkNum);
  6930. #if (!ISWIN)
  6931. int faces = 0;
  6932. foreach (ISceneChildEntity part in Parts)
  6933. faces += GetNumberOfSides(part);
  6934. #else
  6935. int faces = Parts.Sum(part => GetNumberOfSides(part));
  6936. #endif
  6937. return new LSL_Integer(faces);
  6938. }
  6939. protected void SetPrimParams(IEntity part, LSL_List rules)
  6940. {
  6941. int idx = 0;
  6942. while (idx < rules.Length)
  6943. {
  6944. int code = rules.GetLSLIntegerItem(idx++);
  6945. int remain = rules.Length - idx;
  6946. int face;
  6947. LSL_Vector v;
  6948. if (code == (int)ScriptBaseClass.PRIM_NAME)
  6949. {
  6950. if (remain < 1)
  6951. return;
  6952. string name = rules.Data[idx++].ToString();
  6953. if (part is ISceneChildEntity)
  6954. (part as ISceneChildEntity).Name = name;
  6955. }
  6956. else if (code == (int)ScriptBaseClass.PRIM_DESC)
  6957. {
  6958. if (remain < 1)
  6959. return;
  6960. string desc = rules.Data[idx++].ToString();
  6961. if (part is ISceneChildEntity)
  6962. (part as ISceneChildEntity).Description = desc;
  6963. }
  6964. else if (code == (int)ScriptBaseClass.PRIM_ROT_LOCAL)
  6965. {
  6966. if (remain < 1)
  6967. return;
  6968. LSL_Rotation lr = rules.GetQuaternionItem(idx++);
  6969. if (part is ISceneChildEntity)
  6970. SetRot((part as ISceneChildEntity), Rot2Quaternion(lr));
  6971. }
  6972. else if (code == (int)ScriptBaseClass.PRIM_POSITION)
  6973. {
  6974. if (remain < 1)
  6975. return;
  6976. v = rules.GetVector3Item(idx++);
  6977. if (part is ISceneChildEntity)
  6978. SetPos(part as ISceneChildEntity, v, true);
  6979. else if (part is IScenePresence)
  6980. {
  6981. (part as IScenePresence).OffsetPosition = new Vector3((float)v.x, (float)v.y, (float)v.z);
  6982. (part as IScenePresence).SendTerseUpdateToAllClients();
  6983. }
  6984. }
  6985. else if (code == (int)ScriptBaseClass.PRIM_POS_LOCAL)
  6986. {
  6987. if (remain < 1)
  6988. return;
  6989. v = rules.GetVector3Item(idx++);
  6990. if (part is ISceneChildEntity)
  6991. {
  6992. if (((ISceneChildEntity)part).ParentID != 0)
  6993. ((ISceneChildEntity)part).OffsetPosition = new Vector3((float)v.x, (float)v.y, (float)v.z);
  6994. else
  6995. part.AbsolutePosition = new Vector3((float)v.x, (float)v.y, (float)v.z);
  6996. }
  6997. else if (part is IScenePresence)
  6998. {
  6999. (part as IScenePresence).OffsetPosition = new Vector3((float)v.x, (float)v.y, (float)v.z);
  7000. (part as IScenePresence).SendTerseUpdateToAllClients();
  7001. }
  7002. }
  7003. else if (code == (int)ScriptBaseClass.PRIM_SIZE)
  7004. {
  7005. if (remain < 1)
  7006. return;
  7007. v = rules.GetVector3Item(idx++);
  7008. if (part is ISceneChildEntity)
  7009. SetScale(part as ISceneChildEntity, v);
  7010. }
  7011. else if (code == (int)ScriptBaseClass.PRIM_ROTATION)
  7012. {
  7013. if (remain < 1)
  7014. return;
  7015. LSL_Rotation q = rules.GetQuaternionItem(idx++);
  7016. if (part is ISceneChildEntity)
  7017. {
  7018. // try to let this work as in SL...
  7019. if ((part as ISceneChildEntity).ParentID == 0)
  7020. {
  7021. // special case: If we are root, rotate complete SOG to new rotation
  7022. SetRot(part as ISceneChildEntity, Rot2Quaternion(q));
  7023. }
  7024. else
  7025. {
  7026. // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask.
  7027. ISceneEntity group = (part as ISceneChildEntity).ParentEntity;
  7028. if (group != null) // a bit paranoid, maybe
  7029. {
  7030. ISceneChildEntity rootPart = group.RootChild;
  7031. if (rootPart != null) // again, better safe than sorry
  7032. {
  7033. SetRot((part as ISceneChildEntity), rootPart.RotationOffset * Rot2Quaternion(q));
  7034. }
  7035. }
  7036. }
  7037. }
  7038. else if (part is IScenePresence)
  7039. {
  7040. IScenePresence sp = (IScenePresence)part;
  7041. ISceneChildEntity childObj = sp.Scene.GetSceneObjectPart(sp.SittingOnUUID);
  7042. if (childObj != null)
  7043. {
  7044. sp.Rotation = childObj.ParentEntity.GroupRotation * Rot2Quaternion(q);
  7045. sp.SendTerseUpdateToAllClients();
  7046. }
  7047. }
  7048. }
  7049. else if (code == (int)ScriptBaseClass.PRIM_TYPE)
  7050. {
  7051. if (remain < 3)
  7052. return;
  7053. if (part is ISceneChildEntity) { }
  7054. else
  7055. return;
  7056. code = rules.GetLSLIntegerItem(idx++);
  7057. remain = rules.Length - idx;
  7058. float hollow;
  7059. LSL_Vector twist;
  7060. LSL_Vector taper_b;
  7061. LSL_Vector topshear;
  7062. float revolutions;
  7063. float radiusoffset;
  7064. float skew;
  7065. LSL_Vector holesize;
  7066. LSL_Vector profilecut;
  7067. if (code == (int)ScriptBaseClass.PRIM_TYPE_BOX)
  7068. {
  7069. if (remain < 6)
  7070. return;
  7071. face = rules.GetLSLIntegerItem(idx++);
  7072. v = rules.GetVector3Item(idx++); // cut
  7073. hollow = (float)rules.GetLSLFloatItem(idx++);
  7074. twist = rules.GetVector3Item(idx++);
  7075. taper_b = rules.GetVector3Item(idx++);
  7076. topshear = rules.GetVector3Item(idx++);
  7077. (part as ISceneChildEntity).Shape.PathCurve = (byte)Extrusion.Straight;
  7078. SetPrimitiveShapeParams((part as ISceneChildEntity), face, v, hollow, twist, taper_b, topshear, 1);
  7079. }
  7080. else if (code == (int)ScriptBaseClass.PRIM_TYPE_CYLINDER)
  7081. {
  7082. if (remain < 6)
  7083. return;
  7084. face = rules.GetLSLIntegerItem(idx++); // holeshape
  7085. v = rules.GetVector3Item(idx++); // cut
  7086. hollow = (float)rules.GetLSLFloatItem(idx++);
  7087. twist = rules.GetVector3Item(idx++);
  7088. taper_b = rules.GetVector3Item(idx++);
  7089. topshear = rules.GetVector3Item(idx++);
  7090. (part as ISceneChildEntity).Shape.ProfileShape = ProfileShape.Circle;
  7091. (part as ISceneChildEntity).Shape.PathCurve = (byte)Extrusion.Straight;
  7092. SetPrimitiveShapeParams((part as ISceneChildEntity), face, v, hollow, twist, taper_b, topshear, 0);
  7093. }
  7094. else if (code == (int)ScriptBaseClass.PRIM_TYPE_PRISM)
  7095. {
  7096. if (remain < 6)
  7097. return;
  7098. face = rules.GetLSLIntegerItem(idx++); // holeshape
  7099. v = rules.GetVector3Item(idx++); //cut
  7100. hollow = (float)rules.GetLSLFloatItem(idx++);
  7101. twist = rules.GetVector3Item(idx++);
  7102. taper_b = rules.GetVector3Item(idx++);
  7103. topshear = rules.GetVector3Item(idx++);
  7104. (part as ISceneChildEntity).Shape.PathCurve = (byte)Extrusion.Straight;
  7105. SetPrimitiveShapeParams((part as ISceneChildEntity), face, v, hollow, twist, taper_b, topshear, 3);
  7106. }
  7107. else if (code == (int)ScriptBaseClass.PRIM_TYPE_SPHERE)
  7108. {
  7109. if (remain < 5)
  7110. return;
  7111. face = rules.GetLSLIntegerItem(idx++); // holeshape
  7112. v = rules.GetVector3Item(idx++); // cut
  7113. hollow = (float)rules.GetLSLFloatItem(idx++);
  7114. twist = rules.GetVector3Item(idx++);
  7115. taper_b = rules.GetVector3Item(idx++); // dimple
  7116. (part as ISceneChildEntity).Shape.PathCurve = (byte)Extrusion.Curve1;
  7117. SetPrimitiveShapeParams((part as ISceneChildEntity), face, v, hollow, twist, taper_b, 5);
  7118. }
  7119. else if (code == (int)ScriptBaseClass.PRIM_TYPE_TORUS)
  7120. {
  7121. if (remain < 11)
  7122. return;
  7123. face = rules.GetLSLIntegerItem(idx++); // holeshape
  7124. v = rules.GetVector3Item(idx++); //cut
  7125. hollow = (float)rules.GetLSLFloatItem(idx++);
  7126. twist = rules.GetVector3Item(idx++);
  7127. holesize = rules.GetVector3Item(idx++);
  7128. topshear = rules.GetVector3Item(idx++);
  7129. profilecut = rules.GetVector3Item(idx++);
  7130. taper_b = rules.GetVector3Item(idx++); // taper_a
  7131. revolutions = (float)rules.GetLSLFloatItem(idx++);
  7132. radiusoffset = (float)rules.GetLSLFloatItem(idx++);
  7133. skew = (float)rules.GetLSLFloatItem(idx++);
  7134. (part as ISceneChildEntity).Shape.PathCurve = (byte)Extrusion.Curve1;
  7135. SetPrimitiveShapeParams((part as ISceneChildEntity), face, v, hollow, twist, holesize, topshear, profilecut, taper_b,
  7136. revolutions, radiusoffset, skew, 0);
  7137. }
  7138. else if (code == (int)ScriptBaseClass.PRIM_TYPE_TUBE)
  7139. {
  7140. if (remain < 11)
  7141. return;
  7142. face = rules.GetLSLIntegerItem(idx++); // holeshape
  7143. v = rules.GetVector3Item(idx++); //cut
  7144. hollow = (float)rules.GetLSLFloatItem(idx++);
  7145. twist = rules.GetVector3Item(idx++);
  7146. holesize = rules.GetVector3Item(idx++);
  7147. topshear = rules.GetVector3Item(idx++);
  7148. profilecut = rules.GetVector3Item(idx++);
  7149. taper_b = rules.GetVector3Item(idx++); // taper_a
  7150. revolutions = (float)rules.GetLSLFloatItem(idx++);
  7151. radiusoffset = (float)rules.GetLSLFloatItem(idx++);
  7152. skew = (float)rules.GetLSLFloatItem(idx++);
  7153. (part as ISceneChildEntity).Shape.PathCurve = (byte)Extrusion.Curve1;
  7154. SetPrimitiveShapeParams((part as ISceneChildEntity), face, v, hollow, twist, holesize, topshear, profilecut, taper_b,
  7155. revolutions, radiusoffset, skew, 1);
  7156. }
  7157. else if (code == (int)ScriptBaseClass.PRIM_TYPE_RING)
  7158. {
  7159. if (remain < 11)
  7160. return;
  7161. face = rules.GetLSLIntegerItem(idx++); // holeshape
  7162. v = rules.GetVector3Item(idx++); //cut
  7163. hollow = (float)rules.GetLSLFloatItem(idx++);
  7164. twist = rules.GetVector3Item(idx++);
  7165. holesize = rules.GetVector3Item(idx++);
  7166. topshear = rules.GetVector3Item(idx++);
  7167. profilecut = rules.GetVector3Item(idx++);
  7168. taper_b = rules.GetVector3Item(idx++); // taper_a
  7169. revolutions = (float)rules.GetLSLFloatItem(idx++);
  7170. radiusoffset = (float)rules.GetLSLFloatItem(idx++);
  7171. skew = (float)rules.GetLSLFloatItem(idx++);
  7172. (part as ISceneChildEntity).Shape.PathCurve = (byte)Extrusion.Curve1;
  7173. SetPrimitiveShapeParams((part as ISceneChildEntity), face, v, hollow, twist, holesize, topshear, profilecut, taper_b,
  7174. revolutions, radiusoffset, skew, 3);
  7175. }
  7176. else if (code == (int)ScriptBaseClass.PRIM_TYPE_SCULPT)
  7177. {
  7178. if (remain < 2)
  7179. return;
  7180. string map = rules.Data[idx++].ToString();
  7181. face = rules.GetLSLIntegerItem(idx++); // type
  7182. (part as ISceneChildEntity).Shape.PathCurve = (byte)Extrusion.Curve1;
  7183. SetPrimitiveShapeParams((part as ISceneChildEntity), map, face);
  7184. }
  7185. }
  7186. else if (code == (int)ScriptBaseClass.PRIM_TEXTURE)
  7187. {
  7188. if (remain < 5)
  7189. return;
  7190. if (part is ISceneChildEntity) { }
  7191. else
  7192. return;
  7193. face = rules.GetLSLIntegerItem(idx++);
  7194. string tex = rules.Data[idx++].ToString();
  7195. LSL_Vector repeats = rules.GetVector3Item(idx++);
  7196. LSL_Vector offsets = rules.GetVector3Item(idx++);
  7197. double rotation = rules.GetLSLFloatItem(idx++);
  7198. SetTexture((part as ISceneChildEntity), tex, face);
  7199. ScaleTexture((part as ISceneChildEntity), repeats.x, repeats.y, face);
  7200. OffsetTexture((part as ISceneChildEntity), offsets.x, offsets.y, face);
  7201. RotateTexture((part as ISceneChildEntity), rotation, face);
  7202. }
  7203. else if (code == (int)ScriptBaseClass.PRIM_COLOR)
  7204. {
  7205. if (remain < 3)
  7206. return;
  7207. if (part is ISceneChildEntity) { }
  7208. else
  7209. return;
  7210. face = rules.GetLSLIntegerItem(idx++);
  7211. LSL_Vector color = rules.GetVector3Item(idx++);
  7212. double alpha = rules.GetLSLFloatItem(idx++);
  7213. (part as ISceneChildEntity).SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face);
  7214. SetAlpha((part as ISceneChildEntity), alpha, face);
  7215. }
  7216. else if (code == (int)ScriptBaseClass.PRIM_FLEXIBLE)
  7217. {
  7218. if (remain < 7)
  7219. return;
  7220. if (!(part is ISceneChildEntity))
  7221. return;
  7222. bool flexi = rules.GetLSLIntegerItem(idx++);
  7223. int softness = rules.GetLSLIntegerItem(idx++);
  7224. float gravity = (float)rules.GetLSLFloatItem(idx++);
  7225. float friction = (float)rules.GetLSLFloatItem(idx++);
  7226. float wind = (float)rules.GetLSLFloatItem(idx++);
  7227. float tension = (float)rules.GetLSLFloatItem(idx++);
  7228. LSL_Vector force = rules.GetVector3Item(idx++);
  7229. SetFlexi((part as ISceneChildEntity), flexi, softness, gravity, friction, wind, tension, force);
  7230. }
  7231. else if (code == (int)ScriptBaseClass.PRIM_POINT_LIGHT)
  7232. {
  7233. if (remain < 5)
  7234. return;
  7235. if (!(part is ISceneChildEntity))
  7236. return;
  7237. bool light = rules.GetLSLIntegerItem(idx++);
  7238. LSL_Vector lightcolor = rules.GetVector3Item(idx++);
  7239. float intensity = (float)rules.GetLSLFloatItem(idx++);
  7240. float radius = (float)rules.GetLSLFloatItem(idx++);
  7241. float falloff = (float)rules.GetLSLFloatItem(idx++);
  7242. SetPointLight((part as ISceneChildEntity), light, lightcolor, intensity, radius, falloff);
  7243. }
  7244. else if (code == (int)ScriptBaseClass.PRIM_GLOW)
  7245. {
  7246. if (remain < 2)
  7247. return;
  7248. if (!(part is ISceneChildEntity))
  7249. return;
  7250. face = rules.GetLSLIntegerItem(idx++);
  7251. float glow = (float)rules.GetLSLFloatItem(idx++);
  7252. SetGlow((part as ISceneChildEntity), face, glow);
  7253. }
  7254. else if (code == (int)ScriptBaseClass.PRIM_BUMP_SHINY)
  7255. {
  7256. if (remain < 3)
  7257. return;
  7258. if (!(part is ISceneChildEntity))
  7259. return;
  7260. face = rules.GetLSLIntegerItem(idx++);
  7261. int shiny = rules.GetLSLIntegerItem(idx++);
  7262. Bumpiness bump = (Bumpiness)Convert.ToByte((int)rules.GetLSLIntegerItem(idx++));
  7263. SetShiny(part as ISceneChildEntity, face, shiny, bump);
  7264. }
  7265. else if (code == (int)ScriptBaseClass.PRIM_FULLBRIGHT)
  7266. {
  7267. if (remain < 2)
  7268. return;
  7269. if (!(part is ISceneChildEntity))
  7270. return;
  7271. face = rules.GetLSLIntegerItem(idx++);
  7272. bool st = rules.GetLSLIntegerItem(idx++);
  7273. SetFullBright(part as ISceneChildEntity, face, st);
  7274. }
  7275. else if (code == (int)ScriptBaseClass.PRIM_MATERIAL)
  7276. {
  7277. if (remain < 1)
  7278. return;
  7279. if (!(part is ISceneChildEntity))
  7280. return;
  7281. int mat = rules.GetLSLIntegerItem(idx++);
  7282. if (mat < 0 || mat > 7)
  7283. return;
  7284. (part as ISceneChildEntity).Material = Convert.ToByte(mat);
  7285. }
  7286. else if (code == (int)ScriptBaseClass.PRIM_PHANTOM)
  7287. {
  7288. if (remain < 1)
  7289. return;
  7290. if (!(part is ISceneChildEntity))
  7291. return;
  7292. string ph = rules.Data[idx++].ToString();
  7293. bool phantom = ph.Equals("1");
  7294. (part as ISceneChildEntity).ScriptSetPhantomStatus(phantom);
  7295. }
  7296. else if (code == (int)ScriptBaseClass.PRIM_PHYSICS)
  7297. {
  7298. if (remain < 1)
  7299. return;
  7300. if (!(part is ISceneChildEntity))
  7301. return;
  7302. string phy = rules.Data[idx++].ToString();
  7303. ((SceneObjectGroup)m_host.ParentEntity).ScriptSetPhysicsStatus(phy.Equals("1"));
  7304. }
  7305. else if (code == (int)ScriptBaseClass.PRIM_TEMP_ON_REZ)
  7306. {
  7307. if (remain < 1)
  7308. return;
  7309. if (!(part is ISceneChildEntity))
  7310. return;
  7311. string temp = rules.Data[idx++].ToString();
  7312. bool tempOnRez = temp.Equals("1");
  7313. (part as ISceneChildEntity).ScriptSetTemporaryStatus(tempOnRez);
  7314. }
  7315. else if (code == (int)ScriptBaseClass.PRIM_TEXGEN)
  7316. {
  7317. if (remain < 2)
  7318. return;
  7319. if (!(part is ISceneChildEntity))
  7320. return;
  7321. //face,type
  7322. face = rules.GetLSLIntegerItem(idx++);
  7323. int style = rules.GetLSLIntegerItem(idx++);
  7324. SetTexGen((part as ISceneChildEntity), face, style);
  7325. }
  7326. else if (code == (int)ScriptBaseClass.PRIM_TEXT)
  7327. {
  7328. if (remain < 3)
  7329. return;
  7330. if (!(part is ISceneChildEntity))
  7331. return;
  7332. string primText = rules.GetLSLStringItem(idx++);
  7333. LSL_Vector primTextColor = rules.GetVector3Item(idx++);
  7334. LSL_Float primTextAlpha = rules.GetLSLFloatItem(idx++);
  7335. Vector3 av3 = new Vector3(Util.Clip((float)primTextColor.x, 0.0f, 1.0f),
  7336. Util.Clip((float)primTextColor.y, 0.0f, 1.0f),
  7337. Util.Clip((float)primTextColor.z, 0.0f, 1.0f));
  7338. (part as ISceneChildEntity).SetText(primText, av3, Util.Clip((float)primTextAlpha, 0.0f, 1.0f));
  7339. }
  7340. else if (code == (int)ScriptBaseClass.PRIM_OMEGA)
  7341. {
  7342. if (remain < 3)
  7343. return;
  7344. LSL_Vector direction = rules.GetVector3Item(idx++);
  7345. LSL_Float spinrate = rules.GetLSLFloatItem(idx++);
  7346. LSL_Float gain = rules.GetLSLFloatItem(idx++);
  7347. if (part is ISceneChildEntity)
  7348. llTargetOmega(direction, spinrate, gain);
  7349. }
  7350. else if (code == (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE)
  7351. {
  7352. bool UsePhysics = ((m_host.Flags & PrimFlags.Physics) != 0);
  7353. bool IsTemporary = ((m_host.Flags & PrimFlags.TemporaryOnRez) != 0);
  7354. bool IsPhantom = ((m_host.Flags & PrimFlags.Phantom) != 0);
  7355. bool IsVolumeDetect = m_host.VolumeDetectActive;
  7356. ObjectFlagUpdatePacket.ExtraPhysicsBlock[] blocks = new ObjectFlagUpdatePacket.ExtraPhysicsBlock[1];
  7357. blocks[0] = new ObjectFlagUpdatePacket.ExtraPhysicsBlock
  7358. {
  7359. Density = m_host.Density,
  7360. Friction = m_host.Friction,
  7361. GravityMultiplier = m_host.GravityMultiplier
  7362. };
  7363. LSL_Integer shapeType = rules.GetLSLIntegerItem(idx++);
  7364. if (shapeType == ScriptBaseClass.PRIM_PHYSICS_SHAPE_PRIM)
  7365. blocks[0].PhysicsShapeType = (byte)shapeType.value;
  7366. else if (shapeType == ScriptBaseClass.PRIM_PHYSICS_SHAPE_NONE)
  7367. blocks[0].PhysicsShapeType = (byte)shapeType.value;
  7368. else //if(shapeType == ScriptBaseClass.PRIM_PHYSICS_SHAPE_CONVEX)
  7369. blocks[0].PhysicsShapeType = (byte)shapeType.value;
  7370. blocks[0].Restitution = m_host.Restitution;
  7371. if (part is ISceneChildEntity)
  7372. if ((part as ISceneChildEntity).UpdatePrimFlags(UsePhysics,
  7373. IsTemporary, IsPhantom, IsVolumeDetect, blocks))
  7374. (part as ISceneChildEntity).ParentEntity.RebuildPhysicalRepresentation(true);
  7375. }
  7376. else if (code == (int)ScriptBaseClass.PRIM_LINK_TARGET)
  7377. {
  7378. if (remain < 1)
  7379. return;
  7380. LSL_Integer nextLink = rules.GetLSLIntegerItem(idx++);
  7381. List<IEntity> entities = GetLinkPartsAndEntities(nextLink);
  7382. if (entities.Count > 0)
  7383. part = entities[0];
  7384. }
  7385. }
  7386. }
  7387. public LSL_String llStringToBase64(string str)
  7388. {
  7389. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  7390. try
  7391. {
  7392. byte[] encData_byte = new byte[str.Length];
  7393. encData_byte = Util.UTF8.GetBytes(str);
  7394. string encodedData = Convert.ToBase64String(encData_byte);
  7395. return encodedData;
  7396. }
  7397. catch (Exception e)
  7398. {
  7399. throw new Exception("Error in base64Encode" + e);
  7400. }
  7401. }
  7402. public LSL_String llBase64ToString(string str)
  7403. {
  7404. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  7405. try
  7406. {
  7407. return Util.Base64ToString(str);
  7408. }
  7409. catch (Exception e)
  7410. {
  7411. throw new Exception("Error in base64Decode" + e);
  7412. }
  7413. }
  7414. public LSL_String llXorBase64Strings(string str1, string str2)
  7415. {
  7416. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  7417. Deprecated("llXorBase64Strings");
  7418. ScriptSleep(300);
  7419. return String.Empty;
  7420. }
  7421. public void llRemoteDataSetRegion()
  7422. {
  7423. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  7424. Deprecated("llRemoteDataSetRegion");
  7425. }
  7426. public LSL_Float llLog10(double val)
  7427. {
  7428. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
  7429. return Math.Log10(val);
  7430. }
  7431. public LSL_Float llLog(double val)
  7432. {
  7433. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
  7434. return Math.Log(val);
  7435. }
  7436. public LSL_List llGetAnimationList(string id)
  7437. {
  7438. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_List();
  7439. LSL_List l = new LSL_List();
  7440. IScenePresence av = World.GetScenePresence((UUID)id);
  7441. if (av == null || av.IsChildAgent) // only if in the region
  7442. return l;
  7443. UUID[] anims = av.Animator.GetAnimationArray();
  7444. foreach (UUID foo in anims)
  7445. l.Add(new LSL_Key(foo.ToString()));
  7446. return l;
  7447. }
  7448. public DateTime llSetParcelMusicURL(string url)
  7449. {
  7450. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return DateTime.Now;
  7451. IParcelManagementModule parcelManagement = World.RequestModuleInterface<IParcelManagementModule>();
  7452. if (parcelManagement != null)
  7453. {
  7454. ILandObject land = parcelManagement.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y);
  7455. if (land == null)
  7456. return DateTime.Now;
  7457. if (!World.Permissions.CanEditParcel(m_host.OwnerID, land))
  7458. return DateTime.Now;
  7459. land.SetMusicUrl(url);
  7460. }
  7461. return PScriptSleep(2000);
  7462. }
  7463. public LSL_Vector llGetRootPosition()
  7464. {
  7465. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
  7466. return new LSL_Vector(m_host.ParentEntity.AbsolutePosition.X, m_host.ParentEntity.AbsolutePosition.Y,
  7467. m_host.ParentEntity.AbsolutePosition.Z);
  7468. }
  7469. /// <summary>
  7470. /// http://lslwiki.net/lslwiki/wakka.php?wakka=llGetRot
  7471. /// http://lslwiki.net/lslwiki/wakka.php?wakka=ChildRotation
  7472. /// Also tested in sl in regards to the behaviour in attachments/mouselook
  7473. /// In the root prim:-
  7474. /// Returns the object rotation if not attached
  7475. /// Returns the avatars rotation if attached
  7476. /// Returns the camera rotation if attached and the avatar is in mouselook
  7477. /// </summary>
  7478. public LSL_Rotation llGetRootRotation()
  7479. {
  7480. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Rotation();
  7481. Quaternion q;
  7482. if (m_host.ParentEntity.RootChild.AttachmentPoint != 0)
  7483. {
  7484. IScenePresence avatar = World.GetScenePresence(m_host.AttachedAvatar);
  7485. if (avatar != null)
  7486. q = (avatar.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0
  7487. ? avatar.CameraRotation
  7488. : avatar.Rotation;
  7489. else
  7490. q = m_host.ParentEntity.GroupRotation; // Likely never get here but just in case
  7491. }
  7492. else
  7493. q = m_host.ParentEntity.GroupRotation; // just the group rotation
  7494. return new LSL_Rotation(q.X, q.Y, q.Z, q.W);
  7495. }
  7496. public LSL_String llGetObjectDesc()
  7497. {
  7498. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  7499. return m_host.Description ?? String.Empty;
  7500. }
  7501. public void llSetObjectDesc(string desc)
  7502. {
  7503. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  7504. m_host.Description = desc ?? String.Empty;
  7505. }
  7506. public LSL_String llGetCreator()
  7507. {
  7508. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  7509. return m_host.CreatorID.ToString();
  7510. }
  7511. public LSL_String llGetTimestamp()
  7512. {
  7513. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  7514. return DateTime.Now.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ");
  7515. }
  7516. public LSL_Integer llGetNumberOfPrims()
  7517. {
  7518. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  7519. int avatarCount = m_host.ParentEntity.SitTargetAvatar.Count;
  7520. return m_host.ParentEntity.PrimCount + avatarCount;
  7521. }
  7522. /// <summary>
  7523. /// A partial implementation.
  7524. /// http://lslwiki.net/lslwiki/wakka.php?wakka=llGetBoundingBox
  7525. /// So far only valid for standing/flying/ground sitting avatars and single prim objects.
  7526. /// If the object has multiple prims and/or a sitting avatar then the bounding
  7527. /// box is for the root prim only.
  7528. /// </summary>
  7529. public LSL_List llGetBoundingBox(string obj)
  7530. {
  7531. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_List();
  7532. UUID objID = UUID.Zero;
  7533. LSL_List result = new LSL_List();
  7534. if (!UUID.TryParse(obj, out objID))
  7535. {
  7536. result.Add(new LSL_Vector());
  7537. result.Add(new LSL_Vector());
  7538. return result;
  7539. }
  7540. IScenePresence presence = World.GetScenePresence(objID);
  7541. if (presence != null)
  7542. {
  7543. if (presence.ParentID == UUID.Zero) // not sat on an object
  7544. {
  7545. LSL_Vector lower = new LSL_Vector();
  7546. LSL_Vector upper = new LSL_Vector();
  7547. if (presence.Animator.Animations.ImplicitDefaultAnimation.AnimID
  7548. == AnimationSet.Animations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
  7549. {
  7550. // This is for ground sitting avatars
  7551. IAvatarAppearanceModule appearance = presence.RequestModuleInterface<IAvatarAppearanceModule>();
  7552. if (appearance != null)
  7553. {
  7554. float height = appearance.Appearance.AvatarHeight / 2.66666667f;
  7555. lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
  7556. upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
  7557. }
  7558. }
  7559. else
  7560. {
  7561. // This is for standing/flying avatars
  7562. IAvatarAppearanceModule appearance = presence.RequestModuleInterface<IAvatarAppearanceModule>();
  7563. if (appearance != null)
  7564. {
  7565. float height = appearance.Appearance.AvatarHeight / 2.0f;
  7566. lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f);
  7567. upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
  7568. }
  7569. }
  7570. result.Add(lower);
  7571. result.Add(upper);
  7572. return result;
  7573. }
  7574. // sitting on an object so we need the bounding box of that
  7575. // which should include the avatar so set the UUID to the
  7576. // UUID of the object the avatar is sat on and allow it to fall through
  7577. // to processing an object
  7578. ISceneChildEntity p = World.GetSceneObjectPart(presence.ParentID);
  7579. objID = p.UUID;
  7580. }
  7581. ISceneChildEntity part = World.GetSceneObjectPart(objID);
  7582. // Currently only works for single prims without a sitting avatar
  7583. if (part != null)
  7584. {
  7585. Vector3 halfSize = part.Scale * 0.5f;
  7586. LSL_Vector lower = new LSL_Vector(halfSize.X * -1.0f, halfSize.Y * -1.0f, halfSize.Z * -1.0f);
  7587. LSL_Vector upper = new LSL_Vector(halfSize.X, halfSize.Y, halfSize.Z);
  7588. result.Add(lower);
  7589. result.Add(upper);
  7590. return result;
  7591. }
  7592. // Not found so return empty values
  7593. result.Add(new LSL_Vector());
  7594. result.Add(new LSL_Vector());
  7595. return result;
  7596. }
  7597. public LSL_Vector llGetGeometricCenter()
  7598. {
  7599. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
  7600. Vector3 MinPos = new Vector3(100000, 100000, 100000);
  7601. Vector3 MaxPos = new Vector3(-100000, -100000, -100000);
  7602. foreach (ISceneChildEntity child in m_host.ParentEntity.ChildrenEntities())
  7603. {
  7604. Vector3 tmp = child.AbsolutePosition;
  7605. if (tmp.X < MinPos.X)
  7606. MinPos.X = tmp.X;
  7607. if (tmp.Y < MinPos.Y)
  7608. MinPos.Y = tmp.Y;
  7609. if (tmp.Z < MinPos.Z)
  7610. MinPos.Z = tmp.Z;
  7611. if (tmp.X > MaxPos.X)
  7612. MaxPos.X = tmp.X;
  7613. if (tmp.Y > MaxPos.Y)
  7614. MaxPos.Y = tmp.Y;
  7615. if (tmp.Z > MaxPos.Z)
  7616. MaxPos.Z = tmp.Z;
  7617. }
  7618. Vector3 GroupAvg = ((MaxPos + MinPos) / 2);
  7619. return new LSL_Vector(GroupAvg.X, GroupAvg.Y, GroupAvg.Z);
  7620. //Just plain wrong!
  7621. //return new LSL_Vector(m_host.GetGeometricCenter().X, m_host.GetGeometricCenter().Y, m_host.GetGeometricCenter().Z);
  7622. }
  7623. public LSL_List llGetPrimitiveParams(LSL_List rules)
  7624. {
  7625. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_List();
  7626. return GetLinkPrimitiveParams(m_host, rules);
  7627. }
  7628. public LSL_List llGetLinkPrimitiveParams(int linknumber, LSL_List rules)
  7629. {
  7630. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_List();
  7631. List<ISceneChildEntity> parts = GetLinkParts(linknumber);
  7632. LSL_List res = new LSL_List();
  7633. #if (!ISWIN)
  7634. LSL_List result = res;
  7635. foreach (ISceneChildEntity part in parts)
  7636. {
  7637. LSL_List list = GetLinkPrimitiveParams(part, rules);
  7638. result = result + list;
  7639. }
  7640. return result;
  7641. #else
  7642. return parts.Select(part => GetLinkPrimitiveParams(part, rules)).Aggregate(res, (current, partRes) => current + partRes);
  7643. #endif
  7644. }
  7645. public LSL_List GetLinkPrimitiveParams(ISceneChildEntity part, LSL_List rules)
  7646. {
  7647. LSL_List res = new LSL_List();
  7648. int idx = 0;
  7649. while (idx < rules.Length)
  7650. {
  7651. int code = rules.GetLSLIntegerItem(idx++);
  7652. int remain = rules.Length - idx;
  7653. Primitive.TextureEntry tex = part.Shape.Textures;
  7654. int face = 0;
  7655. if (code == (int)ScriptBaseClass.PRIM_NAME)
  7656. {
  7657. res.Add(new LSL_String(part.Name));
  7658. }
  7659. else if (code == (int)ScriptBaseClass.PRIM_DESC)
  7660. {
  7661. res.Add(new LSL_String(part.Description));
  7662. }
  7663. else if (code == (int)ScriptBaseClass.PRIM_MATERIAL)
  7664. {
  7665. res.Add(new LSL_Integer(part.Material));
  7666. }
  7667. else if (code == (int)ScriptBaseClass.PRIM_PHYSICS)
  7668. {
  7669. res.Add((part.GetEffectiveObjectFlags() & (uint)PrimFlags.Physics) != 0
  7670. ? new LSL_Integer(1)
  7671. : new LSL_Integer(0));
  7672. }
  7673. else if (code == (int)ScriptBaseClass.PRIM_TEMP_ON_REZ)
  7674. {
  7675. res.Add((part.GetEffectiveObjectFlags() & (uint)PrimFlags.TemporaryOnRez) != 0
  7676. ? new LSL_Integer(1)
  7677. : new LSL_Integer(0));
  7678. }
  7679. else if (code == (int)ScriptBaseClass.PRIM_PHANTOM)
  7680. {
  7681. res.Add((part.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) != 0
  7682. ? new LSL_Integer(1)
  7683. : new LSL_Integer(0));
  7684. }
  7685. else if (code == (int)ScriptBaseClass.PRIM_POSITION)
  7686. {
  7687. Vector3 tmp = part.AbsolutePosition;
  7688. LSL_Vector v = new LSL_Vector(tmp.X,
  7689. tmp.Y,
  7690. tmp.Z);
  7691. // For some reason, the part.AbsolutePosition.* values do not change if the
  7692. // linkset is rotated; they always reflect the child prim's world position
  7693. // as though the linkset is unrotated. This is incompatible behavior with SL's
  7694. // implementation, so will break scripts imported from there (not to mention it
  7695. // makes it more difficult to determine a child prim's actual inworld position).
  7696. if (part.ParentID != 0)
  7697. {
  7698. LSL_Rotation rtmp = llGetRootRotation();
  7699. LSL_Vector rpos = llGetRootPosition();
  7700. v = ((v - rpos) * rtmp) + rpos;
  7701. }
  7702. res.Add(v);
  7703. }
  7704. else if (code == (int)ScriptBaseClass.PRIM_POS_LOCAL)
  7705. {
  7706. res.Add(GetLocalPos(part));
  7707. }
  7708. else if (code == (int)ScriptBaseClass.PRIM_SIZE)
  7709. {
  7710. Vector3 tmp = part.Scale;
  7711. res.Add(new LSL_Vector(tmp.X,
  7712. tmp.Y,
  7713. tmp.Z));
  7714. }
  7715. else if (code == (int)ScriptBaseClass.PRIM_ROTATION)
  7716. {
  7717. res.Add(GetPartRot(part));
  7718. }
  7719. else if (code == (int)ScriptBaseClass.PRIM_TYPE)
  7720. {
  7721. // implementing box
  7722. PrimitiveBaseShape Shape = part.Shape;
  7723. int primType = (int)part.GetPrimType();
  7724. res.Add(new LSL_Integer(primType));
  7725. double topshearx = (sbyte)Shape.PathShearX / 100.0; // Fix negative values for PathShearX
  7726. double topsheary = (sbyte)Shape.PathShearY / 100.0; // and PathShearY.
  7727. if (primType == ScriptBaseClass.PRIM_TYPE_BOX ||
  7728. primType == ScriptBaseClass.PRIM_TYPE_CYLINDER ||
  7729. primType == ScriptBaseClass.PRIM_TYPE_PRISM)
  7730. {
  7731. res.Add(new LSL_Integer(Shape.ProfileCurve));
  7732. res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0));
  7733. res.Add(new LSL_Float(Shape.ProfileHollow / 50000.0));
  7734. res.Add(new LSL_Vector(Shape.PathTwistBegin / 100.0, Shape.PathTwist / 100.0, 0));
  7735. res.Add(new LSL_Vector(1 - (Shape.PathScaleX / 100.0 - 1), 1 - (Shape.PathScaleY / 100.0 - 1), 0));
  7736. res.Add(new LSL_Vector(topshearx, topsheary, 0));
  7737. }
  7738. if (primType == ScriptBaseClass.PRIM_TYPE_SPHERE)
  7739. {
  7740. res.Add(new LSL_Integer(Shape.ProfileCurve));
  7741. res.Add(new LSL_Vector(Shape.PathBegin / 50000.0, 1 - Shape.PathEnd / 50000.0, 0));
  7742. res.Add(new LSL_Float(Shape.ProfileHollow / 50000.0));
  7743. res.Add(new LSL_Vector(Shape.PathTwistBegin / 100.0, Shape.PathTwist / 100.0, 0));
  7744. res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0));
  7745. }
  7746. if (primType == ScriptBaseClass.PRIM_TYPE_SCULPT)
  7747. {
  7748. res.Add(Shape.SculptTexture.ToString());
  7749. res.Add(new LSL_Integer(Shape.SculptType));
  7750. }
  7751. if (primType == ScriptBaseClass.PRIM_TYPE_RING ||
  7752. primType == ScriptBaseClass.PRIM_TYPE_TUBE ||
  7753. primType == ScriptBaseClass.PRIM_TYPE_TORUS)
  7754. {
  7755. // holeshape
  7756. res.Add(new LSL_Integer(Shape.ProfileCurve));
  7757. // cut
  7758. res.Add(new LSL_Vector(Shape.PathBegin / 50000.0, 1 - Shape.PathEnd / 50000.0, 0));
  7759. // hollow
  7760. res.Add(new LSL_Float(Shape.ProfileHollow / 50000.0));
  7761. // twist
  7762. res.Add(new LSL_Vector(Shape.PathTwistBegin / 100.0, Shape.PathTwist / 100.0, 0));
  7763. // vector holesize
  7764. res.Add(new LSL_Vector(1 - (Shape.PathScaleX / 100.0 - 1), 1 - (Shape.PathScaleY / 100.0 - 1), 0));
  7765. // vector topshear
  7766. res.Add(new LSL_Vector(topshearx, topsheary, 0));
  7767. // vector profilecut
  7768. res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0));
  7769. // vector tapera
  7770. res.Add(new LSL_Vector(Shape.PathTaperX / 100.0, Shape.PathTaperY / 100.0, 0));
  7771. // float revolutions
  7772. res.Add(new LSL_Float(Math.Round(Shape.PathRevolutions * 0.015d, 2, MidpointRounding.AwayFromZero)) + 1.0d);
  7773. // Slightly inaccurate, because an unsigned byte is being used to represent
  7774. // the entire range of floating-point values from 1.0 through 4.0 (which is how
  7775. // SL does it).
  7776. //
  7777. // Using these formulas to store and retrieve PathRevolutions, it is not
  7778. // possible to use all values between 1.00 and 4.00. For instance, you can't
  7779. // represent 1.10. You can represent 1.09 and 1.11, but not 1.10. So, if you
  7780. // use llSetPrimitiveParams to set revolutions to 1.10 and then retreive them
  7781. // with llGetPrimitiveParams, you'll retrieve 1.09. You can also see a similar
  7782. // behavior in the viewer as you cannot set 1.10. The viewer jumps to 1.11.
  7783. // In SL, llSetPrimitveParams and llGetPrimitiveParams can set and get a value
  7784. // such as 1.10. So, SL must store and retreive the actual user input rather
  7785. // than only storing the encoded value.
  7786. // float radiusoffset
  7787. res.Add(new LSL_Float(Shape.PathRadiusOffset / 100.0));
  7788. // float skew
  7789. res.Add(new LSL_Float(Shape.PathSkew / 100.0));
  7790. }
  7791. }
  7792. else if (code == (int)ScriptBaseClass.PRIM_TEXTURE)
  7793. {
  7794. if (remain < 1)
  7795. return res;
  7796. face = rules.GetLSLIntegerItem(idx++);
  7797. if (face == ScriptBaseClass.ALL_SIDES)
  7798. {
  7799. for (face = 0; face < GetNumberOfSides(part); face++)
  7800. {
  7801. Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
  7802. res.Add(new LSL_String(texface.TextureID.ToString()));
  7803. res.Add(new LSL_Vector(texface.RepeatU,
  7804. texface.RepeatV,
  7805. 0));
  7806. res.Add(new LSL_Vector(texface.OffsetU,
  7807. texface.OffsetV,
  7808. 0));
  7809. res.Add(new LSL_Float(texface.Rotation));
  7810. }
  7811. }
  7812. else
  7813. {
  7814. if (face >= 0 && face < GetNumberOfSides(part))
  7815. {
  7816. Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
  7817. res.Add(new LSL_String(texface.TextureID.ToString()));
  7818. res.Add(new LSL_Vector(texface.RepeatU,
  7819. texface.RepeatV,
  7820. 0));
  7821. res.Add(new LSL_Vector(texface.OffsetU,
  7822. texface.OffsetV,
  7823. 0));
  7824. res.Add(new LSL_Float(texface.Rotation));
  7825. }
  7826. }
  7827. }
  7828. else if (code == (int)ScriptBaseClass.PRIM_COLOR)
  7829. {
  7830. if (remain < 1)
  7831. return res;
  7832. face = rules.GetLSLIntegerItem(idx++);
  7833. tex = part.Shape.Textures;
  7834. Color4 texcolor;
  7835. if (face == ScriptBaseClass.ALL_SIDES)
  7836. {
  7837. for (face = 0; face < GetNumberOfSides(part); face++)
  7838. {
  7839. texcolor = tex.GetFace((uint)face).RGBA;
  7840. res.Add(new LSL_Vector(texcolor.R,
  7841. texcolor.G,
  7842. texcolor.B));
  7843. res.Add(new LSL_Float(texcolor.A));
  7844. }
  7845. }
  7846. else
  7847. {
  7848. texcolor = tex.GetFace((uint)face).RGBA;
  7849. res.Add(new LSL_Vector(texcolor.R,
  7850. texcolor.G,
  7851. texcolor.B));
  7852. res.Add(new LSL_Float(texcolor.A));
  7853. }
  7854. }
  7855. else if (code == (int)ScriptBaseClass.PRIM_BUMP_SHINY)
  7856. {
  7857. if (remain < 1)
  7858. return res;
  7859. face = rules.GetLSLIntegerItem(idx++);
  7860. if (face == ScriptBaseClass.ALL_SIDES)
  7861. {
  7862. for (face = 0; face < GetNumberOfSides(part); face++)
  7863. {
  7864. Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
  7865. // Convert Shininess to PRIM_SHINY_*
  7866. res.Add(new LSL_Integer((uint)texface.Shiny >> 6));
  7867. // PRIM_BUMP_*
  7868. res.Add(new LSL_Integer((int)texface.Bump));
  7869. }
  7870. }
  7871. else
  7872. {
  7873. if (face >= 0 && face < GetNumberOfSides(part))
  7874. {
  7875. Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
  7876. // Convert Shininess to PRIM_SHINY_*
  7877. res.Add(new LSL_Integer((uint)texface.Shiny >> 6));
  7878. // PRIM_BUMP_*
  7879. res.Add(new LSL_Integer((int)texface.Bump));
  7880. }
  7881. }
  7882. }
  7883. else if (code == (int)ScriptBaseClass.PRIM_FULLBRIGHT)
  7884. {
  7885. if (remain < 1)
  7886. return res;
  7887. face = rules.GetLSLIntegerItem(idx++);
  7888. tex = part.Shape.Textures;
  7889. if (face == ScriptBaseClass.ALL_SIDES)
  7890. {
  7891. for (face = 0; face < GetNumberOfSides(part); face++)
  7892. {
  7893. Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
  7894. res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0));
  7895. }
  7896. }
  7897. else
  7898. {
  7899. if (face >= 0 && face < GetNumberOfSides(part))
  7900. {
  7901. Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
  7902. res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0));
  7903. }
  7904. }
  7905. }
  7906. else if (code == (int)ScriptBaseClass.PRIM_FLEXIBLE)
  7907. {
  7908. PrimitiveBaseShape shape = part.Shape;
  7909. res.Add(shape.FlexiEntry ? new LSL_Integer(1) : new LSL_Integer(0));
  7910. res.Add(new LSL_Integer(shape.FlexiSoftness));// softness
  7911. res.Add(new LSL_Float(shape.FlexiGravity)); // gravity
  7912. res.Add(new LSL_Float(shape.FlexiDrag)); // friction
  7913. res.Add(new LSL_Float(shape.FlexiWind)); // wind
  7914. res.Add(new LSL_Float(shape.FlexiTension)); // tension
  7915. res.Add(new LSL_Vector(shape.FlexiForceX, // force
  7916. shape.FlexiForceY,
  7917. shape.FlexiForceZ));
  7918. }
  7919. else if (code == (int)ScriptBaseClass.PRIM_TEXGEN)
  7920. {
  7921. if (remain < 1)
  7922. return res;
  7923. face = rules.GetLSLIntegerItem(idx++);
  7924. if (face == ScriptBaseClass.ALL_SIDES)
  7925. {
  7926. for (face = 0; face < GetNumberOfSides(part); face++)
  7927. {
  7928. MappingType texgen = tex.GetFace((uint)face).TexMapType;
  7929. // Convert MappingType to PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR etc.
  7930. res.Add(new LSL_Integer((uint)texgen >> 1));
  7931. }
  7932. }
  7933. else
  7934. {
  7935. if (face >= 0 && face < GetNumberOfSides(part))
  7936. {
  7937. MappingType texgen = tex.GetFace((uint)face).TexMapType;
  7938. res.Add(new LSL_Integer((uint)texgen >> 1));
  7939. }
  7940. }
  7941. }
  7942. else if (code == (int)ScriptBaseClass.PRIM_POINT_LIGHT)
  7943. {
  7944. PrimitiveBaseShape shape = part.Shape;
  7945. res.Add(shape.LightEntry ? new LSL_Integer(1) : new LSL_Integer(0));
  7946. res.Add(new LSL_Vector(shape.LightColorR, // color
  7947. shape.LightColorG,
  7948. shape.LightColorB));
  7949. res.Add(new LSL_Float(shape.LightIntensity)); // intensity
  7950. res.Add(new LSL_Float(shape.LightRadius)); // radius
  7951. res.Add(new LSL_Float(shape.LightFalloff)); // falloff
  7952. }
  7953. else if (code == (int)ScriptBaseClass.PRIM_GLOW)
  7954. {
  7955. if (remain < 1)
  7956. return res;
  7957. face = rules.GetLSLIntegerItem(idx++);
  7958. if (face == ScriptBaseClass.ALL_SIDES)
  7959. {
  7960. for (face = 0; face < GetNumberOfSides(part); face++)
  7961. {
  7962. Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
  7963. res.Add(new LSL_Float(texface.Glow));
  7964. }
  7965. }
  7966. else
  7967. {
  7968. if (face >= 0 && face < GetNumberOfSides(part))
  7969. {
  7970. Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
  7971. res.Add(new LSL_Float(texface.Glow));
  7972. }
  7973. }
  7974. }
  7975. else if (code == (int)ScriptBaseClass.PRIM_TEXT)
  7976. {
  7977. Color4 textColor = part.GetTextColor();
  7978. res.Add(new LSL_String(part.Text));
  7979. res.Add(new LSL_Vector(textColor.R,
  7980. textColor.G,
  7981. textColor.B));
  7982. res.Add(new LSL_Float(textColor.A));
  7983. }
  7984. else if (code == (int)ScriptBaseClass.PRIM_ROT_LOCAL)
  7985. {
  7986. Quaternion rtmp = part.RotationOffset;
  7987. res.Add(new LSL_Rotation(rtmp.X, rtmp.Y, rtmp.Z, rtmp.W));
  7988. }
  7989. else if (code == (int)ScriptBaseClass.PRIM_OMEGA)
  7990. {
  7991. Vector3 axis = part.OmegaAxis;
  7992. LSL_Float spinRate = part.OmegaSpinRate;
  7993. LSL_Float gain = part.OmegaGain;
  7994. res.Add(axis);
  7995. res.Add(spinRate);
  7996. res.Add(gain);
  7997. }
  7998. else if (code == (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE)
  7999. {
  8000. res.Add(new LSL_Integer(part.PhysicsType));
  8001. }
  8002. else if (code == (int)ScriptBaseClass.PRIM_LINK_TARGET)
  8003. {
  8004. if (remain < 1)
  8005. continue;
  8006. LSL_Integer nextLink = rules.GetLSLIntegerItem(idx++);
  8007. List<ISceneChildEntity> entities = GetLinkParts(nextLink);
  8008. if (entities.Count > 0)
  8009. part = entities[0];
  8010. }
  8011. }
  8012. return res;
  8013. }
  8014. public LSL_List llGetPhysicsMaterial()
  8015. {
  8016. return new LSL_List(m_host.GravityMultiplier, m_host.Restitution, m_host.Friction, m_host.Density);
  8017. }
  8018. public void llSetPhysicsMaterial(LSL_Integer bits, LSL_Float density, LSL_Float friction, LSL_Float restitution,
  8019. LSL_Float gravityMultiplier)
  8020. {
  8021. ObjectFlagUpdatePacket.ExtraPhysicsBlock[] blocks = new ObjectFlagUpdatePacket.ExtraPhysicsBlock[1];
  8022. blocks[0] = new ObjectFlagUpdatePacket.ExtraPhysicsBlock();
  8023. if ((bits & ScriptBaseClass.DENSITY) == ScriptBaseClass.DENSITY)
  8024. m_host.Density = (float)density;
  8025. else
  8026. blocks[0].Density = m_host.Density;
  8027. if ((bits & ScriptBaseClass.FRICTION) == ScriptBaseClass.FRICTION)
  8028. m_host.Friction = (float)friction;
  8029. else
  8030. blocks[0].Friction = m_host.Friction;
  8031. if ((bits & ScriptBaseClass.RESTITUTION) == ScriptBaseClass.RESTITUTION)
  8032. m_host.Restitution = (float)restitution;
  8033. else
  8034. blocks[0].Restitution = m_host.Restitution;
  8035. if ((bits & ScriptBaseClass.GRAVITY_MULTIPLIER) == ScriptBaseClass.GRAVITY_MULTIPLIER)
  8036. m_host.GravityMultiplier = (float)gravityMultiplier;
  8037. else
  8038. blocks[0].GravityMultiplier = m_host.GravityMultiplier;
  8039. bool UsePhysics = ((m_host.Flags & PrimFlags.Physics) != 0);
  8040. bool IsTemporary = ((m_host.Flags & PrimFlags.TemporaryOnRez) != 0);
  8041. bool IsPhantom = ((m_host.Flags & PrimFlags.Phantom) != 0);
  8042. bool IsVolumeDetect = m_host.VolumeDetectActive;
  8043. blocks[0].PhysicsShapeType = m_host.PhysicsType;
  8044. if (m_host.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect, blocks))
  8045. m_host.ParentEntity.RebuildPhysicalRepresentation(true);
  8046. }
  8047. // <remarks>
  8048. // <para>
  8049. // The .NET definition of base 64 is:
  8050. // <list>
  8051. // <item>
  8052. // Significant: A-Z a-z 0-9 + -
  8053. // </item>
  8054. // <item>
  8055. // Whitespace: \t \n \r ' '
  8056. // </item>
  8057. // <item>
  8058. // Valueless: =
  8059. // </item>
  8060. // <item>
  8061. // End-of-string: \0 or '=='
  8062. // </item>
  8063. // </list>
  8064. // </para>
  8065. // <para>
  8066. // Each point in a base-64 string represents
  8067. // a 6 bit value. A 32-bit integer can be
  8068. // represented using 6 characters (with some
  8069. // redundancy).
  8070. // </para>
  8071. // <para>
  8072. // LSL requires a base64 string to be 8
  8073. // characters in length. LSL also uses '/'
  8074. // rather than '-' (MIME compliant).
  8075. // </para>
  8076. // <para>
  8077. // RFC 1341 used as a reference (as specified
  8078. // by the SecondLife Wiki).
  8079. // </para>
  8080. // <para>
  8081. // SL do not record any kind of exception for
  8082. // these functions, so the string to integer
  8083. // conversion returns '0' if an invalid
  8084. // character is encountered during conversion.
  8085. // </para>
  8086. // <para>
  8087. // References
  8088. // <list>
  8089. // <item>
  8090. // http://lslwiki.net/lslwiki/wakka.php?wakka=Base64
  8091. // </item>
  8092. // <item>
  8093. // </item>
  8094. // </list>
  8095. // </para>
  8096. // </remarks>
  8097. // <summary>
  8098. // Table for converting 6-bit integers into
  8099. // base-64 characters
  8100. // </summary>
  8101. protected static readonly char[] i2ctable =
  8102. {
  8103. 'A','B','C','D','E','F','G','H',
  8104. 'I','J','K','L','M','N','O','P',
  8105. 'Q','R','S','T','U','V','W','X',
  8106. 'Y','Z',
  8107. 'a','b','c','d','e','f','g','h',
  8108. 'i','j','k','l','m','n','o','p',
  8109. 'q','r','s','t','u','v','w','x',
  8110. 'y','z',
  8111. '0','1','2','3','4','5','6','7',
  8112. '8','9',
  8113. '+','/'
  8114. };
  8115. // <summary>
  8116. // Table for converting base-64 characters
  8117. // into 6-bit integers.
  8118. // </summary>
  8119. protected static readonly int[] c2itable =
  8120. {
  8121. -1,-1,-1,-1,-1,-1,-1,-1, // 0x
  8122. -1,-1,-1,-1,-1,-1,-1,-1,
  8123. -1,-1,-1,-1,-1,-1,-1,-1, // 1x
  8124. -1,-1,-1,-1,-1,-1,-1,-1,
  8125. -1,-1,-1,-1,-1,-1,-1,-1, // 2x
  8126. -1,-1,-1,63,-1,-1,-1,64,
  8127. 53,54,55,56,57,58,59,60, // 3x
  8128. 61,62,-1,-1,-1,0,-1,-1,
  8129. -1,1,2,3,4,5,6,7, // 4x
  8130. 8,9,10,11,12,13,14,15,
  8131. 16,17,18,19,20,21,22,23, // 5x
  8132. 24,25,26,-1,-1,-1,-1,-1,
  8133. -1,27,28,29,30,31,32,33, // 6x
  8134. 34,35,36,37,38,39,40,41,
  8135. 42,43,44,45,46,47,48,49, // 7x
  8136. 50,51,52,-1,-1,-1,-1,-1,
  8137. -1,-1,-1,-1,-1,-1,-1,-1, // 8x
  8138. -1,-1,-1,-1,-1,-1,-1,-1,
  8139. -1,-1,-1,-1,-1,-1,-1,-1, // 9x
  8140. -1,-1,-1,-1,-1,-1,-1,-1,
  8141. -1,-1,-1,-1,-1,-1,-1,-1, // Ax
  8142. -1,-1,-1,-1,-1,-1,-1,-1,
  8143. -1,-1,-1,-1,-1,-1,-1,-1, // Bx
  8144. -1,-1,-1,-1,-1,-1,-1,-1,
  8145. -1,-1,-1,-1,-1,-1,-1,-1, // Cx
  8146. -1,-1,-1,-1,-1,-1,-1,-1,
  8147. -1,-1,-1,-1,-1,-1,-1,-1, // Dx
  8148. -1,-1,-1,-1,-1,-1,-1,-1,
  8149. -1,-1,-1,-1,-1,-1,-1,-1, // Ex
  8150. -1,-1,-1,-1,-1,-1,-1,-1,
  8151. -1,-1,-1,-1,-1,-1,-1,-1, // Fx
  8152. -1,-1,-1,-1,-1,-1,-1,-1
  8153. };
  8154. // <summary>
  8155. // Converts a 32-bit integer into a Base64
  8156. // character string. Base64 character strings
  8157. // are always 8 characters long. All iinteger
  8158. // values are acceptable.
  8159. // </summary>
  8160. // <param name="number">
  8161. // 32-bit integer to be converted.
  8162. // </param>
  8163. // <returns>
  8164. // 8 character string. The 1st six characters
  8165. // contain the encoded number, the last two
  8166. // characters are padded with "=".
  8167. // </returns>
  8168. public LSL_String llIntegerToBase64(int number)
  8169. {
  8170. // uninitialized string
  8171. char[] imdt = new char[8];
  8172. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  8173. // Manually unroll the loop
  8174. imdt[7] = '=';
  8175. imdt[6] = '=';
  8176. imdt[5] = i2ctable[number << 4 & 0x3F];
  8177. imdt[4] = i2ctable[number >> 2 & 0x3F];
  8178. imdt[3] = i2ctable[number >> 8 & 0x3F];
  8179. imdt[2] = i2ctable[number >> 14 & 0x3F];
  8180. imdt[1] = i2ctable[number >> 20 & 0x3F];
  8181. imdt[0] = i2ctable[number >> 26 & 0x3F];
  8182. return new string(imdt);
  8183. }
  8184. // <summary>
  8185. // Converts an eight character base-64 string
  8186. // into a 32-bit integer.
  8187. // </summary>
  8188. // <param name="str">
  8189. // 8 characters string to be converted. Other
  8190. // length strings return zero.
  8191. // </param>
  8192. // <returns>
  8193. // Returns an integer representing the
  8194. // encoded value providedint he 1st 6
  8195. // characters of the string.
  8196. // </returns>
  8197. // <remarks>
  8198. // This is coded to behave like LSL's
  8199. // implementation (I think), based upon the
  8200. // information available at the Wiki.
  8201. // If more than 8 characters are supplied,
  8202. // zero is returned.
  8203. // If a NULL string is supplied, zero will
  8204. // be returned.
  8205. // If fewer than 6 characters are supplied, then
  8206. // the answer will reflect a partial
  8207. // accumulation.
  8208. // <para>
  8209. // The 6-bit segments are
  8210. // extracted left-to-right in big-endian mode,
  8211. // which means that segment 6 only contains the
  8212. // two low-order bits of the 32 bit integer as
  8213. // its high order 2 bits. A short string therefore
  8214. // means loss of low-order information. E.g.
  8215. //
  8216. // |<---------------------- 32-bit integer ----------------------->|<-Pad->|
  8217. // |<--Byte 0----->|<--Byte 1----->|<--Byte 2----->|<--Byte 3----->|<-Pad->|
  8218. // |3|3|2|2|2|2|2|2|2|2|2|2|1|1|1|1|1|1|1|1|1|1| | | | | | | | | | |P|P|P|P|
  8219. // |1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|P|P|P|P|
  8220. // | str[0] | str[1] | str[2] | str[3] | str[4] | str[6] |
  8221. //
  8222. // </para>
  8223. // </remarks>
  8224. public LSL_Integer llBase64ToInteger(string str)
  8225. {
  8226. int number = 0;
  8227. int digit;
  8228. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  8229. // Require a well-fromed base64 string
  8230. if (str.Length > 8)
  8231. return 0;
  8232. // The loop is unrolled in the interests
  8233. // of performance and simple necessity.
  8234. //
  8235. // MUST find 6 digits to be well formed
  8236. // -1 == invalid
  8237. // 0 == padding
  8238. if ((digit = c2itable[str[0]]) <= 0)
  8239. {
  8240. return digit < 0 ? 0 : number;
  8241. }
  8242. number += --digit << 26;
  8243. if ((digit = c2itable[str[1]]) <= 0)
  8244. {
  8245. return digit < 0 ? 0 : number;
  8246. }
  8247. number += --digit << 20;
  8248. if ((digit = c2itable[str[2]]) <= 0)
  8249. {
  8250. return digit < 0 ? 0 : number;
  8251. }
  8252. number += --digit << 14;
  8253. if ((digit = c2itable[str[3]]) <= 0)
  8254. {
  8255. return digit < 0 ? 0 : number;
  8256. }
  8257. number += --digit << 8;
  8258. if ((digit = c2itable[str[4]]) <= 0)
  8259. {
  8260. return digit < 0 ? 0 : number;
  8261. }
  8262. number += --digit << 2;
  8263. if ((digit = c2itable[str[5]]) <= 0)
  8264. {
  8265. return digit < 0 ? 0 : number;
  8266. }
  8267. number += --digit >> 4;
  8268. // ignore trailing padding
  8269. return number;
  8270. }
  8271. public LSL_Float llGetGMTclock()
  8272. {
  8273. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
  8274. return DateTime.UtcNow.TimeOfDay.TotalSeconds;
  8275. }
  8276. public LSL_String llGetHTTPHeader(LSL_Key request_id, string header)
  8277. {
  8278. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  8279. if (m_UrlModule != null)
  8280. return m_UrlModule.GetHttpHeader(request_id, header);
  8281. return String.Empty;
  8282. }
  8283. public LSL_String llGetSimulatorHostname()
  8284. {
  8285. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  8286. IUrlModule UrlModule = World.RequestModuleInterface<IUrlModule>();
  8287. return UrlModule.ExternalHostNameForLSL;
  8288. }
  8289. // <summary>
  8290. // Scan the string supplied in 'src' and
  8291. // tokenize it based upon two sets of
  8292. // tokenizers provided in two lists,
  8293. // separators and spacers.
  8294. // </summary>
  8295. //
  8296. // <remarks>
  8297. // Separators demarcate tokens and are
  8298. // elided as they are encountered. Spacers
  8299. // also demarcate tokens, but are themselves
  8300. // retained as tokens.
  8301. //
  8302. // Both separators and spacers may be arbitrarily
  8303. // long strings. i.e. ":::".
  8304. //
  8305. // The function returns an ordered list
  8306. // representing the tokens found in the supplied
  8307. // sources string. If two successive tokenizers
  8308. // are encountered, then a NULL entry is added
  8309. // to the list.
  8310. //
  8311. // It is a precondition that the source and
  8312. // toekizer lisst are non-null. If they are null,
  8313. // then a null pointer exception will be thrown
  8314. // while their lengths are being determined.
  8315. //
  8316. // A small amount of working memoryis required
  8317. // of approximately 8*#tokenizers.
  8318. //
  8319. // There are many ways in which this function
  8320. // can be implemented, this implementation is
  8321. // fairly naive and assumes that when the
  8322. // function is invooked with a short source
  8323. // string and/or short lists of tokenizers, then
  8324. // performance will not be an issue.
  8325. //
  8326. // In order to minimize the perofrmance
  8327. // effects of long strings, or large numbers
  8328. // of tokeizers, the function skips as far as
  8329. // possible whenever a toekenizer is found,
  8330. // and eliminates redundant tokenizers as soon
  8331. // as is possible.
  8332. //
  8333. // The implementation tries to avoid any copying
  8334. // of arrays or other objects.
  8335. // </remarks>
  8336. private LSL_List ParseString(string src, LSL_List separators, LSL_List spacers, bool keepNulls)
  8337. {
  8338. int beginning = 0;
  8339. int srclen = src.Length;
  8340. int seplen = separators.Length;
  8341. object[] separray = separators.Data;
  8342. int spclen = spacers.Length;
  8343. object[] spcarray = spacers.Data;
  8344. int mlen = seplen + spclen;
  8345. int[] offset = new int[mlen + 1];
  8346. bool[] active = new bool[mlen];
  8347. // Initial capacity reduces resize cost
  8348. LSL_List tokens = new LSL_List();
  8349. // All entries are initially valid
  8350. for (int i = 0; i < mlen; i++)
  8351. active[i] = true;
  8352. offset[mlen] = srclen;
  8353. while (beginning < srclen)
  8354. {
  8355. int best = mlen;
  8356. // Scan for separators
  8357. int j;
  8358. for (j = 0; j < seplen; j++)
  8359. {
  8360. if (separray[j].ToString() == String.Empty)
  8361. active[j] = false;
  8362. if (active[j])
  8363. {
  8364. // scan all of the markers
  8365. if ((offset[j] = src.IndexOf(separray[j].ToString(), beginning)) == -1)
  8366. {
  8367. // not present at all
  8368. active[j] = false;
  8369. }
  8370. else
  8371. {
  8372. // present and correct
  8373. if (offset[j] < offset[best])
  8374. {
  8375. // closest so far
  8376. best = j;
  8377. if (offset[best] == beginning)
  8378. break;
  8379. }
  8380. }
  8381. }
  8382. }
  8383. // Scan for spacers
  8384. if (offset[best] != beginning)
  8385. {
  8386. for (j = seplen; (j < mlen) && (offset[best] > beginning); j++)
  8387. {
  8388. if (spcarray[j - seplen].ToString() == String.Empty)
  8389. active[j] = false;
  8390. if (active[j])
  8391. {
  8392. // scan all of the markers
  8393. if ((offset[j] = src.IndexOf(spcarray[j - seplen].ToString(), beginning)) == -1)
  8394. {
  8395. // not present at all
  8396. active[j] = false;
  8397. }
  8398. else
  8399. {
  8400. // present and correct
  8401. if (offset[j] < offset[best])
  8402. {
  8403. // closest so far
  8404. best = j;
  8405. }
  8406. }
  8407. }
  8408. }
  8409. }
  8410. // This is the normal exit from the scanning loop
  8411. if (best == mlen)
  8412. {
  8413. // no markers were found on this pass
  8414. // so we're pretty much done
  8415. if ((keepNulls) || ((srclen - beginning) > 0))
  8416. tokens.Add(new LSL_String(src.Substring(beginning, srclen - beginning)));
  8417. break;
  8418. }
  8419. // Otherwise we just add the newly delimited token
  8420. // and recalculate where the search should continue.
  8421. if ((keepNulls) || ((offset[best] - beginning) > 0))
  8422. tokens.Add(new LSL_String(src.Substring(beginning, offset[best] - beginning)));
  8423. if (best < seplen)
  8424. {
  8425. beginning = offset[best] + (separray[best].ToString()).Length;
  8426. }
  8427. else
  8428. {
  8429. beginning = offset[best] + (spcarray[best - seplen].ToString()).Length;
  8430. string str = spcarray[best - seplen].ToString();
  8431. if ((keepNulls) || ((str.Length > 0)))
  8432. tokens.Add(new LSL_String(str));
  8433. }
  8434. }
  8435. // This an awkward an not very intuitive boundary case. If the
  8436. // last substring is a tokenizer, then there is an implied trailing
  8437. // null list entry. Hopefully the single comparison will not be too
  8438. // arduous. Alternatively the 'break' could be replced with a return
  8439. // but that's shabby programming.
  8440. if ((beginning == srclen) && (keepNulls))
  8441. {
  8442. if (srclen != 0)
  8443. tokens.Add(new LSL_String(""));
  8444. }
  8445. return tokens;
  8446. }
  8447. public LSL_List llParseString2List(string src, LSL_List separators, LSL_List spacers)
  8448. {
  8449. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "llParseString2List", m_host, "LSL", m_itemID)) return new LSL_List();
  8450. return ParseString(src, separators, spacers, false);
  8451. }
  8452. public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
  8453. {
  8454. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "llParseStringKeepNulls", m_host, "LSL", m_itemID)) return new LSL_List();
  8455. return ParseString(src, separators, spacers, true);
  8456. }
  8457. public LSL_Integer llGetObjectPermMask(int mask)
  8458. {
  8459. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Integer();
  8460. int permmask = 0;
  8461. if (mask == ScriptBaseClass.MASK_BASE)//0
  8462. {
  8463. permmask = (int)m_host.BaseMask;
  8464. }
  8465. else if (mask == ScriptBaseClass.MASK_OWNER)//1
  8466. {
  8467. permmask = (int)m_host.OwnerMask;
  8468. }
  8469. else if (mask == ScriptBaseClass.MASK_GROUP)//2
  8470. {
  8471. permmask = (int)m_host.GroupMask;
  8472. }
  8473. else if (mask == ScriptBaseClass.MASK_EVERYONE)//3
  8474. {
  8475. permmask = (int)m_host.EveryoneMask;
  8476. }
  8477. else if (mask == ScriptBaseClass.MASK_NEXT)//4
  8478. {
  8479. permmask = (int)m_host.NextOwnerMask;
  8480. }
  8481. return permmask;
  8482. }
  8483. public void llSetObjectPermMask(int mask, int value)
  8484. {
  8485. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  8486. if (m_ScriptEngine.Config.GetBoolean("AllowGodFunctions", false))
  8487. {
  8488. if (World.Permissions.CanRunConsoleCommand(m_host.OwnerID))
  8489. {
  8490. if (mask == ScriptBaseClass.MASK_BASE)//0
  8491. {
  8492. m_host.BaseMask = (uint)value;
  8493. }
  8494. else if (mask == ScriptBaseClass.MASK_OWNER)//1
  8495. {
  8496. m_host.OwnerMask = (uint)value;
  8497. }
  8498. else if (mask == ScriptBaseClass.MASK_GROUP)//2
  8499. {
  8500. m_host.GroupMask = (uint)value;
  8501. }
  8502. else if (mask == ScriptBaseClass.MASK_EVERYONE)//3
  8503. {
  8504. m_host.EveryoneMask = (uint)value;
  8505. }
  8506. else if (mask == ScriptBaseClass.MASK_NEXT)//4
  8507. {
  8508. m_host.NextOwnerMask = (uint)value;
  8509. }
  8510. }
  8511. }
  8512. }
  8513. public LSL_Integer llGetInventoryPermMask(string item, int mask)
  8514. {
  8515. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  8516. lock (m_host.TaskInventory)
  8517. {
  8518. foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
  8519. {
  8520. if (inv.Value.Name == item)
  8521. {
  8522. switch (mask)
  8523. {
  8524. case 0:
  8525. return (int)inv.Value.BasePermissions;
  8526. case 1:
  8527. return (int)inv.Value.CurrentPermissions;
  8528. case 2:
  8529. return (int)inv.Value.GroupPermissions;
  8530. case 3:
  8531. return (int)inv.Value.EveryonePermissions;
  8532. case 4:
  8533. return (int)inv.Value.NextPermissions;
  8534. }
  8535. }
  8536. }
  8537. }
  8538. return -1;
  8539. }
  8540. public void llSetInventoryPermMask(string item, int mask, int value)
  8541. {
  8542. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  8543. if (m_ScriptEngine.Config.GetBoolean("AllowGodFunctions", false))
  8544. {
  8545. if (World.Permissions.CanRunConsoleCommand(m_host.OwnerID))
  8546. {
  8547. lock (m_host.TaskInventory)
  8548. {
  8549. foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
  8550. {
  8551. if (inv.Value.Name == item)
  8552. {
  8553. switch (mask)
  8554. {
  8555. case 0:
  8556. inv.Value.BasePermissions = (uint)value;
  8557. break;
  8558. case 1:
  8559. inv.Value.CurrentPermissions = (uint)value;
  8560. break;
  8561. case 2:
  8562. inv.Value.GroupPermissions = (uint)value;
  8563. break;
  8564. case 3:
  8565. inv.Value.EveryonePermissions = (uint)value;
  8566. break;
  8567. case 4:
  8568. inv.Value.NextPermissions = (uint)value;
  8569. break;
  8570. }
  8571. }
  8572. }
  8573. }
  8574. }
  8575. }
  8576. }
  8577. public LSL_String llGetInventoryCreator(string item)
  8578. {
  8579. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  8580. lock (m_host.TaskInventory)
  8581. {
  8582. foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
  8583. {
  8584. if (inv.Value.Name == item)
  8585. {
  8586. return inv.Value.CreatorID.ToString();
  8587. }
  8588. }
  8589. }
  8590. llSay(0, "No item name '" + item + "'");
  8591. return String.Empty;
  8592. }
  8593. public void llOwnerSay(string msg)
  8594. {
  8595. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  8596. IChatModule chatModule = World.RequestModuleInterface<IChatModule>();
  8597. if (chatModule != null)
  8598. chatModule.SimChatBroadcast(msg, ChatTypeEnum.Owner, 0,
  8599. m_host.AbsolutePosition, m_host.Name, m_host.UUID, false, UUID.Zero, World);
  8600. }
  8601. public LSL_String llRequestSecureURL()
  8602. {
  8603. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  8604. if (m_UrlModule != null)
  8605. return m_UrlModule.RequestSecureURL(m_ScriptEngine.ScriptModule, m_host, m_itemID).ToString();
  8606. return UUID.Zero.ToString();
  8607. }
  8608. public LSL_String llGetEnv(LSL_String name)
  8609. {
  8610. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  8611. if (name == "sim_channel")
  8612. return "Aurora-Sim Server";
  8613. if (name == "sim_version")
  8614. return World.RequestModuleInterface<ISimulationBase>().Version;
  8615. return "";
  8616. }
  8617. public void llTeleportAgent(LSL_Key avatar, LSL_String landmark, LSL_Vector position, LSL_Vector look_at)
  8618. {
  8619. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  8620. UUID invItemID = InventorySelf();
  8621. if (invItemID == UUID.Zero)
  8622. return;
  8623. lock (m_host.TaskInventory)
  8624. {
  8625. if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero)
  8626. {
  8627. ShoutError("No permissions to teleport the agent");
  8628. return;
  8629. }
  8630. if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TELEPORT) == 0)
  8631. {
  8632. ShoutError("No permissions to teleport the agent");
  8633. return;
  8634. }
  8635. }
  8636. TaskInventoryItem item = null;
  8637. lock (m_host.TaskInventory)
  8638. {
  8639. foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
  8640. {
  8641. if (inv.Value.Name == landmark)
  8642. item = inv.Value;
  8643. }
  8644. }
  8645. if (item == null && landmark != "")
  8646. return;
  8647. IScenePresence presence = World.GetScenePresence(m_host.OwnerID);
  8648. if (presence != null)
  8649. {
  8650. IEntityTransferModule module = World.RequestModuleInterface<IEntityTransferModule>();
  8651. if (module != null)
  8652. {
  8653. if (landmark == "")
  8654. module.Teleport(presence, World.RegionInfo.RegionHandle,
  8655. position.ToVector3(), look_at.ToVector3(), (uint)TeleportFlags.ViaLocation);
  8656. else
  8657. {
  8658. AssetLandmark lm = new AssetLandmark(
  8659. World.AssetService.Get(item.AssetID.ToString()));
  8660. module.Teleport(presence, lm.RegionHandle, lm.Position,
  8661. look_at.ToVector3(), (uint)TeleportFlags.ViaLocation);
  8662. }
  8663. }
  8664. }
  8665. }
  8666. public void llTeleportAgentGlobalCoords(LSL_Key agent, LSL_Vector global_coordinates,
  8667. LSL_Vector region_coordinates, LSL_Vector look_at)
  8668. {
  8669. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  8670. UUID invItemID = InventorySelf();
  8671. if (invItemID == UUID.Zero)
  8672. return;
  8673. lock (m_host.TaskInventory)
  8674. {
  8675. if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero)
  8676. {
  8677. ShoutError("No permissions to teleport the agent");
  8678. return;
  8679. }
  8680. if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TELEPORT) == 0)
  8681. {
  8682. ShoutError("No permissions to teleport the agent");
  8683. return;
  8684. }
  8685. }
  8686. IScenePresence presence = World.GetScenePresence(m_host.OwnerID);
  8687. if (presence != null)
  8688. {
  8689. IEntityTransferModule module = World.RequestModuleInterface<IEntityTransferModule>();
  8690. if (module != null)
  8691. {
  8692. module.Teleport(presence, Utils.UIntsToLong((uint)global_coordinates.x, (uint)global_coordinates.y),
  8693. region_coordinates.ToVector3(), look_at.ToVector3(), (uint)TeleportFlags.ViaLocation);
  8694. }
  8695. }
  8696. }
  8697. public LSL_Key llRequestSimulatorData(string simulator, int data)
  8698. {
  8699. UUID tid = UUID.Zero;
  8700. try
  8701. {
  8702. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  8703. string reply = String.Empty;
  8704. GridRegion info = World.RegionInfo.RegionName == simulator
  8705. ? new GridRegion(World.RegionInfo)
  8706. : World.GridService.GetRegionByName(World.RegionInfo.AllScopeIDs, simulator);
  8707. switch (data)
  8708. {
  8709. case 5: // DATA_SIM_POS
  8710. if (info == null)
  8711. break;
  8712. reply = new LSL_Vector(
  8713. info.RegionLocX,
  8714. info.RegionLocY,
  8715. 0).ToString();
  8716. break;
  8717. case 6: // DATA_SIM_STATUS
  8718. if (info != null)
  8719. {
  8720. reply = (info.Flags & (int)Framework.RegionFlags.RegionOnline) != 0 ? "up" : "down";
  8721. }
  8722. //if() starting
  8723. //if() stopping
  8724. //if() crashed
  8725. else
  8726. reply = "unknown";
  8727. break;
  8728. case 7: // DATA_SIM_RATING
  8729. if (info == null)
  8730. break;
  8731. uint access = Util.ConvertAccessLevelToMaturity(info.Access);
  8732. if (access == 0)
  8733. reply = "PG";
  8734. else if (access == 1)
  8735. reply = "MATURE";
  8736. else if (access == 2)
  8737. reply = "ADULT";
  8738. else
  8739. reply = "UNKNOWN";
  8740. break;
  8741. case 128:
  8742. try
  8743. {
  8744. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.High, "llRequestSimulatorData", m_host, "LSL", m_itemID)) return "";
  8745. reply = "Aurora";
  8746. }
  8747. catch
  8748. {
  8749. reply = "";
  8750. }
  8751. break;
  8752. }
  8753. if (reply != "")
  8754. {
  8755. UUID rq = UUID.Random();
  8756. DataserverPlugin dataserverPlugin = (DataserverPlugin)m_ScriptEngine.GetScriptPlugin("Dataserver");
  8757. tid = dataserverPlugin.RegisterRequest(m_host.UUID, m_itemID, rq.ToString());
  8758. dataserverPlugin.AddReply(rq.ToString(), reply, 1000);
  8759. }
  8760. }
  8761. catch
  8762. {
  8763. }
  8764. ScriptSleep(1000);
  8765. return (LSL_Key)tid.ToString();
  8766. }
  8767. public LSL_String llRequestURL()
  8768. {
  8769. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  8770. if (m_UrlModule != null)
  8771. return m_UrlModule.RequestURL(m_ScriptEngine.ScriptModule, m_host, m_itemID).ToString();
  8772. return UUID.Zero.ToString();
  8773. }
  8774. public void llForceMouselook(int mouselook)
  8775. {
  8776. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  8777. m_host.ForceMouselook = (mouselook != 0);
  8778. }
  8779. /// <summary>
  8780. /// illListReplaceList removes the sub-list defined by the inclusive indices
  8781. /// start and end and inserts the src list in its place. The inclusive
  8782. /// nature of the indices means that at least one element must be deleted
  8783. /// if the indices are within the bounds of the existing list. I.e. 2,2
  8784. /// will remove the element at index 2 and replace it with the source
  8785. /// list. Both indices may be negative, with the usual interpretation. An
  8786. /// interesting case is where end is lower than start. As these indices
  8787. /// bound the list to be removed, then 0->end, and start->lim are removed
  8788. /// and the source list is added as a suffix.
  8789. /// </summary>
  8790. public LSL_List llListReplaceList(LSL_List dest, LSL_List src, int start, int end)
  8791. {
  8792. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_List();
  8793. // Note that although we have normalized, both
  8794. // indices could still be negative.
  8795. if (start < 0)
  8796. {
  8797. start = start + dest.Length;
  8798. }
  8799. if (end < 0)
  8800. {
  8801. end = end + dest.Length;
  8802. }
  8803. // The comventional case, remove a sequence starting with
  8804. // start and ending with end. And then insert the source
  8805. // list.
  8806. if (start <= end)
  8807. {
  8808. // If greater than zero, then there is going to be a
  8809. // surviving prefix. Otherwise the inclusive nature
  8810. // of the indices mean that we're going to add the
  8811. // source list as a prefix.
  8812. if (start > 0)
  8813. {
  8814. LSL_List pref = dest.GetSublist(0, start - 1);
  8815. // Only add a suffix if there is something
  8816. // beyond the end index (it's inclusive too).
  8817. if (end + 1 < dest.Length)
  8818. {
  8819. return pref + src + dest.GetSublist(end + 1, -1);
  8820. }
  8821. return pref + src;
  8822. }
  8823. // If start is less than or equal to zero, then
  8824. // the new list is simply a prefix. We still need to
  8825. // figure out any necessary surgery to the destination
  8826. // based upon end. Note that if end exceeds the upper
  8827. // bound in this case, the entire destination list
  8828. // is removed.
  8829. if (end + 1 < dest.Length)
  8830. {
  8831. return src + dest.GetSublist(end + 1, -1);
  8832. }
  8833. return src;
  8834. }
  8835. // Finally, if start > end, we strip away a prefix and
  8836. // a suffix, to leave the list that sits <between> ens
  8837. // and start, and then tag on the src list. AT least
  8838. // that's my interpretation. We can get sublist to do
  8839. // this for us. Note that one, or both of the indices
  8840. // might have been negative.
  8841. return dest.GetSublist(end + 1, start - 1) + src;
  8842. }
  8843. public DateTime llLoadURL(string avatar_id, string message, string url)
  8844. {
  8845. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return DateTime.Now;
  8846. IDialogModule dm = World.RequestModuleInterface<IDialogModule>();
  8847. if (null != dm)
  8848. dm.SendUrlToUser(
  8849. new UUID(avatar_id), m_host.Name, m_host.UUID, m_host.OwnerID, false, message, url);
  8850. return PScriptSleep(10000);
  8851. }
  8852. public DateTime llParcelMediaCommandList(LSL_List commandList)
  8853. {
  8854. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return DateTime.Now;
  8855. // according to the docs, this command only works if script owner and land owner are the same
  8856. // lets add estate owners and gods, too, and use the generic permission check.
  8857. IParcelManagementModule parcelManagement = World.RequestModuleInterface<IParcelManagementModule>();
  8858. if (parcelManagement != null)
  8859. {
  8860. ILandObject landObject = parcelManagement.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y);
  8861. if (landObject == null)
  8862. return DateTime.Now;
  8863. if (!World.Permissions.CanEditParcel(m_host.OwnerID, landObject))
  8864. return DateTime.Now;
  8865. bool update = false; // send a ParcelMediaUpdate (and possibly change the land's media URL)?
  8866. byte loop = 0;
  8867. LandData landData = landObject.LandData;
  8868. string url = landData.MediaURL;
  8869. string texture = landData.MediaID.ToString();
  8870. bool autoAlign = landData.MediaAutoScale != 0;
  8871. string mediaType = landData.MediaType;
  8872. string description = landData.MediaDescription;
  8873. int width = landData.MediaWidth;
  8874. int height = landData.MediaHeight;
  8875. float mediaLoopSet = landData.MediaLoopSet;
  8876. ParcelMediaCommandEnum? commandToSend = null;
  8877. float time = 0.0f; // default is from start
  8878. IScenePresence presence = null;
  8879. for (int i = 0; i < commandList.Data.Length; i++)
  8880. {
  8881. int tmp = ((LSL_Integer)commandList.Data[i]).value;
  8882. ParcelMediaCommandEnum command = (ParcelMediaCommandEnum)tmp;
  8883. switch (command)
  8884. {
  8885. case ParcelMediaCommandEnum.Agent:
  8886. // we send only to one agent
  8887. if ((i + 1) < commandList.Length)
  8888. {
  8889. if (commandList.Data[i + 1] is LSL_String)
  8890. {
  8891. UUID agentID;
  8892. if (UUID.TryParse((LSL_String)commandList.Data[i + 1], out agentID))
  8893. {
  8894. presence = World.GetScenePresence(agentID);
  8895. }
  8896. }
  8897. else ShoutError("The argument of PARCEL_MEDIA_COMMAND_AGENT must be a key");
  8898. ++i;
  8899. }
  8900. break;
  8901. case ParcelMediaCommandEnum.Loop:
  8902. loop = 1;
  8903. commandToSend = command;
  8904. update = true; //need to send the media update packet to set looping
  8905. break;
  8906. case ParcelMediaCommandEnum.LoopSet:
  8907. if ((i + 1) < commandList.Length)
  8908. {
  8909. if (commandList.Data[i + 1] is LSL_Float)
  8910. {
  8911. mediaLoopSet = (float)((LSL_Float)commandList.Data[i + 1]).value;
  8912. }
  8913. else ShoutError("The argument of PARCEL_MEDIA_COMMAND_LOOP_SET must be a float");
  8914. ++i;
  8915. }
  8916. commandToSend = command;
  8917. break;
  8918. case ParcelMediaCommandEnum.Play:
  8919. loop = 0;
  8920. commandToSend = command;
  8921. update = true; //need to send the media update packet to make sure it doesn't loop
  8922. break;
  8923. case ParcelMediaCommandEnum.Pause:
  8924. case ParcelMediaCommandEnum.Stop:
  8925. case ParcelMediaCommandEnum.Unload:
  8926. commandToSend = command;
  8927. break;
  8928. case ParcelMediaCommandEnum.Url:
  8929. if ((i + 1) < commandList.Length)
  8930. {
  8931. if (commandList.Data[i + 1] is LSL_String)
  8932. {
  8933. url = (LSL_String)commandList.Data[i + 1];
  8934. update = true;
  8935. }
  8936. else ShoutError("The argument of PARCEL_MEDIA_COMMAND_URL must be a string.");
  8937. ++i;
  8938. }
  8939. break;
  8940. case ParcelMediaCommandEnum.Texture:
  8941. if ((i + 1) < commandList.Length)
  8942. {
  8943. if (commandList.Data[i + 1] is LSL_String)
  8944. {
  8945. texture = (LSL_String)commandList.Data[i + 1];
  8946. update = true;
  8947. }
  8948. else ShoutError("The argument of PARCEL_MEDIA_COMMAND_TEXTURE must be a string or key.");
  8949. ++i;
  8950. }
  8951. break;
  8952. case ParcelMediaCommandEnum.Time:
  8953. if ((i + 1) < commandList.Length)
  8954. {
  8955. if (commandList.Data[i + 1] is LSL_Float)
  8956. {
  8957. time = (float)(LSL_Float)commandList.Data[i + 1];
  8958. }
  8959. else ShoutError("The argument of PARCEL_MEDIA_COMMAND_TIME must be a float.");
  8960. ++i;
  8961. }
  8962. commandToSend = command;
  8963. break;
  8964. case ParcelMediaCommandEnum.AutoAlign:
  8965. if ((i + 1) < commandList.Length)
  8966. {
  8967. if (commandList.Data[i + 1] is LSL_Integer)
  8968. {
  8969. autoAlign = (LSL_Integer)commandList.Data[i + 1];
  8970. update = true;
  8971. }
  8972. else ShoutError("The argument of PARCEL_MEDIA_COMMAND_AUTO_ALIGN must be an integer.");
  8973. ++i;
  8974. }
  8975. break;
  8976. case ParcelMediaCommandEnum.Type:
  8977. if ((i + 1) < commandList.Length)
  8978. {
  8979. if (commandList.Data[i + 1] is LSL_String)
  8980. {
  8981. mediaType = (LSL_String)commandList.Data[i + 1];
  8982. update = true;
  8983. }
  8984. else ShoutError("The argument of PARCEL_MEDIA_COMMAND_TYPE must be a string.");
  8985. ++i;
  8986. }
  8987. break;
  8988. case ParcelMediaCommandEnum.Desc:
  8989. if ((i + 1) < commandList.Length)
  8990. {
  8991. if (commandList.Data[i + 1] is LSL_String)
  8992. {
  8993. description = (LSL_String)commandList.Data[i + 1];
  8994. update = true;
  8995. }
  8996. else ShoutError("The argument of PARCEL_MEDIA_COMMAND_DESC must be a string.");
  8997. ++i;
  8998. }
  8999. break;
  9000. case ParcelMediaCommandEnum.Size:
  9001. if ((i + 2) < commandList.Length)
  9002. {
  9003. if (commandList.Data[i + 1] is LSL_Integer)
  9004. {
  9005. if (commandList.Data[i + 2] is LSL_Integer)
  9006. {
  9007. width = (LSL_Integer)commandList.Data[i + 1];
  9008. height = (LSL_Integer)commandList.Data[i + 2];
  9009. update = true;
  9010. }
  9011. else ShoutError("The second argument of PARCEL_MEDIA_COMMAND_SIZE must be an integer.");
  9012. }
  9013. else ShoutError("The first argument of PARCEL_MEDIA_COMMAND_SIZE must be an integer.");
  9014. i += 2;
  9015. }
  9016. break;
  9017. default:
  9018. NotImplemented("llParcelMediaCommandList parameter not supported yet: " + Enum.Parse(typeof(ParcelMediaCommandEnum), commandList.Data[i].ToString()));
  9019. break;
  9020. }//end switch
  9021. }//end for
  9022. // if we didn't get a presence, we send to all and change the url
  9023. // if we did get a presence, we only send to the agent specified, and *don't change the land settings*!
  9024. // did something important change or do we only start/stop/pause?
  9025. if (update)
  9026. {
  9027. if (presence == null)
  9028. {
  9029. // we send to all
  9030. landData.MediaID = new UUID(texture);
  9031. landData.MediaAutoScale = autoAlign ? (byte)1 : (byte)0;
  9032. landData.MediaWidth = width;
  9033. landData.MediaHeight = height;
  9034. landData.MediaType = mediaType;
  9035. landData.MediaDescription = description;
  9036. landData.MediaLoop = loop == 1;
  9037. landData.MediaLoopSet = mediaLoopSet;
  9038. // do that one last, it will cause a ParcelPropertiesUpdate
  9039. landObject.SetMediaUrl(url);
  9040. // now send to all (non-child) agents
  9041. World.ForEachScenePresence(delegate(IScenePresence sp)
  9042. {
  9043. if (!sp.IsChildAgent && (sp.CurrentParcelUUID == landData.GlobalID))
  9044. {
  9045. sp.ControllingClient.SendParcelMediaUpdate(landData.MediaURL,
  9046. landData.MediaID,
  9047. landData.MediaAutoScale,
  9048. mediaType,
  9049. description,
  9050. width, height,
  9051. loop);
  9052. }
  9053. });
  9054. }
  9055. else if (!presence.IsChildAgent)
  9056. {
  9057. // we only send to one (root) agent
  9058. presence.ControllingClient.SendParcelMediaUpdate(url,
  9059. new UUID(texture),
  9060. autoAlign ? (byte)1 : (byte)0,
  9061. mediaType,
  9062. description,
  9063. width, height,
  9064. loop);
  9065. }
  9066. }
  9067. if (commandToSend != null)
  9068. {
  9069. float ParamToSend = time;
  9070. if ((ParcelMediaCommandEnum)commandToSend == ParcelMediaCommandEnum.LoopSet)
  9071. ParamToSend = mediaLoopSet;
  9072. // the commandList contained a start/stop/... command, too
  9073. if (presence == null)
  9074. {
  9075. // send to all (non-child) agents
  9076. World.ForEachScenePresence(delegate(IScenePresence sp)
  9077. {
  9078. if (!sp.IsChildAgent)
  9079. {
  9080. sp.ControllingClient.SendParcelMediaCommand(landData.Flags,
  9081. (ParcelMediaCommandEnum)commandToSend,
  9082. ParamToSend);
  9083. }
  9084. });
  9085. }
  9086. else if (!presence.IsChildAgent)
  9087. {
  9088. presence.ControllingClient.SendParcelMediaCommand(landData.Flags,
  9089. (ParcelMediaCommandEnum)commandToSend,
  9090. ParamToSend);
  9091. }
  9092. }
  9093. }
  9094. return PScriptSleep(2000);
  9095. }
  9096. public LSL_List llParcelMediaQuery(LSL_List aList)
  9097. {
  9098. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_List();
  9099. LSL_List list = new LSL_List();
  9100. foreach (object t in aList.Data)
  9101. {
  9102. if (t != null)
  9103. {
  9104. IParcelManagementModule parcelManagement = World.RequestModuleInterface<IParcelManagementModule>();
  9105. if (parcelManagement != null)
  9106. {
  9107. LSL_Integer tmp = (LSL_Integer)t;
  9108. switch ((ParcelMediaCommandEnum)tmp.value)
  9109. {
  9110. case ParcelMediaCommandEnum.Url:
  9111. list.Add(new LSL_String(parcelManagement.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).LandData.MediaURL));
  9112. break;
  9113. case ParcelMediaCommandEnum.Desc:
  9114. list.Add(new LSL_String(parcelManagement.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).LandData.MediaDescription));
  9115. break;
  9116. case ParcelMediaCommandEnum.Texture:
  9117. list.Add(new LSL_String(parcelManagement.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).LandData.MediaID.ToString()));
  9118. break;
  9119. case ParcelMediaCommandEnum.Type:
  9120. list.Add(new LSL_String(parcelManagement.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).LandData.MediaType));
  9121. break;
  9122. case ParcelMediaCommandEnum.Loop:
  9123. list.Add(new LSL_Integer(parcelManagement.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).LandData.MediaLoop ? 1 : 0));
  9124. break;
  9125. case ParcelMediaCommandEnum.LoopSet:
  9126. list.Add(new LSL_Integer(parcelManagement.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).LandData.MediaLoopSet));
  9127. break;
  9128. case ParcelMediaCommandEnum.Size:
  9129. list.Add(new LSL_String(parcelManagement.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).LandData.MediaHeight));
  9130. list.Add(new LSL_String(parcelManagement.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).LandData.MediaWidth));
  9131. break;
  9132. default:
  9133. const ParcelMediaCommandEnum mediaCommandEnum = ParcelMediaCommandEnum.Url;
  9134. NotImplemented("llParcelMediaQuery parameter do not supported yet: " + Enum.Parse(mediaCommandEnum.GetType(), t.ToString()));
  9135. break;
  9136. }
  9137. }
  9138. }
  9139. }
  9140. ScriptSleep(2000);
  9141. return list;
  9142. }
  9143. public LSL_List llGetPrimMediaParams(LSL_Integer face, LSL_List rules)
  9144. {
  9145. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_List();
  9146. ScriptSleep(1000);
  9147. // LSL Spec http://wiki.secondlife.com/wiki/LlGetPrimMediaParams says to fail silently if face is invalid
  9148. // TODO: Need to correctly handle case where a face has no media (which gives back an empty list).
  9149. // Assuming silently fail means give back an empty list. Ideally, need to check this.
  9150. if (face < 0 || face > m_host.GetNumberOfSides() - 1)
  9151. return new LSL_List();
  9152. return GetPrimMediaParams(m_host, face, rules);
  9153. }
  9154. public LSL_List llGetLinkMedia(LSL_Integer link, LSL_Integer face, LSL_List rules)
  9155. {
  9156. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_List();
  9157. List<ISceneChildEntity> entities = GetLinkParts(link);
  9158. if (entities.Count == 0 || face < 0 || face > entities[0].GetNumberOfSides() - 1)
  9159. return new LSL_List();
  9160. LSL_List res = new LSL_List();
  9161. #if (!ISWIN)
  9162. LSL_List result = res;
  9163. foreach (ISceneChildEntity part in entities)
  9164. {
  9165. LSL_List list = GetPrimMediaParams(part, face, rules);
  9166. result = result + list;
  9167. }
  9168. return result;
  9169. #else
  9170. return entities.Select(part => GetPrimMediaParams(part, face, rules)).Aggregate(res,
  9171. (current, partRes) =>
  9172. current + partRes);
  9173. #endif
  9174. }
  9175. private LSL_List GetPrimMediaParams(ISceneChildEntity obj, int face, LSL_List rules)
  9176. {
  9177. IMoapModule module = World.RequestModuleInterface<IMoapModule>();
  9178. if (null == module)
  9179. throw new Exception("Media on a prim functions not available");
  9180. MediaEntry me = module.GetMediaEntry(obj, face);
  9181. // As per http://wiki.secondlife.com/wiki/LlGetPrimMediaParams
  9182. if (null == me)
  9183. return new LSL_List();
  9184. LSL_List res = new LSL_List();
  9185. for (int i = 0; i < rules.Length; i++)
  9186. {
  9187. int code = (int)rules.GetLSLIntegerItem(i);
  9188. if (code == ScriptBaseClass.PRIM_MEDIA_ALT_IMAGE_ENABLE)
  9189. {
  9190. // Not implemented
  9191. res.Add(new LSL_Integer(0));
  9192. }
  9193. else if (code == ScriptBaseClass.PRIM_MEDIA_CONTROLS)
  9194. {
  9195. res.Add(me.Controls == MediaControls.Standard
  9196. ? new LSL_Integer(ScriptBaseClass.PRIM_MEDIA_CONTROLS_STANDARD)
  9197. : new LSL_Integer(ScriptBaseClass.PRIM_MEDIA_CONTROLS_MINI));
  9198. }
  9199. else if (code == ScriptBaseClass.PRIM_MEDIA_CURRENT_URL)
  9200. {
  9201. res.Add(new LSL_String(me.CurrentURL));
  9202. }
  9203. else if (code == ScriptBaseClass.PRIM_MEDIA_HOME_URL)
  9204. {
  9205. res.Add(new LSL_String(me.HomeURL));
  9206. }
  9207. else if (code == ScriptBaseClass.PRIM_MEDIA_AUTO_LOOP)
  9208. {
  9209. res.Add(me.AutoLoop ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE);
  9210. }
  9211. else if (code == ScriptBaseClass.PRIM_MEDIA_AUTO_PLAY)
  9212. {
  9213. res.Add(me.AutoPlay ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE);
  9214. }
  9215. else if (code == ScriptBaseClass.PRIM_MEDIA_AUTO_SCALE)
  9216. {
  9217. res.Add(me.AutoScale ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE);
  9218. }
  9219. else if (code == ScriptBaseClass.PRIM_MEDIA_AUTO_ZOOM)
  9220. {
  9221. res.Add(me.AutoZoom ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE);
  9222. }
  9223. else if (code == ScriptBaseClass.PRIM_MEDIA_FIRST_CLICK_INTERACT)
  9224. {
  9225. res.Add(me.InteractOnFirstClick ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE);
  9226. }
  9227. else if (code == ScriptBaseClass.PRIM_MEDIA_WIDTH_PIXELS)
  9228. {
  9229. res.Add(new LSL_Integer(me.Width));
  9230. }
  9231. else if (code == ScriptBaseClass.PRIM_MEDIA_HEIGHT_PIXELS)
  9232. {
  9233. res.Add(new LSL_Integer(me.Height));
  9234. }
  9235. else if (code == ScriptBaseClass.PRIM_MEDIA_WHITELIST_ENABLE)
  9236. {
  9237. res.Add(me.EnableWhiteList ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE);
  9238. }
  9239. else if (code == ScriptBaseClass.PRIM_MEDIA_WHITELIST)
  9240. {
  9241. string[] urls = (string[])me.WhiteList.Clone();
  9242. for (int j = 0; j < urls.Length; j++)
  9243. urls[j] = Uri.EscapeDataString(urls[j]);
  9244. res.Add(new LSL_String(string.Join(", ", urls)));
  9245. }
  9246. else if (code == ScriptBaseClass.PRIM_MEDIA_PERMS_INTERACT)
  9247. {
  9248. res.Add(new LSL_Integer((int)me.InteractPermissions));
  9249. }
  9250. else if (code == ScriptBaseClass.PRIM_MEDIA_PERMS_CONTROL)
  9251. {
  9252. res.Add(new LSL_Integer((int)me.ControlPermissions));
  9253. }
  9254. }
  9255. return res;
  9256. }
  9257. public LSL_Integer llClearPrimMedia(LSL_Integer face)
  9258. {
  9259. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  9260. ScriptSleep(1000);
  9261. ClearPrimMedia(m_host, face);
  9262. return ScriptBaseClass.LSL_STATUS_OK;
  9263. }
  9264. public LSL_Integer llClearLinkMedia(LSL_Integer link, LSL_Integer face)
  9265. {
  9266. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  9267. ScriptSleep(1000);
  9268. List<ISceneChildEntity> entities = GetLinkParts(link);
  9269. if (entities.Count == 0 || face < 0 || face > entities[0].GetNumberOfSides() - 1)
  9270. return ScriptBaseClass.LSL_STATUS_OK;
  9271. foreach (ISceneChildEntity child in entities)
  9272. ClearPrimMedia(child, face);
  9273. return ScriptBaseClass.LSL_STATUS_OK;
  9274. }
  9275. private void ClearPrimMedia(ISceneChildEntity entity, LSL_Integer face)
  9276. {
  9277. // LSL Spec http://wiki.secondlife.com/wiki/LlClearPrimMedia says to fail silently if face is invalid
  9278. // Assuming silently fail means sending back LSL_STATUS_OK. Ideally, need to check this.
  9279. // FIXME: Don't perform the media check directly
  9280. if (face < 0 || face > entity.GetNumberOfSides() - 1)
  9281. return;
  9282. IMoapModule module = World.RequestModuleInterface<IMoapModule>();
  9283. if (null == module)
  9284. throw new Exception("Media on a prim functions not available");
  9285. module.ClearMediaEntry(entity, face);
  9286. }
  9287. public LSL_Integer llSetPrimMediaParams(LSL_Integer face, LSL_List rules)
  9288. {
  9289. ScriptSleep(1000);
  9290. // LSL Spec http://wiki.secondlife.com/wiki/LlSetPrimMediaParams says to fail silently if face is invalid
  9291. // Assuming silently fail means sending back LSL_STATUS_OK. Ideally, need to check this.
  9292. // Don't perform the media check directly
  9293. if (face < 0 || face > m_host.GetNumberOfSides() - 1)
  9294. return ScriptBaseClass.LSL_STATUS_OK;
  9295. return SetPrimMediaParams(m_host, face, rules);
  9296. }
  9297. public LSL_Integer llSetLinkMedia(LSL_Integer link, LSL_Integer face, LSL_List rules)
  9298. {
  9299. ScriptSleep(1000);
  9300. // LSL Spec http://wiki.secondlife.com/wiki/LlSetPrimMediaParams says to fail silently if face is invalid
  9301. // Assuming silently fail means sending back LSL_STATUS_OK. Ideally, need to check this.
  9302. // Don't perform the media check directly
  9303. List<ISceneChildEntity> entities = GetLinkParts(link);
  9304. if (entities.Count == 0 || face < 0 || face > entities[0].GetNumberOfSides() - 1)
  9305. return ScriptBaseClass.LSL_STATUS_OK;
  9306. foreach (ISceneChildEntity child in entities)
  9307. SetPrimMediaParams(child, face, rules);
  9308. return ScriptBaseClass.LSL_STATUS_OK;
  9309. }
  9310. public LSL_Integer SetPrimMediaParams(ISceneChildEntity obj, int face, LSL_List rules)
  9311. {
  9312. IMoapModule module = World.RequestModuleInterface<IMoapModule>();
  9313. if (null == module)
  9314. throw new Exception("Media on a prim functions not available");
  9315. MediaEntry me = module.GetMediaEntry(obj, face) ?? new MediaEntry();
  9316. int i = 0;
  9317. while (i < rules.Length - 1)
  9318. {
  9319. int code = rules.GetLSLIntegerItem(i++);
  9320. if (code == ScriptBaseClass.PRIM_MEDIA_ALT_IMAGE_ENABLE)
  9321. {
  9322. me.EnableAlterntiveImage = (rules.GetLSLIntegerItem(i++) != 0);
  9323. }
  9324. else if (code == ScriptBaseClass.PRIM_MEDIA_CONTROLS)
  9325. {
  9326. int v = rules.GetLSLIntegerItem(i++);
  9327. me.Controls = ScriptBaseClass.PRIM_MEDIA_CONTROLS_STANDARD == v
  9328. ? MediaControls.Standard
  9329. : MediaControls.Mini;
  9330. }
  9331. else if (code == ScriptBaseClass.PRIM_MEDIA_CURRENT_URL)
  9332. {
  9333. me.CurrentURL = rules.GetLSLStringItem(i++);
  9334. }
  9335. else if (code == ScriptBaseClass.PRIM_MEDIA_HOME_URL)
  9336. {
  9337. me.HomeURL = rules.GetLSLStringItem(i++);
  9338. }
  9339. else if (code == ScriptBaseClass.PRIM_MEDIA_AUTO_LOOP)
  9340. {
  9341. me.AutoLoop = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++));
  9342. }
  9343. else if (code == ScriptBaseClass.PRIM_MEDIA_AUTO_PLAY)
  9344. {
  9345. me.AutoPlay = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++));
  9346. }
  9347. else if (code == ScriptBaseClass.PRIM_MEDIA_AUTO_SCALE)
  9348. {
  9349. me.AutoScale = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++));
  9350. }
  9351. else if (code == ScriptBaseClass.PRIM_MEDIA_AUTO_ZOOM)
  9352. {
  9353. me.AutoZoom = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++));
  9354. }
  9355. else if (code == ScriptBaseClass.PRIM_MEDIA_FIRST_CLICK_INTERACT)
  9356. {
  9357. me.InteractOnFirstClick = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++));
  9358. }
  9359. else if (code == ScriptBaseClass.PRIM_MEDIA_WIDTH_PIXELS)
  9360. {
  9361. me.Width = rules.GetLSLIntegerItem(i++);
  9362. }
  9363. else if (code == ScriptBaseClass.PRIM_MEDIA_HEIGHT_PIXELS)
  9364. {
  9365. me.Height = rules.GetLSLIntegerItem(i++);
  9366. }
  9367. else if (code == ScriptBaseClass.PRIM_MEDIA_WHITELIST_ENABLE)
  9368. {
  9369. me.EnableWhiteList = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++));
  9370. }
  9371. else if (code == ScriptBaseClass.PRIM_MEDIA_WHITELIST)
  9372. {
  9373. string[] rawWhiteListUrls = rules.GetLSLStringItem(i++).ToString().Split(new[] { ',' });
  9374. List<string> whiteListUrls = new List<string>();
  9375. #if (!ISWIN)
  9376. Array.ForEach(
  9377. rawWhiteListUrls, delegate(string rawUrl) { whiteListUrls.Add(rawUrl.Trim()); });
  9378. #else
  9379. Array.ForEach(
  9380. rawWhiteListUrls, rawUrl => whiteListUrls.Add(rawUrl.Trim()));
  9381. #endif
  9382. me.WhiteList = whiteListUrls.ToArray();
  9383. }
  9384. else if (code == ScriptBaseClass.PRIM_MEDIA_PERMS_INTERACT)
  9385. {
  9386. me.InteractPermissions = (MediaPermission)(byte)(int)rules.GetLSLIntegerItem(i++);
  9387. }
  9388. else if (code == ScriptBaseClass.PRIM_MEDIA_PERMS_CONTROL)
  9389. {
  9390. me.ControlPermissions = (MediaPermission)(byte)(int)rules.GetLSLIntegerItem(i++);
  9391. }
  9392. }
  9393. module.SetMediaEntry(obj, face, me);
  9394. return ScriptBaseClass.LSL_STATUS_OK;
  9395. }
  9396. public LSL_Integer llModPow(int a, int b, int c)
  9397. {
  9398. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  9399. Int64 tmp = 0;
  9400. Math.DivRem(Convert.ToInt64(Math.Pow(a, b)), c, out tmp);
  9401. ScriptSleep(100);
  9402. return Convert.ToInt32(tmp);
  9403. }
  9404. public LSL_Integer llGetInventoryType(string name)
  9405. {
  9406. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  9407. lock (m_host.TaskInventory)
  9408. {
  9409. foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
  9410. {
  9411. if (inv.Value.Name == name)
  9412. {
  9413. return inv.Value.Type;
  9414. }
  9415. }
  9416. }
  9417. return -1;
  9418. }
  9419. public void llSetPayPrice(int price, LSL_List quick_pay_buttons)
  9420. {
  9421. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  9422. m_host.ParentEntity.RootChild.PayPrice[0] = price;
  9423. if (quick_pay_buttons.Data.Length > 0)
  9424. m_host.ParentEntity.RootChild.PayPrice[1] = (LSL_Integer)quick_pay_buttons.Data[0];
  9425. else
  9426. m_host.ParentEntity.RootChild.PayPrice[1] = (LSL_Integer)(-2);
  9427. if (quick_pay_buttons.Data.Length > 1)
  9428. m_host.ParentEntity.RootChild.PayPrice[2] = (LSL_Integer)quick_pay_buttons.Data[1];
  9429. else
  9430. m_host.ParentEntity.RootChild.PayPrice[2] = (LSL_Integer)(-2);
  9431. if (quick_pay_buttons.Data.Length > 2)
  9432. m_host.ParentEntity.RootChild.PayPrice[3] = (LSL_Integer)quick_pay_buttons.Data[2];
  9433. else
  9434. m_host.ParentEntity.RootChild.PayPrice[3] = (LSL_Integer)(-2);
  9435. if (quick_pay_buttons.Data.Length > 3)
  9436. m_host.ParentEntity.RootChild.PayPrice[4] = (LSL_Integer)quick_pay_buttons.Data[3];
  9437. else
  9438. m_host.ParentEntity.RootChild.PayPrice[4] = (LSL_Integer)(-2);
  9439. }
  9440. public LSL_Vector llGetCameraPos()
  9441. {
  9442. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
  9443. UUID invItemID = InventorySelf();
  9444. if (invItemID == UUID.Zero)
  9445. return new LSL_Vector();
  9446. lock (m_host.TaskInventory)
  9447. {
  9448. if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero)
  9449. return new LSL_Vector();
  9450. if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0)
  9451. {
  9452. ShoutError("No permissions to track the camera");
  9453. return new LSL_Vector();
  9454. }
  9455. }
  9456. IScenePresence presence = World.GetScenePresence(m_host.OwnerID);
  9457. if (presence != null)
  9458. {
  9459. LSL_Vector pos = new LSL_Vector(presence.CameraPosition.X, presence.CameraPosition.Y, presence.CameraPosition.Z);
  9460. return pos;
  9461. }
  9462. return new LSL_Vector();
  9463. }
  9464. public LSL_Rotation llGetCameraRot()
  9465. {
  9466. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Rotation();
  9467. UUID invItemID = InventorySelf();
  9468. if (invItemID == UUID.Zero)
  9469. return new LSL_Rotation();
  9470. lock (m_host.TaskInventory)
  9471. {
  9472. if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero)
  9473. return new LSL_Rotation();
  9474. if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0)
  9475. {
  9476. ShoutError("No permissions to track the camera");
  9477. return new LSL_Rotation();
  9478. }
  9479. }
  9480. IScenePresence presence = World.GetScenePresence(m_host.OwnerID);
  9481. if (presence != null)
  9482. {
  9483. return new LSL_Rotation(presence.CameraRotation.X, presence.CameraRotation.Y, presence.CameraRotation.Z, presence.CameraRotation.W);
  9484. }
  9485. return new LSL_Rotation();
  9486. }
  9487. /// <summary>
  9488. /// The SL implementation does nothing, it is deprecated
  9489. /// This duplicates SL
  9490. /// </summary>
  9491. public DateTime llSetPrimURL(string url)
  9492. {
  9493. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return DateTime.Now;
  9494. return PScriptSleep(2000);
  9495. }
  9496. /// <summary>
  9497. /// The SL implementation shouts an error, it is deprecated
  9498. /// This duplicates SL
  9499. /// </summary>
  9500. public DateTime llRefreshPrimURL()
  9501. {
  9502. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return DateTime.Now;
  9503. Deprecated("llRefreshPrimURL");
  9504. return PScriptSleep(20000);
  9505. }
  9506. public LSL_String llEscapeURL(string url)
  9507. {
  9508. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_String();
  9509. try
  9510. {
  9511. return Uri.EscapeDataString(url);
  9512. }
  9513. catch (Exception ex)
  9514. {
  9515. return "llEscapeURL: " + ex;
  9516. }
  9517. }
  9518. public LSL_String llUnescapeURL(string url)
  9519. {
  9520. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  9521. try
  9522. {
  9523. return Uri.UnescapeDataString(url);
  9524. }
  9525. catch (Exception ex)
  9526. {
  9527. return "llUnescapeURL: " + ex;
  9528. }
  9529. }
  9530. public DateTime llMapDestination(string simname, LSL_Vector pos, LSL_Vector lookAt)
  9531. {
  9532. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return DateTime.Now;
  9533. UUID avatarID = m_host.OwnerID;
  9534. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, 0);
  9535. // only works on the first detected avatar
  9536. //This only works in touch events or if the item is attached to the avatar
  9537. if (detectedParams == null && !m_host.IsAttachment) return DateTime.Now;
  9538. if (detectedParams != null)
  9539. avatarID = detectedParams.Key;
  9540. IScenePresence avatar = World.GetScenePresence(avatarID);
  9541. if (avatar != null)
  9542. {
  9543. IMuteListModule module = m_host.ParentEntity.Scene.RequestModuleInterface<IMuteListModule>();
  9544. if (module != null)
  9545. {
  9546. bool cached = false; //Unneeded
  9547. #if (!ISWIN)
  9548. foreach (MuteList mute in module.GetMutes(avatar.UUID, out cached))
  9549. if (mute.MuteID == m_host.OwnerID)
  9550. return DateTime.Now;//If the avatar is muted, they don't get any contact from the muted av
  9551. #else
  9552. if (module.GetMutes(avatar.UUID, out cached).Any(mute => mute.MuteID == m_host.OwnerID))
  9553. {
  9554. return DateTime.Now;//If the avatar is muted, they don't get any contact from the muted av
  9555. }
  9556. #endif
  9557. }
  9558. avatar.ControllingClient.SendScriptTeleportRequest(m_host.Name, simname,
  9559. new Vector3((float)pos.x, (float)pos.y, (float)pos.z),
  9560. new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z));
  9561. }
  9562. return PScriptSleep(1000);
  9563. }
  9564. public DateTime llAddToLandBanList(string avatar, double hours)
  9565. {
  9566. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return DateTime.Now;
  9567. IParcelManagementModule parcelManagement = World.RequestModuleInterface<IParcelManagementModule>();
  9568. if (parcelManagement != null)
  9569. {
  9570. LandData land = parcelManagement.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).LandData;
  9571. if (land.OwnerID == m_host.OwnerID)
  9572. {
  9573. ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
  9574. UUID key;
  9575. if (UUID.TryParse(avatar, out key))
  9576. {
  9577. entry.AgentID = key;
  9578. entry.Flags = AccessList.Ban;
  9579. entry.Time = DateTime.Now.AddHours(hours);
  9580. land.ParcelAccessList.Add(entry);
  9581. }
  9582. }
  9583. }
  9584. return PScriptSleep(100);
  9585. }
  9586. public DateTime llRemoveFromLandPassList(string avatar)
  9587. {
  9588. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return DateTime.Now;
  9589. IParcelManagementModule parcelManagement = World.RequestModuleInterface<IParcelManagementModule>();
  9590. if (parcelManagement != null)
  9591. {
  9592. LandData land = parcelManagement.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).LandData;
  9593. if (land.OwnerID == m_host.OwnerID)
  9594. {
  9595. UUID key;
  9596. if (UUID.TryParse(avatar, out key))
  9597. {
  9598. foreach (ParcelManager.ParcelAccessEntry entry in land.ParcelAccessList)
  9599. {
  9600. if (entry.AgentID == key && entry.Flags == AccessList.Access)
  9601. {
  9602. land.ParcelAccessList.Remove(entry);
  9603. break;
  9604. }
  9605. }
  9606. }
  9607. }
  9608. }
  9609. return PScriptSleep(100);
  9610. }
  9611. public DateTime llRemoveFromLandBanList(string avatar)
  9612. {
  9613. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return DateTime.Now;
  9614. IParcelManagementModule parcelManagement = World.RequestModuleInterface<IParcelManagementModule>();
  9615. if (parcelManagement != null)
  9616. {
  9617. LandData land = parcelManagement.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).LandData;
  9618. if (land.OwnerID == m_host.OwnerID)
  9619. {
  9620. UUID key;
  9621. if (UUID.TryParse(avatar, out key))
  9622. {
  9623. foreach (ParcelManager.ParcelAccessEntry entry in land.ParcelAccessList)
  9624. {
  9625. if (entry.AgentID == key && entry.Flags == AccessList.Ban)
  9626. {
  9627. land.ParcelAccessList.Remove(entry);
  9628. break;
  9629. }
  9630. }
  9631. }
  9632. }
  9633. }
  9634. return PScriptSleep(100);
  9635. }
  9636. public void llSetCameraParams(LSL_List rules)
  9637. {
  9638. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  9639. // our key in the object we are in
  9640. UUID invItemID = InventorySelf();
  9641. if (invItemID == UUID.Zero) return;
  9642. // the object we are in
  9643. UUID objectID = m_host.ParentUUID;
  9644. if (objectID == UUID.Zero) return;
  9645. UUID agentID;
  9646. lock (m_host.TaskInventory)
  9647. {
  9648. // we need the permission first, to know which avatar we want to set the camera for
  9649. agentID = m_host.TaskInventory[invItemID].PermsGranter;
  9650. if (agentID == UUID.Zero) return;
  9651. if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) return;
  9652. }
  9653. IScenePresence presence = World.GetScenePresence(agentID);
  9654. // we are not interested in child-agents
  9655. if (presence.IsChildAgent) return;
  9656. SortedDictionary<int, float> parameters = new SortedDictionary<int, float>();
  9657. object[] data = rules.Data;
  9658. for (int i = 0; i < data.Length; ++i)
  9659. {
  9660. int type = Convert.ToInt32(data[i++].ToString());
  9661. if (i >= data.Length) break; // odd number of entries => ignore the last
  9662. // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3)
  9663. if (type == ScriptBaseClass.CAMERA_FOCUS ||
  9664. type == ScriptBaseClass.CAMERA_FOCUS_OFFSET ||
  9665. type == ScriptBaseClass.CAMERA_POSITION)
  9666. {
  9667. LSL_Vector v = (LSL_Vector)data[i];
  9668. parameters.Add(type + 1, (float)v.x);
  9669. parameters.Add(type + 2, (float)v.y);
  9670. parameters.Add(type + 3, (float)v.z);
  9671. }
  9672. else
  9673. {
  9674. if (data[i] is LSL_Float)
  9675. parameters.Add(type, (float)((LSL_Float)data[i]).value);
  9676. else if (data[i] is LSL_Integer)
  9677. parameters.Add(type, ((LSL_Integer)data[i]).value);
  9678. else parameters.Add(type, Convert.ToSingle(data[i]));
  9679. }
  9680. }
  9681. if (parameters.Count > 0) presence.ControllingClient.SendSetFollowCamProperties(objectID, parameters);
  9682. }
  9683. public void llClearCameraParams()
  9684. {
  9685. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  9686. // our key in the object we are in
  9687. UUID invItemID = InventorySelf();
  9688. if (invItemID == UUID.Zero) return;
  9689. // the object we are in
  9690. UUID objectID = m_host.ParentUUID;
  9691. if (objectID == UUID.Zero) return;
  9692. // we need the permission first, to know which avatar we want to clear the camera for
  9693. UUID agentID;
  9694. lock (m_host.TaskInventory)
  9695. {
  9696. agentID = m_host.TaskInventory[invItemID].PermsGranter;
  9697. if (agentID == UUID.Zero) return;
  9698. if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) return;
  9699. }
  9700. IScenePresence presence = World.GetScenePresence(agentID);
  9701. // we are not interested in child-agents
  9702. if (presence.IsChildAgent) return;
  9703. presence.ControllingClient.SendClearFollowCamProperties(objectID);
  9704. }
  9705. public LSL_Float llListStatistics(int operation, LSL_List src)
  9706. {
  9707. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
  9708. LSL_List nums = LSL_List.ToDoubleList(src);
  9709. if (operation == ScriptBaseClass.LIST_STAT_RANGE)
  9710. return nums.Range();
  9711. if (operation == ScriptBaseClass.LIST_STAT_MIN)
  9712. return nums.Min();
  9713. if (operation == ScriptBaseClass.LIST_STAT_MAX)
  9714. return nums.Max();
  9715. if (operation == ScriptBaseClass.LIST_STAT_MEAN)
  9716. return nums.Mean();
  9717. if (operation == ScriptBaseClass.LIST_STAT_MEDIAN)
  9718. return nums.Median();
  9719. if (operation == ScriptBaseClass.LIST_STAT_NUM_COUNT)
  9720. return nums.NumericLength();
  9721. if (operation == ScriptBaseClass.LIST_STAT_STD_DEV)
  9722. return nums.StdDev();
  9723. if (operation == ScriptBaseClass.LIST_STAT_SUM)
  9724. return nums.Sum();
  9725. if (operation == ScriptBaseClass.LIST_STAT_SUM_SQUARES)
  9726. return nums.SumSqrs();
  9727. if (operation == ScriptBaseClass.LIST_STAT_GEOMETRIC_MEAN)
  9728. return nums.GeometricMean();
  9729. if (operation == ScriptBaseClass.LIST_STAT_HARMONIC_MEAN)
  9730. return nums.HarmonicMean();
  9731. return 0.0;
  9732. }
  9733. public LSL_Integer llGetUnixTime()
  9734. {
  9735. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  9736. return Util.UnixTimeSinceEpoch();
  9737. }
  9738. public LSL_Integer llGetParcelFlags(LSL_Vector pos)
  9739. {
  9740. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  9741. IParcelManagementModule parcelManagement = World.RequestModuleInterface<IParcelManagementModule>();
  9742. if (parcelManagement != null)
  9743. {
  9744. return (int)parcelManagement.GetLandObject((float)pos.x, (float)pos.y).LandData.Flags;
  9745. }
  9746. return 0;
  9747. }
  9748. public LSL_Integer llGetRegionFlags()
  9749. {
  9750. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  9751. IEstateModule estate = World.RequestModuleInterface<IEstateModule>();
  9752. if (estate == null)
  9753. return 67108864;
  9754. return (int)estate.GetRegionFlags();
  9755. }
  9756. public LSL_String llXorBase64StringsCorrect(string str1, string str2)
  9757. {
  9758. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  9759. string ret = String.Empty;
  9760. string src1 = llBase64ToString(str1);
  9761. string src2 = llBase64ToString(str2);
  9762. int c = 0;
  9763. foreach (char t in src1)
  9764. {
  9765. ret += (char)(t ^ src2[c]);
  9766. c++;
  9767. if (c >= src2.Length)
  9768. c = 0;
  9769. }
  9770. return llStringToBase64(ret);
  9771. }
  9772. public LSL_String llHTTPRequest(string url, LSL_List parameters, string body)
  9773. {
  9774. // Partial implementation: support for parameter flags needed
  9775. // see http://wiki.secondlife.com/wiki/LlHTTPRequest
  9776. // parameter flags support are implemented in ScriptsHttpRequests.cs
  9777. // in StartHttpRequest
  9778. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  9779. IHttpRequestModule httpScriptMod =
  9780. World.RequestModuleInterface<IHttpRequestModule>();
  9781. #if (!ISWIN)
  9782. List<string> param = new List<string>();
  9783. foreach (object o in parameters.Data)
  9784. param.Add(o.ToString());
  9785. #else
  9786. List<string> param = parameters.Data.Select(o => o.ToString()).ToList();
  9787. #endif
  9788. Vector3 position = m_host.AbsolutePosition;
  9789. Vector3 velocity = m_host.Velocity;
  9790. Quaternion rotation = m_host.RotationOffset;
  9791. string ownerName = String.Empty;
  9792. IScenePresence scenePresence = World.GetScenePresence(m_host.OwnerID);
  9793. ownerName = scenePresence == null ? resolveName(m_host.OwnerID) : scenePresence.Name;
  9794. RegionInfo regionInfo = World.RegionInfo;
  9795. Dictionary<string, string> httpHeaders = new Dictionary<string, string>();
  9796. string shard = "OpenSim";
  9797. IConfigSource config = m_ScriptEngine.ConfigSource;
  9798. if (config.Configs["LSLRemoting"] != null)
  9799. shard = config.Configs["LSLRemoting"].GetString("shard", shard);
  9800. httpHeaders["X-SecondLife-Shard"] = shard;
  9801. httpHeaders["X-SecondLife-Object-Name"] = m_host.Name;
  9802. httpHeaders["X-SecondLife-Object-Key"] = m_host.UUID.ToString();
  9803. httpHeaders["X-SecondLife-Region"] = string.Format("{0} ({1}, {2})", regionInfo.RegionName, regionInfo.RegionLocX, regionInfo.RegionLocY);
  9804. httpHeaders["X-SecondLife-Local-Position"] = string.Format("({0:0.000000}, {1:0.000000}, {2:0.000000})", position.X, position.Y, position.Z);
  9805. httpHeaders["X-SecondLife-Local-Velocity"] = string.Format("({0:0.000000}, {1:0.000000}, {2:0.000000})", velocity.X, velocity.Y, velocity.Z);
  9806. httpHeaders["X-SecondLife-Local-Rotation"] = string.Format("({0:0.000000}, {1:0.000000}, {2:0.000000}, {3:0.000000})", rotation.X, rotation.Y, rotation.Z, rotation.W);
  9807. httpHeaders["X-SecondLife-Owner-Name"] = ownerName;
  9808. httpHeaders["X-SecondLife-Owner-Key"] = m_host.OwnerID.ToString();
  9809. string userAgent = "";
  9810. if (config.Configs["LSLRemoting"] != null)
  9811. userAgent = config.Configs["LSLRemoting"].GetString("user_agent", null);
  9812. if (userAgent != null)
  9813. httpHeaders["User-Agent"] = userAgent;
  9814. const string authregex = @"^(https?:\/\/)(\w+):(\w+)@(.*)$";
  9815. Regex r = new Regex(authregex);
  9816. Match m = r.Match(url);
  9817. if (m.Success)
  9818. {
  9819. //for (int i = 1; i < gnums.Length; i++) {
  9820. // //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]];
  9821. // //CaptureCollection cc = g.Captures;
  9822. //}
  9823. if (m.Groups.Count == 5)
  9824. {
  9825. httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.Encoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString())));
  9826. url = m.Groups[1].ToString() + m.Groups[4];
  9827. }
  9828. }
  9829. UUID reqID = httpScriptMod.
  9830. StartHttpRequest(m_host.UUID, m_itemID, url, param, httpHeaders, body);
  9831. if (reqID != UUID.Zero)
  9832. return reqID.ToString();
  9833. else
  9834. return new LSL_String("");
  9835. }
  9836. public void llSetContentType(LSL_Key id, LSL_Integer type)
  9837. {
  9838. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  9839. string content_type = "text/plain";
  9840. if (type == ScriptBaseClass.CONTENT_TYPE_TEXT)
  9841. content_type = "text/plain";
  9842. else if (type == ScriptBaseClass.CONTENT_TYPE_HTML)
  9843. content_type = "text/html";
  9844. if (m_UrlModule != null)
  9845. m_UrlModule.SetContentType(id, content_type);
  9846. }
  9847. public void llHTTPResponse(LSL_Key id, int status, string body)
  9848. {
  9849. // Partial implementation: support for parameter flags needed
  9850. // see http://wiki.secondlife.com/wiki/llHTTPResponse
  9851. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  9852. if (m_UrlModule != null)
  9853. m_UrlModule.HttpResponse(id, status, body);
  9854. }
  9855. public DateTime llResetLandBanList()
  9856. {
  9857. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return DateTime.Now;
  9858. IParcelManagementModule parcelManagement = World.RequestModuleInterface<IParcelManagementModule>();
  9859. if (parcelManagement != null)
  9860. {
  9861. LandData land = parcelManagement.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).LandData;
  9862. if (land.OwnerID == m_host.OwnerID)
  9863. {
  9864. foreach (ParcelManager.ParcelAccessEntry entry in land.ParcelAccessList)
  9865. {
  9866. if (entry.Flags == AccessList.Ban)
  9867. {
  9868. land.ParcelAccessList.Remove(entry);
  9869. }
  9870. }
  9871. }
  9872. }
  9873. return PScriptSleep(100);
  9874. }
  9875. public DateTime llResetLandPassList()
  9876. {
  9877. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return DateTime.Now;
  9878. IParcelManagementModule parcelManagement = World.RequestModuleInterface<IParcelManagementModule>();
  9879. if (parcelManagement != null)
  9880. {
  9881. LandData land = parcelManagement.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).LandData;
  9882. if (land.OwnerID == m_host.OwnerID)
  9883. {
  9884. foreach (ParcelManager.ParcelAccessEntry entry in land.ParcelAccessList)
  9885. {
  9886. if (entry.Flags == AccessList.Access)
  9887. {
  9888. land.ParcelAccessList.Remove(entry);
  9889. }
  9890. }
  9891. }
  9892. }
  9893. return PScriptSleep(100);
  9894. }
  9895. public LSL_Integer llGetParcelPrimCount(LSL_Vector pos, int category, int sim_wide)
  9896. {
  9897. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  9898. IParcelManagementModule parcelManagement = World.RequestModuleInterface<IParcelManagementModule>();
  9899. if (parcelManagement != null)
  9900. {
  9901. LandData land = parcelManagement.GetLandObject((float)pos.x, (float)pos.y).LandData;
  9902. if (land == null)
  9903. {
  9904. return 0;
  9905. }
  9906. IPrimCountModule primCountsModule = World.RequestModuleInterface<IPrimCountModule>();
  9907. if (primCountsModule != null)
  9908. {
  9909. IPrimCounts primCounts = primCountsModule.GetPrimCounts(land.GlobalID);
  9910. if (sim_wide != 0)
  9911. {
  9912. if (category == 0)
  9913. {
  9914. return primCounts.Simulator;
  9915. }
  9916. return 0;
  9917. }
  9918. switch (category)
  9919. {
  9920. case 0:
  9921. return primCounts.Total;//land.
  9922. case 1:
  9923. return primCounts.Owner;
  9924. case 2:
  9925. return primCounts.Group;
  9926. case 3:
  9927. return primCounts.Others;
  9928. case 4:
  9929. return primCounts.Selected;
  9930. case 5:
  9931. return primCounts.Temporary;//land.
  9932. }
  9933. }
  9934. }
  9935. return 0;
  9936. }
  9937. public LSL_List llGetParcelPrimOwners(LSL_Vector pos)
  9938. {
  9939. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_List();
  9940. IParcelManagementModule parcelManagement = World.RequestModuleInterface<IParcelManagementModule>();
  9941. LSL_List ret = new LSL_List();
  9942. if (parcelManagement != null)
  9943. {
  9944. ILandObject land = parcelManagement.GetLandObject((float)pos.x, (float)pos.y);
  9945. if (land != null)
  9946. {
  9947. IPrimCountModule primCountModule = World.RequestModuleInterface<IPrimCountModule>();
  9948. if (primCountModule != null)
  9949. {
  9950. IPrimCounts primCounts = primCountModule.GetPrimCounts(land.LandData.GlobalID);
  9951. foreach (KeyValuePair<UUID, int> detectedParams in primCounts.GetAllUserCounts())
  9952. {
  9953. ret.Add(new LSL_String(detectedParams.Key.ToString()));
  9954. ret.Add(new LSL_Integer(detectedParams.Value));
  9955. }
  9956. }
  9957. }
  9958. }
  9959. ScriptSleep(2000);
  9960. return ret;
  9961. }
  9962. public LSL_Integer llGetObjectPrimCount(string object_id)
  9963. {
  9964. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  9965. ISceneChildEntity part = World.GetSceneObjectPart(new UUID(object_id));
  9966. if (part == null)
  9967. {
  9968. return 0;
  9969. }
  9970. return part.ParentEntity.PrimCount;
  9971. }
  9972. public LSL_Integer llGetParcelMaxPrims(LSL_Vector pos, int sim_wide)
  9973. {
  9974. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  9975. IParcelManagementModule parcelManagement = World.RequestModuleInterface<IParcelManagementModule>();
  9976. if (parcelManagement != null)
  9977. {
  9978. IPrimCountModule primCount = World.RequestModuleInterface<IPrimCountModule>();
  9979. ILandObject land = parcelManagement.GetLandObject((float)pos.x, (float)pos.y);
  9980. return primCount.GetParcelMaxPrimCount(land);
  9981. }
  9982. return 0;
  9983. }
  9984. public LSL_List llGetParcelDetails(LSL_Vector pos, LSL_List param)
  9985. {
  9986. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_List();
  9987. IParcelManagementModule parcelManagement = World.RequestModuleInterface<IParcelManagementModule>();
  9988. LSL_List ret = new LSL_List();
  9989. if (parcelManagement != null)
  9990. {
  9991. LandData land = parcelManagement.GetLandObject((float)pos.x, (float)pos.y).LandData;
  9992. if (land == null)
  9993. {
  9994. return new LSL_List(0);
  9995. }
  9996. foreach (object o in param.Data)
  9997. {
  9998. if ((LSL_Integer)o == ScriptBaseClass.PARCEL_DETAILS_NAME)
  9999. ret.Add(new LSL_String(land.Name));
  10000. else if ((LSL_Integer)o == ScriptBaseClass.PARCEL_DETAILS_DESC)
  10001. ret.Add(new LSL_String(land.Description));
  10002. else if ((LSL_Integer)o == ScriptBaseClass.PARCEL_DETAILS_OWNER)
  10003. ret.Add(new LSL_Key(land.OwnerID.ToString()));
  10004. else if ((LSL_Integer)o == ScriptBaseClass.PARCEL_DETAILS_GROUP)
  10005. ret.Add(new LSL_Key(land.GroupID.ToString()));
  10006. else if ((LSL_Integer)o == ScriptBaseClass.PARCEL_DETAILS_AREA)
  10007. ret.Add(new LSL_Integer(land.Area));
  10008. else if ((LSL_Integer)o == ScriptBaseClass.PARCEL_DETAILS_ID)
  10009. //Returning the InfoUUID so that we can use this for landmarks outside of this region
  10010. // http://wiki.secondlife.com/wiki/PARCEL_DETAILS_ID
  10011. ret.Add(new LSL_Key(land.InfoUUID.ToString()));
  10012. else if ((LSL_Integer)o == ScriptBaseClass.PARCEL_DETAILS_PRIVACY)
  10013. ret.Add(new LSL_Integer(land.Private ? 1 : 0));
  10014. else
  10015. ret.Add(new LSL_Integer(0));
  10016. }
  10017. }
  10018. return ret;
  10019. }
  10020. public LSL_String llStringTrim(string src, int type)
  10021. {
  10022. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  10023. if (type == (int)ScriptBaseClass.STRING_TRIM_HEAD) { return src.TrimStart(); }
  10024. if (type == (int)ScriptBaseClass.STRING_TRIM_TAIL) { return src.TrimEnd(); }
  10025. if (type == (int)ScriptBaseClass.STRING_TRIM) { return src.Trim(); }
  10026. return src;
  10027. }
  10028. public LSL_List llGetObjectDetails(string id, LSL_List args)
  10029. {
  10030. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_List();
  10031. LSL_List ret = new LSL_List();
  10032. UUID key = new UUID();
  10033. if (UUID.TryParse(id, out key))
  10034. {
  10035. IScenePresence av = World.GetScenePresence(key);
  10036. if (av != null)
  10037. {
  10038. foreach (object o in args.Data)
  10039. {
  10040. if ((LSL_Integer)o == ScriptBaseClass.OBJECT_NAME)
  10041. {
  10042. ret.Add(new LSL_String(av.Name));
  10043. }
  10044. else if ((LSL_Integer)o == ScriptBaseClass.OBJECT_DESC)
  10045. {
  10046. ret.Add(new LSL_String(""));
  10047. }
  10048. else if ((LSL_Integer)o == ScriptBaseClass.OBJECT_POS)
  10049. {
  10050. Vector3 tmp = av.AbsolutePosition;
  10051. ret.Add(new LSL_Vector(tmp.X, tmp.Y, tmp.Z));
  10052. }
  10053. else if ((LSL_Integer)o == ScriptBaseClass.OBJECT_ROT)
  10054. {
  10055. Quaternion rtmp = av.Rotation;
  10056. ret.Add(new LSL_Rotation(rtmp.X, rtmp.Y, rtmp.Z, rtmp.W));
  10057. }
  10058. else if ((LSL_Integer)o == ScriptBaseClass.OBJECT_VELOCITY)
  10059. {
  10060. Vector3 tmp = av.Velocity;
  10061. ret.Add(new LSL_Vector(tmp.X, tmp.Y, tmp.Z));
  10062. }
  10063. else if ((LSL_Integer)o == ScriptBaseClass.OBJECT_OWNER)
  10064. {
  10065. ret.Add(id);
  10066. }
  10067. else if ((LSL_Integer)o == ScriptBaseClass.OBJECT_GROUP)
  10068. {
  10069. ret.Add(UUID.Zero.ToString());
  10070. }
  10071. else if ((LSL_Integer)o == ScriptBaseClass.OBJECT_CREATOR)
  10072. {
  10073. ret.Add(UUID.Zero.ToString());
  10074. }
  10075. else if ((LSL_Integer)o == ScriptBaseClass.OBJECT_RUNNING_SCRIPT_COUNT)
  10076. {
  10077. IScriptModule[] modules = World.RequestModuleInterfaces<IScriptModule>();
  10078. #if (!ISWIN)
  10079. int activeScripts = 0;
  10080. foreach (IScriptModule mod in modules)
  10081. activeScripts += mod.GetActiveScripts(av);
  10082. #else
  10083. int activeScripts = modules.Sum(mod => mod.GetActiveScripts(av));
  10084. #endif
  10085. ret.Add(activeScripts);
  10086. }
  10087. else if ((LSL_Integer)o == ScriptBaseClass.OBJECT_TOTAL_SCRIPT_COUNT)
  10088. {
  10089. IScriptModule[] modules = World.RequestModuleInterfaces<IScriptModule>();
  10090. #if (!ISWIN)
  10091. int totalScripts = 0;
  10092. foreach (IScriptModule mod in modules)
  10093. totalScripts += mod.GetTotalScripts(av);
  10094. #else
  10095. int totalScripts = modules.Sum(mod => mod.GetTotalScripts(av));
  10096. #endif
  10097. ret.Add(totalScripts);
  10098. }
  10099. else if ((LSL_Integer)o == ScriptBaseClass.OBJECT_SCRIPT_MEMORY)
  10100. {
  10101. ret.Add(0);
  10102. }
  10103. else if ((LSL_Integer)o == ScriptBaseClass.OBJECT_SCRIPT_TIME)
  10104. {
  10105. IScriptModule[] modules = World.RequestModuleInterfaces<IScriptModule>();
  10106. #if (!ISWIN)
  10107. int scriptTime = 0;
  10108. foreach (IScriptModule mod in modules)
  10109. scriptTime += mod.GetScriptTime(m_itemID);
  10110. #else
  10111. int scriptTime = modules.Sum(mod => mod.GetScriptTime(m_itemID));
  10112. #endif
  10113. ret.Add(scriptTime);
  10114. }
  10115. else if ((LSL_Integer)o == ScriptBaseClass.OBJECT_PRIM_EQUIVALENCE)
  10116. {
  10117. ret.Add(0);
  10118. }
  10119. else if ((LSL_Integer)o == ScriptBaseClass.OBJECT_SERVER_COST)
  10120. {
  10121. ret.Add(0);
  10122. }
  10123. else if ((LSL_Integer)o == ScriptBaseClass.OBJECT_STREAMING_COST)
  10124. {
  10125. ret.Add(0);
  10126. }
  10127. else if ((LSL_Integer)o == ScriptBaseClass.OBJECT_PHYSICS_COST)
  10128. {
  10129. ret.Add(0);
  10130. }
  10131. else if ((LSL_Integer)o == ScriptBaseClass.OBJECT_CHARACTER_TIME)
  10132. {
  10133. ret.Add(0);
  10134. }
  10135. else if ((LSL_Integer)o == ScriptBaseClass.OBJECT_ROOT)
  10136. {
  10137. ret.Add(av.Sitting ? av.SittingOnUUID : av.UUID);
  10138. }
  10139. else if ((LSL_Integer)o == ScriptBaseClass.OBJECT_ATTACHED_POINT)
  10140. {
  10141. ret.Add(0);