PageRenderTime 53ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 3ms

/Aurora/AuroraDotNetEngine/APIs/LSL_Api.cs

https://bitbucket.org/VirtualReality/software-testing
C# | 11705 lines | 8971 code | 1635 blank | 1099 comment | 2545 complexity | d910892bba07447d3b6e84bd58f4441b 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 Aurora.Framework;
  28. using Aurora.Framework.ClientInterfaces;
  29. using Aurora.Framework.ConsoleFramework;
  30. using Aurora.Framework.DatabaseInterfaces;
  31. using Aurora.Framework.Modules;
  32. using Aurora.Framework.Physics;
  33. using Aurora.Framework.PresenceInfo;
  34. using Aurora.Framework.SceneInfo;
  35. using Aurora.Framework.SceneInfo.Entities;
  36. using Aurora.Framework.Serialization;
  37. using Aurora.Framework.Servers;
  38. using Aurora.Framework.Services;
  39. using Aurora.Framework.Services.ClassHelpers.Assets;
  40. using Aurora.Framework.Services.ClassHelpers.Inventory;
  41. using Aurora.Framework.Services.ClassHelpers.Profile;
  42. using Aurora.Framework.Utilities;
  43. using Aurora.ScriptEngine.AuroraDotNetEngine.APIs.Interfaces;
  44. using Aurora.ScriptEngine.AuroraDotNetEngine.Plugins;
  45. using Aurora.ScriptEngine.AuroraDotNetEngine.Runtime;
  46. using Nini.Config;
  47. using OpenMetaverse;
  48. using OpenMetaverse.Packets;
  49. using System;
  50. using System.Collections;
  51. using System.Collections.Generic;
  52. using System.Linq;
  53. using System.Runtime.Remoting.Lifetime;
  54. using System.Text;
  55. using System.Text.RegularExpressions;
  56. using System.Threading;
  57. using GridRegion = Aurora.Framework.Services.GridRegion;
  58. using LSL_Float = Aurora.ScriptEngine.AuroraDotNetEngine.LSL_Types.LSLFloat;
  59. using LSL_Integer = Aurora.ScriptEngine.AuroraDotNetEngine.LSL_Types.LSLInteger;
  60. using LSL_Key = Aurora.ScriptEngine.AuroraDotNetEngine.LSL_Types.LSLString;
  61. using LSL_List = Aurora.ScriptEngine.AuroraDotNetEngine.LSL_Types.list;
  62. using LSL_Rotation = Aurora.ScriptEngine.AuroraDotNetEngine.LSL_Types.Quaternion;
  63. using LSL_String = Aurora.ScriptEngine.AuroraDotNetEngine.LSL_Types.LSLString;
  64. using LSL_Vector = Aurora.ScriptEngine.AuroraDotNetEngine.LSL_Types.Vector3;
  65. using PrimType = Aurora.Framework.SceneInfo.PrimType;
  66. using RegionFlags = Aurora.Framework.Services.RegionFlags;
  67. namespace Aurora.ScriptEngine.AuroraDotNetEngine.APIs
  68. {
  69. /// <summary>
  70. /// Contains all LSL ll-functions. This class will be in Default AppDomain.
  71. /// </summary>
  72. [Serializable]
  73. public class LSL_Api : MarshalByRefObject, ILSL_Api, IScriptApi
  74. {
  75. protected IScriptModulePlugin m_ScriptEngine;
  76. protected ISceneChildEntity m_host;
  77. protected uint m_localID;
  78. protected UUID m_itemID;
  79. protected bool throwErrorOnNotImplemented = true;
  80. protected float m_ScriptDelayFactor = 1.0f;
  81. protected float m_ScriptDistanceFactor = 1.0f;
  82. protected float m_MinTimerInterval = 0.1f;
  83. protected DateTime m_timer = DateTime.Now;
  84. protected bool m_waitingForScriptAnswer = false;
  85. protected bool m_automaticLinkPermission = false;
  86. protected IMessageTransferModule m_TransferModule = null;
  87. protected int m_notecardLineReadCharsMax = 255;
  88. protected int m_scriptConsoleChannel = 0;
  89. protected bool m_scriptConsoleChannelEnabled = false;
  90. protected IUrlModule m_UrlModule = null;
  91. internal ScriptProtectionModule ScriptProtection;
  92. protected IWorldComm m_comms = null;
  93. // MUST be a ref type
  94. public class UserInfoCacheEntry
  95. {
  96. public int time;
  97. public UserAccount account;
  98. public UserInfo pinfo;
  99. }
  100. protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache =
  101. new Dictionary<UUID, UserInfoCacheEntry>();
  102. public void Initialize(IScriptModulePlugin ScriptEngine, ISceneChildEntity host, uint localID, UUID itemID,
  103. ScriptProtectionModule module)
  104. {
  105. m_ScriptEngine = ScriptEngine;
  106. m_host = host;
  107. m_localID = localID;
  108. m_itemID = itemID;
  109. ScriptProtection = module;
  110. m_ScriptDelayFactor =
  111. m_ScriptEngine.Config.GetFloat("ScriptDelayFactor", 1.0f);
  112. m_ScriptDistanceFactor =
  113. m_ScriptEngine.Config.GetFloat("ScriptDistanceLimitFactor", 1.0f);
  114. m_MinTimerInterval =
  115. m_ScriptEngine.Config.GetFloat("MinTimerInterval", 0.5f);
  116. m_automaticLinkPermission =
  117. m_ScriptEngine.Config.GetBoolean("AutomaticLinkPermission", false);
  118. m_notecardLineReadCharsMax =
  119. m_ScriptEngine.Config.GetInt("NotecardLineReadCharsMax", 255);
  120. if (m_notecardLineReadCharsMax > 65535)
  121. m_notecardLineReadCharsMax = 65535;
  122. m_TransferModule =
  123. World.RequestModuleInterface<IMessageTransferModule>();
  124. m_UrlModule = World.RequestModuleInterface<IUrlModule>();
  125. m_comms = World.RequestModuleInterface<IWorldComm>();
  126. }
  127. public IScriptApi Copy()
  128. {
  129. return new LSL_Api();
  130. }
  131. public string Name
  132. {
  133. get { return "ll"; }
  134. }
  135. public string InterfaceName
  136. {
  137. get { return "ILSL_Api"; }
  138. }
  139. /// <summary>
  140. /// We don't have to add any assemblies here
  141. /// </summary>
  142. public string[] ReferencedAssemblies
  143. {
  144. get { return new string[0]; }
  145. }
  146. /// <summary>
  147. /// We use the default namespace, so we don't have any to add
  148. /// </summary>
  149. public string[] NamespaceAdditions
  150. {
  151. get { return new string[0]; }
  152. }
  153. public void Dispose()
  154. {
  155. }
  156. public override Object InitializeLifetimeService()
  157. {
  158. ILease lease = (ILease) base.InitializeLifetimeService();
  159. if (lease != null && lease.CurrentState == LeaseState.Initial)
  160. {
  161. lease.InitialLeaseTime = TimeSpan.FromMinutes(0);
  162. // lease.RenewOnCallTime = TimeSpan.FromSeconds(10.0);
  163. // lease.SponsorshipTimeout = TimeSpan.FromMinutes(1.0);
  164. }
  165. return lease;
  166. }
  167. protected virtual void ScriptSleep(int delay)
  168. {
  169. delay = (int) (delay*m_ScriptDelayFactor);
  170. if (delay == 0)
  171. return;
  172. Thread.Sleep(delay);
  173. }
  174. /// <summary>
  175. /// This is the new sleep implementation that allows for us to not freeze the script thread while we run
  176. /// </summary>
  177. /// <param name="delay"></param>
  178. /// <returns></returns>
  179. protected DateTime PScriptSleep(int delay)
  180. {
  181. double dly = (delay*m_ScriptDelayFactor);
  182. if (dly == 0.0)
  183. return DateTime.Now;
  184. DateTime timeToStopSleeping = DateTime.Now.AddMilliseconds(dly);
  185. return timeToStopSleeping;
  186. }
  187. public IScene World
  188. {
  189. get { return m_host.ParentEntity.Scene; }
  190. }
  191. public void state(string newState)
  192. {
  193. m_ScriptEngine.SetState(m_itemID, newState);
  194. throw new EventAbortException();
  195. }
  196. /// <summary>
  197. /// Reset the named script. The script must be present
  198. /// in the same prim.
  199. /// </summary>
  200. public void llResetScript()
  201. {
  202. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  203. if (m_UrlModule != null)
  204. {
  205. m_UrlModule.ScriptRemoved(m_itemID);
  206. }
  207. m_ScriptEngine.ResetScript(m_host.UUID, m_itemID, true);
  208. }
  209. public void llResetOtherScript(string name)
  210. {
  211. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  212. UUID item;
  213. if ((item = ScriptByName(name)) != UUID.Zero)
  214. m_ScriptEngine.ResetScript(m_host.UUID, item, false);
  215. else
  216. ShoutError("llResetOtherScript: script " + name + " not found");
  217. }
  218. public LSL_Integer llGetScriptState(string name)
  219. {
  220. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  221. return new LSL_Integer();
  222. UUID item;
  223. if ((item = ScriptByName(name)) != UUID.Zero)
  224. {
  225. return m_ScriptEngine.GetScriptRunningState(item) ? 1 : 0;
  226. }
  227. ShoutError("llGetScriptState: script " + name + " not found");
  228. // If we didn't find it, then it's safe to
  229. // assume it is not running.
  230. return 0;
  231. }
  232. public LSL_Key llGenerateKey()
  233. {
  234. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  235. return new LSL_Key();
  236. return UUID.Random().ToString();
  237. }
  238. public void llSetScriptState(string name, int run)
  239. {
  240. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  241. UUID item;
  242. // These functions are supposed to be robust,
  243. // so get the state one step at a time.
  244. if ((item = ScriptByName(name)) != UUID.Zero)
  245. {
  246. m_ScriptEngine.SetScriptRunningState(item, run == 1);
  247. }
  248. else
  249. {
  250. ShoutError("llSetScriptState: script " + name + " not found");
  251. }
  252. }
  253. public List<ISceneChildEntity> GetLinkParts(int linkType)
  254. {
  255. List<ISceneChildEntity> ret = new List<ISceneChildEntity> {m_host};
  256. if (linkType == ScriptBaseClass.LINK_SET)
  257. {
  258. if (m_host.ParentEntity != null)
  259. return new List<ISceneChildEntity>(m_host.ParentEntity.ChildrenEntities());
  260. return ret;
  261. }
  262. if (linkType == ScriptBaseClass.LINK_ROOT)
  263. {
  264. if (m_host.ParentEntity != null)
  265. {
  266. ret = new List<ISceneChildEntity> {m_host.ParentEntity.RootChild};
  267. return ret;
  268. }
  269. return ret;
  270. }
  271. if (linkType == ScriptBaseClass.LINK_ALL_OTHERS)
  272. {
  273. if (m_host.ParentEntity == null)
  274. return new List<ISceneChildEntity>();
  275. ret = new List<ISceneChildEntity>(m_host.ParentEntity.ChildrenEntities());
  276. if (ret.Contains(m_host))
  277. ret.Remove(m_host);
  278. return ret;
  279. }
  280. if (linkType == ScriptBaseClass.LINK_ALL_CHILDREN)
  281. {
  282. if (m_host.ParentEntity == null)
  283. return new List<ISceneChildEntity>();
  284. ret = new List<ISceneChildEntity>(m_host.ParentEntity.ChildrenEntities());
  285. if (ret.Contains(m_host.ParentEntity.RootChild))
  286. ret.Remove(m_host.ParentEntity.RootChild);
  287. return ret;
  288. }
  289. if (linkType == ScriptBaseClass.LINK_THIS)
  290. {
  291. return ret;
  292. }
  293. if (linkType < 0 || m_host.ParentEntity == null)
  294. return new List<ISceneChildEntity>();
  295. IEntity target = m_host.ParentEntity.GetLinkNumPart(linkType);
  296. if (target is ISceneChildEntity)
  297. {
  298. ret = new List<ISceneChildEntity> {target as ISceneChildEntity};
  299. }
  300. //No allowing scene presences to be found here
  301. return ret;
  302. }
  303. public List<IEntity> GetLinkPartsAndEntities(int linkType)
  304. {
  305. List<IEntity> ret = new List<IEntity> {m_host};
  306. if (linkType == ScriptBaseClass.LINK_SET)
  307. {
  308. if (m_host.ParentEntity != null)
  309. {
  310. List<ISceneChildEntity> parts = new List<ISceneChildEntity>(m_host.ParentEntity.ChildrenEntities());
  311. #if (!ISWIN)
  312. return parts.ConvertAll<IEntity>(new Converter<ISceneChildEntity, IEntity>(delegate(ISceneChildEntity part)
  313. {
  314. return (IEntity)part;
  315. }));
  316. #else
  317. return parts.ConvertAll(part => (IEntity) part);
  318. #endif
  319. }
  320. return ret;
  321. }
  322. if (linkType == ScriptBaseClass.LINK_ROOT)
  323. {
  324. if (m_host.ParentEntity != null)
  325. {
  326. ret = new List<IEntity> {m_host.ParentEntity.RootChild};
  327. return ret;
  328. }
  329. return ret;
  330. }
  331. if (linkType == ScriptBaseClass.LINK_ALL_OTHERS)
  332. {
  333. if (m_host.ParentEntity == null)
  334. return new List<IEntity>();
  335. List<ISceneChildEntity> sceneobjectparts =
  336. new List<ISceneChildEntity>(m_host.ParentEntity.ChildrenEntities());
  337. #if (!ISWIN)
  338. ret = sceneobjectparts.ConvertAll<IEntity>(new Converter<ISceneChildEntity, IEntity>(delegate(ISceneChildEntity part)
  339. {
  340. return (IEntity)part;
  341. }));
  342. #else
  343. ret = sceneobjectparts.ConvertAll(part => (IEntity) part);
  344. #endif
  345. if (ret.Contains(m_host))
  346. ret.Remove(m_host);
  347. return ret;
  348. }
  349. if (linkType == ScriptBaseClass.LINK_ALL_CHILDREN)
  350. {
  351. if (m_host.ParentEntity == null)
  352. return new List<IEntity>();
  353. List<ISceneChildEntity> children = new List<ISceneChildEntity>(m_host.ParentEntity.ChildrenEntities());
  354. #if (!ISWIN)
  355. ret = children.ConvertAll<IEntity>(new Converter<ISceneChildEntity, IEntity>(delegate(ISceneChildEntity part)
  356. {
  357. return (IEntity)part;
  358. }));
  359. #else
  360. ret = children.ConvertAll(part => (IEntity) part);
  361. #endif
  362. if (ret.Contains(m_host.ParentEntity.RootChild))
  363. ret.Remove(m_host.ParentEntity.RootChild);
  364. return ret;
  365. }
  366. if (linkType == ScriptBaseClass.LINK_THIS)
  367. {
  368. return ret;
  369. }
  370. if (linkType < 0 || m_host.ParentEntity == null)
  371. return new List<IEntity>();
  372. IEntity target = m_host.ParentEntity.GetLinkNumPart(linkType);
  373. if (target == null)
  374. return new List<IEntity>();
  375. ret = new List<IEntity> {target};
  376. return ret;
  377. }
  378. protected UUID InventorySelf()
  379. {
  380. UUID invItemID = new UUID();
  381. lock (m_host.TaskInventory)
  382. {
  383. foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
  384. {
  385. if (inv.Value.Type == 10 && inv.Value.ItemID == m_itemID)
  386. {
  387. invItemID = inv.Key;
  388. break;
  389. }
  390. }
  391. }
  392. return invItemID;
  393. }
  394. protected UUID InventoryKey(string name, int type)
  395. {
  396. lock (m_host.TaskInventory)
  397. {
  398. foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
  399. {
  400. if (inv.Value.Name == name)
  401. {
  402. if (inv.Value.Type != type)
  403. return UUID.Zero;
  404. return inv.Value.AssetID;
  405. }
  406. }
  407. }
  408. return UUID.Zero;
  409. }
  410. protected UUID InventoryKey(string name, bool throwExceptionIfDoesNotExist)
  411. {
  412. lock (m_host.TaskInventory)
  413. {
  414. foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
  415. {
  416. if (inv.Value.Name == name)
  417. {
  418. return inv.Value.AssetID;
  419. }
  420. }
  421. }
  422. if (throwExceptionIfDoesNotExist)
  423. {
  424. IChatModule chatModule = World.RequestModuleInterface<IChatModule>();
  425. if (chatModule != null)
  426. chatModule.SimChat("Could not find sound '" + name + "'.",
  427. ChatTypeEnum.DebugChannel, 2147483647, m_host.AbsolutePosition,
  428. m_host.Name, m_host.UUID, false, World);
  429. }
  430. return UUID.Zero;
  431. }
  432. /// <summary>
  433. /// accepts a valid UUID, -or- a name of an inventory item.
  434. /// Returns a valid UUID or UUID.Zero if key invalid and item not found
  435. /// in prim inventory.
  436. /// </summary>
  437. /// <param name="k"></param>
  438. /// <param name="throwExceptionIfDoesNotExist"></param>
  439. /// <returns></returns>
  440. protected UUID KeyOrName(string k, bool throwExceptionIfDoesNotExist)
  441. {
  442. UUID key = UUID.Zero;
  443. // if we can parse the string as a key, use it.
  444. if (UUID.TryParse(k, out key))
  445. {
  446. return key;
  447. }
  448. // else try to locate the name in inventory of object. found returns key,
  449. // not found returns UUID.Zero which will translate to the default particle texture
  450. return InventoryKey(k, throwExceptionIfDoesNotExist);
  451. }
  452. // convert a LSL_Rotation to a Quaternion
  453. protected Quaternion Rot2Quaternion(LSL_Rotation r)
  454. {
  455. Quaternion q = new Quaternion((float) r.x, (float) r.y, (float) r.z, (float) r.s);
  456. q.Normalize();
  457. return q;
  458. }
  459. //These are the implementations of the various ll-functions used by the LSL scripts.
  460. public LSL_Float llSin(double f)
  461. {
  462. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  463. return new LSL_Float();
  464. return Math.Sin(f);
  465. }
  466. public LSL_Float llCos(double f)
  467. {
  468. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  469. return new LSL_Float();
  470. return Math.Cos(f);
  471. }
  472. public LSL_Float llTan(double f)
  473. {
  474. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  475. return new LSL_Float();
  476. return Math.Tan(f);
  477. }
  478. public LSL_Float llAtan2(double x, double y)
  479. {
  480. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  481. return new LSL_Float();
  482. return Math.Atan2(x, y);
  483. }
  484. public LSL_Float llSqrt(double f)
  485. {
  486. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  487. return new LSL_Float();
  488. return Math.Sqrt(f);
  489. }
  490. public LSL_Float llPow(double fbase, double fexponent)
  491. {
  492. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  493. return new LSL_Float();
  494. return Math.Pow(fbase, fexponent);
  495. }
  496. public LSL_Integer llAbs(int i)
  497. {
  498. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  499. return new LSL_Integer();
  500. // changed to replicate LSL behaviour whereby minimum int value is returned untouched.
  501. if (i == Int32.MinValue)
  502. return i;
  503. return Math.Abs(i);
  504. }
  505. public LSL_Float llFabs(double f)
  506. {
  507. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  508. return new LSL_Float();
  509. return Math.Abs(f);
  510. }
  511. public LSL_Float llFrand(double mag)
  512. {
  513. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  514. return new LSL_Float();
  515. lock (Util.RandomClass)
  516. {
  517. return Util.RandomClass.NextDouble()*mag;
  518. }
  519. }
  520. public LSL_Integer llFloor(double f)
  521. {
  522. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  523. return new LSL_Integer();
  524. return (int) Math.Floor(f);
  525. }
  526. public LSL_Integer llCeil(double f)
  527. {
  528. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  529. return new LSL_Integer();
  530. return (int) Math.Ceiling(f);
  531. }
  532. // Xantor 01/May/2008 fixed midpointrounding (2.5 becomes 3.0 instead of 2.0, default = ToEven)
  533. public LSL_Integer llRound(double f)
  534. {
  535. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  536. return new LSL_Integer();
  537. double RoundedNumber = Math.Round(f, MidpointRounding.AwayFromZero);
  538. //Attempt to fix rounded numbers like -4.5 arounding away from zero
  539. if (f < 0)
  540. {
  541. if (f + 0.5 == RoundedNumber || f - 0.5 == RoundedNumber)
  542. {
  543. RoundedNumber += 1;
  544. }
  545. }
  546. return (int) RoundedNumber;
  547. }
  548. //This next group are vector operations involving squaring and square root. ckrinke
  549. public LSL_Float llVecMag(LSL_Vector v)
  550. {
  551. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  552. return new LSL_Float();
  553. return LSL_Vector.Mag(v);
  554. }
  555. public LSL_Vector llVecNorm(LSL_Vector v)
  556. {
  557. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  558. return new LSL_Vector();
  559. return LSL_Vector.Norm(v);
  560. }
  561. public LSL_Float llVecDist(LSL_Vector a, LSL_Vector b)
  562. {
  563. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  564. return new LSL_Float();
  565. double dx = a.x - b.x;
  566. double dy = a.y - b.y;
  567. double dz = a.z - b.z;
  568. return Math.Sqrt(dx*dx + dy*dy + dz*dz);
  569. }
  570. //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke
  571. // Old implementation of llRot2Euler. Normalization not required as Atan2 function will
  572. // only return values >= -PI (-180 degrees) and <= PI (180 degrees).
  573. public LSL_Vector llRot2Euler(LSL_Rotation r)
  574. {
  575. //This implementation is from http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions. ckrinke
  576. LSL_Rotation t = new LSL_Rotation(r.x*r.x, r.y*r.y, r.z*r.z, r.s*r.s);
  577. double m = (t.x + t.y + t.z + t.s);
  578. if (m == 0) return new LSL_Vector();
  579. double n = 2*(r.y*r.s + r.x*r.z);
  580. double p = m*m - n*n;
  581. if (p > 0)
  582. return new LSL_Vector(Math.Atan2(2.0*(r.x*r.s - r.y*r.z), (-t.x - t.y + t.z + t.s)),
  583. Math.Atan2(n, Math.Sqrt(p)),
  584. Math.Atan2(2.0*(r.z*r.s - r.x*r.y), (t.x - t.y - t.z + t.s)));
  585. if (n > 0)
  586. 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));
  587. 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));
  588. }
  589. /* From wiki:
  590. The Euler angle vector (in radians) is converted to a rotation by doing the rotations around the 3 axes
  591. in Z, Y, X order. So llEuler2Rot(<1.0, 2.0, 3.0> * DEG_TO_RAD) generates a rotation by taking the zero rotation,
  592. a vector pointing along the X axis, first rotating it 3 degrees around the global Z axis, then rotating the resulting
  593. vector 2 degrees around the global Y axis, and finally rotating that 1 degree around the global X axis.
  594. */
  595. /* How we arrived at this llEuler2Rot
  596. *
  597. * Experiment in SL to determine conventions:
  598. * llEuler2Rot(<PI,0,0>)=<1,0,0,0>
  599. * llEuler2Rot(<0,PI,0>)=<0,1,0,0>
  600. * llEuler2Rot(<0,0,PI>)=<0,0,1,0>
  601. *
  602. * Important facts about Quaternions
  603. * - multiplication is non-commutative (a*b != b*a)
  604. * - http://en.wikipedia.org/wiki/Quaternion#Basis_multiplication
  605. *
  606. * Above SL experiment gives (c1,c2,c3,s1,s2,s3 as defined in our llEuler2Rot):
  607. * Qx = c1+i*s1
  608. * Qy = c2+j*s2;
  609. * Qz = c3+k*s3;
  610. *
  611. * Rotations applied in order (from above) Z, Y, X
  612. * Q = (Qz * Qy) * Qx
  613. * ((c1+i*s1)*(c2+j*s2))*(c3+k*s3)
  614. * (c1*c2+i*s1*c2+j*c1*s2+ij*s1*s2)*(c3+k*s3)
  615. * (c1*c2+i*s1*c2+j*c1*s2+k*s1*s2)*(c3+k*s3)
  616. * 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
  617. * 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
  618. * regroup: x=i*(s1*c2*c3+c1*s2*s3)
  619. * y=j*(c1*s2*c3-s1*c2*s3)
  620. * z=k*(s1*s2*c3+c1*c2*s3)
  621. * s= c1*c2*c3-s1*s2*s3
  622. *
  623. * This implementation agrees with the functions found here:
  624. * http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions
  625. * And with the results in SL.
  626. *
  627. * It's also possible to calculate llEuler2Rot by direct multiplication of
  628. * the Qz, Qy, and Qx vectors (as above - and done in the "accurate" function
  629. * from the wiki).
  630. * Apparently in some cases this is better from a numerical precision perspective?
  631. */
  632. public LSL_Rotation llEuler2Rot(LSL_Vector v)
  633. {
  634. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  635. return new LSL_Rotation();
  636. double c1 = Math.Cos(v.x*0.5);
  637. double c2 = Math.Cos(v.y*0.5);
  638. double c3 = Math.Cos(v.z*0.5);
  639. double s1 = Math.Sin(v.x*0.5);
  640. double s2 = Math.Sin(v.y*0.5);
  641. double s3 = Math.Sin(v.z*0.5);
  642. double x = s1*c2*c3 + c1*s2*s3;
  643. double y = c1*s2*c3 - s1*c2*s3;
  644. double z = s1*s2*c3 + c1*c2*s3;
  645. double s = c1*c2*c3 - s1*s2*s3;
  646. return new LSL_Rotation(x, y, z, s);
  647. }
  648. public LSL_Rotation llAxes2Rot(LSL_Vector fwd, LSL_Vector left, LSL_Vector up)
  649. {
  650. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  651. return new LSL_Rotation();
  652. double s;
  653. double tr = fwd.x + left.y + up.z + 1.0;
  654. if (tr >= 1.0)
  655. {
  656. s = 0.5/Math.Sqrt(tr);
  657. return new LSL_Rotation(
  658. (left.z - up.y)*s,
  659. (up.x - fwd.z)*s,
  660. (fwd.y - left.x)*s,
  661. 0.25/s);
  662. }
  663. double max = (left.y > up.z) ? left.y : up.z;
  664. if (max < fwd.x)
  665. {
  666. s = Math.Sqrt(fwd.x - (left.y + up.z) + 1.0);
  667. double x = s*0.5;
  668. s = 0.5/s;
  669. return new LSL_Rotation(
  670. x,
  671. (fwd.y + left.x)*s,
  672. (up.x + fwd.z)*s,
  673. (left.z - up.y)*s);
  674. }
  675. if (max == left.y)
  676. {
  677. s = Math.Sqrt(left.y - (up.z + fwd.x) + 1.0);
  678. double y = s*0.5;
  679. s = 0.5/s;
  680. return new LSL_Rotation(
  681. (fwd.y + left.x)*s,
  682. y,
  683. (left.z + up.y)*s,
  684. (up.x - fwd.z)*s);
  685. }
  686. s = Math.Sqrt(up.z - (fwd.x + left.y) + 1.0);
  687. double z = s*0.5;
  688. s = 0.5/s;
  689. return new LSL_Rotation(
  690. (up.x + fwd.z)*s,
  691. (left.z + up.y)*s,
  692. z,
  693. (fwd.y - left.x)*s);
  694. }
  695. public LSL_Vector llRot2Fwd(LSL_Rotation r)
  696. {
  697. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  698. return new LSL_Vector();
  699. double m = r.x*r.x + r.y*r.y + r.z*r.z + r.s*r.s;
  700. // m is always greater than zero
  701. // if m is not equal to 1 then Rotation needs to be normalized
  702. if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision
  703. {
  704. m = 1.0/Math.Sqrt(m);
  705. r.x *= m;
  706. r.y *= m;
  707. r.z *= m;
  708. r.s *= m;
  709. }
  710. // Fast Algebric Calculations instead of Vectors & Quaternions Product
  711. double x = r.x*r.x - r.y*r.y - r.z*r.z + r.s*r.s;
  712. double y = 2*(r.x*r.y + r.z*r.s);
  713. double z = 2*(r.x*r.z - r.y*r.s);
  714. return (new LSL_Vector(x, y, z));
  715. }
  716. public LSL_Vector llRot2Left(LSL_Rotation r)
  717. {
  718. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  719. return new LSL_Vector();
  720. double m = r.x*r.x + r.y*r.y + r.z*r.z + r.s*r.s;
  721. // m is always greater than zero
  722. // if m is not equal to 1 then Rotation needs to be normalized
  723. if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision
  724. {
  725. m = 1.0/Math.Sqrt(m);
  726. r.x *= m;
  727. r.y *= m;
  728. r.z *= m;
  729. r.s *= m;
  730. }
  731. // Fast Algebric Calculations instead of Vectors & Quaternions Product
  732. double x = 2*(r.x*r.y - r.z*r.s);
  733. double y = -r.x*r.x + r.y*r.y - r.z*r.z + r.s*r.s;
  734. double z = 2*(r.x*r.s + r.y*r.z);
  735. return (new LSL_Vector(x, y, z));
  736. }
  737. public LSL_Vector llRot2Up(LSL_Rotation r)
  738. {
  739. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  740. return new LSL_Vector();
  741. double m = r.x*r.x + r.y*r.y + r.z*r.z + r.s*r.s;
  742. // m is always greater than zero
  743. // if m is not equal to 1 then Rotation needs to be normalized
  744. if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision
  745. {
  746. m = 1.0/Math.Sqrt(m);
  747. r.x *= m;
  748. r.y *= m;
  749. r.z *= m;
  750. r.s *= m;
  751. }
  752. // Fast Algebric Calculations instead of Vectors & Quaternions Product
  753. double x = 2*(r.x*r.z + r.y*r.s);
  754. double y = 2*(-r.x*r.s + r.y*r.z);
  755. double z = -r.x*r.x - r.y*r.y + r.z*r.z + r.s*r.s;
  756. return (new LSL_Vector(x, y, z));
  757. }
  758. public LSL_Rotation llRotBetween(LSL_Vector a, LSL_Vector b)
  759. {
  760. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  761. return new LSL_Rotation();
  762. //A and B should both be normalized
  763. LSL_Rotation rotBetween;
  764. // Check for zero vectors. If either is zero, return zero rotation. Otherwise,
  765. // continue calculation.
  766. if (a == new LSL_Vector(0.0f, 0.0f, 0.0f) || b == new LSL_Vector(0.0f, 0.0f, 0.0f))
  767. {
  768. rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
  769. }
  770. else
  771. {
  772. a = LSL_Vector.Norm(a);
  773. b = LSL_Vector.Norm(b);
  774. double dotProduct = LSL_Vector.Dot(a, b);
  775. // There are two degenerate cases possible. These are for vectors 180 or
  776. // 0 degrees apart. These have to be detected and handled individually.
  777. //
  778. // Check for vectors 180 degrees apart.
  779. // A dot product of -1 would mean the angle between vectors is 180 degrees.
  780. if (dotProduct < -0.9999999f)
  781. {
  782. // First assume X axis is orthogonal to the vectors.
  783. LSL_Vector orthoVector = new LSL_Vector(1.0f, 0.0f, 0.0f);
  784. orthoVector = orthoVector - a*(a.x/LSL_Vector.Dot(a, a));
  785. // Check for near zero vector. A very small non-zero number here will create
  786. // a rotation in an undesired direction.
  787. rotBetween = LSL_Vector.Mag(orthoVector) > 0.0001
  788. ? new LSL_Rotation(orthoVector.x, orthoVector.y, orthoVector.z, 0.0f)
  789. : new LSL_Rotation(0.0f, 0.0f, 1.0f, 0.0f);
  790. }
  791. // Check for parallel vectors.
  792. // A dot product of 1 would mean the angle between vectors is 0 degrees.
  793. else if (dotProduct > 0.9999999f)
  794. {
  795. // Set zero rotation.
  796. rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
  797. }
  798. else
  799. {
  800. // All special checks have been performed so get the axis of rotation.
  801. LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
  802. // Quarternion s value is the length of the unit vector + dot product.
  803. double qs = 1.0 + dotProduct;
  804. rotBetween = new LSL_Rotation(crossProduct.x, crossProduct.y, crossProduct.z, qs);
  805. // Normalize the rotation.
  806. double mag = LSL_Rotation.Mag(rotBetween);
  807. // We shouldn't have to worry about a divide by zero here. The qs value will be
  808. // non-zero because we already know if we're here, then the dotProduct is not -1 so
  809. // qs will not be zero. Also, we've already handled the input vectors being zero so the
  810. // crossProduct vector should also not be zero.
  811. rotBetween.x = rotBetween.x/mag;
  812. rotBetween.y = rotBetween.y/mag;
  813. rotBetween.z = rotBetween.z/mag;
  814. rotBetween.s = rotBetween.s/mag;
  815. // Check for undefined values and set zero rotation if any found. This code might not actually be required
  816. // any longer since zero vectors are checked for at the top.
  817. if (Double.IsNaN(rotBetween.x) || Double.IsNaN(rotBetween.y) || Double.IsNaN(rotBetween.z) ||
  818. Double.IsNaN(rotBetween.s))
  819. {
  820. rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
  821. }
  822. }
  823. }
  824. return rotBetween;
  825. }
  826. public void llWhisper(int channelID, string text)
  827. {
  828. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  829. if (text.Length > 1023)
  830. text = text.Substring(0, 1023);
  831. IChatModule chatModule = World.RequestModuleInterface<IChatModule>();
  832. if (chatModule != null)
  833. chatModule.SimChat(text, ChatTypeEnum.Whisper, channelID,
  834. m_host.ParentEntity.RootChild.AbsolutePosition, m_host.Name, m_host.UUID, false,
  835. World);
  836. if (m_comms != null)
  837. m_comms.DeliverMessage(ChatTypeEnum.Whisper, channelID, m_host.Name, m_host.UUID, text);
  838. }
  839. public void llSay(int channelID, object m_text)
  840. {
  841. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  842. string text = m_text.ToString();
  843. if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel))
  844. {
  845. MainConsole.Instance.Debug(text);
  846. }
  847. else
  848. {
  849. if (text.Length > 1023)
  850. text = text.Substring(0, 1023);
  851. IChatModule chatModule = World.RequestModuleInterface<IChatModule>();
  852. if (chatModule != null)
  853. chatModule.SimChat(text, ChatTypeEnum.Say, channelID,
  854. m_host.ParentEntity.RootChild.AbsolutePosition, m_host.Name, m_host.UUID, false,
  855. World);
  856. if (m_comms != null)
  857. m_comms.DeliverMessage(ChatTypeEnum.Say, channelID, m_host.Name, m_host.UUID, text);
  858. }
  859. }
  860. public void llShout(int channelID, string text)
  861. {
  862. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  863. if (text.Length > 1023)
  864. text = text.Substring(0, 1023);
  865. IChatModule chatModule = World.RequestModuleInterface<IChatModule>();
  866. if (chatModule != null)
  867. chatModule.SimChat(text, ChatTypeEnum.Shout, channelID,
  868. m_host.ParentEntity.RootChild.AbsolutePosition, m_host.Name, m_host.UUID, true, World);
  869. if (m_comms != null)
  870. m_comms.DeliverMessage(ChatTypeEnum.Shout, channelID, m_host.Name, m_host.UUID, text);
  871. }
  872. public void llRegionSay(int channelID, string text)
  873. {
  874. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  875. if (text.Length > 1023)
  876. text = text.Substring(0, 1023);
  877. if (channelID == 0) //0 isn't normally allowed, so check against a higher threat level
  878. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.Moderate, "LSL", m_host, "LSL", m_itemID)) return;
  879. IChatModule chatModule = World.RequestModuleInterface<IChatModule>();
  880. if (chatModule != null)
  881. chatModule.SimChat(text, ChatTypeEnum.Region, channelID,
  882. m_host.ParentEntity.RootChild.AbsolutePosition, m_host.Name, m_host.UUID, false,
  883. World);
  884. if (m_comms != null)
  885. m_comms.DeliverMessage(ChatTypeEnum.Region, channelID, m_host.Name, m_host.UUID, text);
  886. }
  887. public void llRegionSayTo(LSL_Key toID, int channelID, string text)
  888. {
  889. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  890. IChatModule chatModule = World.RequestModuleInterface<IChatModule>();
  891. if (text.Length > 1023)
  892. text = text.Substring(0, 1023);
  893. if (channelID == 0)
  894. {
  895. IScenePresence presence = World.GetScenePresence(UUID.Parse(toID.m_string));
  896. if (presence != null)
  897. {
  898. if (chatModule != null)
  899. chatModule.TrySendChatMessage(presence, m_host.AbsolutePosition, m_host.AbsolutePosition,
  900. m_host.UUID, m_host.Name, ChatTypeEnum.Say, text,
  901. ChatSourceType.Object, 10000);
  902. }
  903. }
  904. if (m_comms != null)
  905. m_comms.DeliverMessage(ChatTypeEnum.Region, channelID, m_host.Name, m_host.UUID,
  906. UUID.Parse(toID.m_string), text);
  907. }
  908. public LSL_Integer llListen(int channelID, string name, string ID, string msg)
  909. {
  910. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  911. return new LSL_Integer();
  912. UUID keyID;
  913. UUID.TryParse(ID, out keyID);
  914. if (m_comms != null)
  915. return m_comms.Listen(m_itemID, m_host.UUID, channelID, name, keyID, msg);
  916. return -1;
  917. }
  918. public void llListenControl(int number, int active)
  919. {
  920. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  921. if (m_comms != null)
  922. m_comms.ListenControl(m_itemID, number, active);
  923. }
  924. public void llListenRemove(int number)
  925. {
  926. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  927. if (m_comms != null)
  928. m_comms.ListenRemove(m_itemID, number);
  929. }
  930. public void llSensor(string name, string id, int type, double range, double arc)
  931. {
  932. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  933. UUID keyID = UUID.Zero;
  934. UUID.TryParse(id, out keyID);
  935. SensorRepeatPlugin sensorPlugin = (SensorRepeatPlugin) m_ScriptEngine.GetScriptPlugin("SensorRepeat");
  936. sensorPlugin.SenseOnce(m_host.UUID, m_itemID, name, keyID, type, range, arc, m_host);
  937. }
  938. public void llSensorRepeat(string name, string id, int type, double range, double arc, double rate)
  939. {
  940. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  941. UUID keyID = UUID.Zero;
  942. UUID.TryParse(id, out keyID);
  943. SensorRepeatPlugin sensorPlugin = (SensorRepeatPlugin) m_ScriptEngine.GetScriptPlugin("SensorRepeat");
  944. sensorPlugin.SetSenseRepeatEvent(m_host.UUID, m_itemID, name, keyID, type, range, arc, rate, m_host);
  945. }
  946. public void llSensorRemove()
  947. {
  948. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  949. SensorRepeatPlugin sensorPlugin = (SensorRepeatPlugin) m_ScriptEngine.GetScriptPlugin("SensorRepeat");
  950. sensorPlugin.RemoveScript(m_host.UUID, m_itemID);
  951. }
  952. public string resolveName(UUID objecUUID)
  953. {
  954. // try avatar username surname
  955. UserAccount account = World.UserAccountService.GetUserAccount(World.RegionInfo.AllScopeIDs, objecUUID);
  956. if (account != null)
  957. return account.Name;
  958. // try an scene object
  959. ISceneChildEntity SOP = World.GetSceneObjectPart(objecUUID);
  960. if (SOP != null)
  961. return SOP.Name;
  962. IEntity SensedObject;
  963. if (!World.Entities.TryGetValue(objecUUID, out SensedObject))
  964. {
  965. IGroupsModule groups = World.RequestModuleInterface<IGroupsModule>();
  966. if (groups != null)
  967. {
  968. GroupRecord gr = groups.GetGroupRecord(objecUUID);
  969. if (gr != null)
  970. return gr.GroupName;
  971. }
  972. return String.Empty;
  973. }
  974. return SensedObject.Name;
  975. }
  976. public LSL_String llDetectedName(int number)
  977. {
  978. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  979. return new LSL_String();
  980. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, number);
  981. if (detectedParams == null)
  982. return String.Empty;
  983. return detectedParams.Name;
  984. }
  985. public LSL_String llDetectedKey(int number)
  986. {
  987. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  988. return new LSL_String();
  989. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, number);
  990. if (detectedParams == null)
  991. return String.Empty;
  992. return detectedParams.Key.ToString();
  993. }
  994. public LSL_String llDetectedOwner(int number)
  995. {
  996. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  997. return new LSL_String();
  998. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, number);
  999. if (detectedParams == null)
  1000. return String.Empty;
  1001. return detectedParams.Owner.ToString();
  1002. }
  1003. public LSL_Integer llDetectedType(int number)
  1004. {
  1005. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  1006. return new LSL_Integer();
  1007. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, number);
  1008. if (detectedParams == null)
  1009. return 0;
  1010. return new LSL_Integer(detectedParams.Type);
  1011. }
  1012. public LSL_Vector llDetectedPos(int number)
  1013. {
  1014. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  1015. return new LSL_Vector();
  1016. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, number);
  1017. if (detectedParams == null)
  1018. return new LSL_Vector();
  1019. return detectedParams.Position;
  1020. }
  1021. public LSL_Vector llDetectedVel(int number)
  1022. {
  1023. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  1024. return new LSL_Vector();
  1025. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, number);
  1026. if (detectedParams == null)
  1027. return new LSL_Vector();
  1028. return detectedParams.Velocity;
  1029. }
  1030. public LSL_Vector llDetectedGrab(int number)
  1031. {
  1032. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  1033. return new LSL_Vector();
  1034. DetectParams parms = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, number);
  1035. if (parms == null)
  1036. return new LSL_Vector(0, 0, 0);
  1037. return parms.OffsetPos;
  1038. }
  1039. public LSL_Rotation llDetectedRot(int number)
  1040. {
  1041. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  1042. return new LSL_Rotation();
  1043. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, number);
  1044. if (detectedParams == null)
  1045. return new LSL_Rotation();
  1046. return detectedParams.Rotation;
  1047. }
  1048. public LSL_Integer llDetectedGroup(int number)
  1049. {
  1050. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  1051. return new LSL_Integer();
  1052. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, number);
  1053. if (detectedParams == null)
  1054. return new LSL_Integer(0);
  1055. if (m_host.GroupID == detectedParams.Group)
  1056. return new LSL_Integer(1);
  1057. return new LSL_Integer(0);
  1058. }
  1059. public LSL_Integer llDetectedLinkNumber(int number)
  1060. {
  1061. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  1062. return new LSL_Integer();
  1063. DetectParams parms = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, number);
  1064. if (parms == null)
  1065. return new LSL_Integer(0);
  1066. return new LSL_Integer(parms.LinkNum);
  1067. }
  1068. /// <summary>
  1069. /// See http://wiki.secondlife.com/wiki/LlDetectedTouchBinormal for details
  1070. /// </summary>
  1071. public LSL_Vector llDetectedTouchBinormal(int index)
  1072. {
  1073. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  1074. return new LSL_Vector();
  1075. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, index);
  1076. if (detectedParams == null)
  1077. return new LSL_Vector();
  1078. return detectedParams.TouchBinormal;
  1079. }
  1080. /// <summary>
  1081. /// See http://wiki.secondlife.com/wiki/LlDetectedTouchFace for details
  1082. /// </summary>
  1083. public LSL_Integer llDetectedTouchFace(int index)
  1084. {
  1085. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  1086. return new LSL_Integer();
  1087. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, index);
  1088. if (detectedParams == null)
  1089. return new LSL_Integer(-1);
  1090. return new LSL_Integer(detectedParams.TouchFace);
  1091. }
  1092. /// <summary>
  1093. /// See http://wiki.secondlife.com/wiki/LlDetectedTouchNormal for details
  1094. /// </summary>
  1095. public LSL_Vector llDetectedTouchNormal(int index)
  1096. {
  1097. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  1098. return new LSL_Vector();
  1099. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, index);
  1100. if (detectedParams == null)
  1101. return new LSL_Vector();
  1102. return detectedParams.TouchNormal;
  1103. }
  1104. /// <summary>
  1105. /// See http://wiki.secondlife.com/wiki/LlDetectedTouchPos for details
  1106. /// </summary>
  1107. public LSL_Vector llDetectedTouchPos(int index)
  1108. {
  1109. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  1110. return new LSL_Vector();
  1111. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, index);
  1112. if (detectedParams == null)
  1113. return new LSL_Vector();
  1114. return detectedParams.TouchPos;
  1115. }
  1116. /// <summary>
  1117. /// See http://wiki.secondlife.com/wiki/LlDetectedTouchST for details
  1118. /// </summary>
  1119. public LSL_Vector llDetectedTouchST(int index)
  1120. {
  1121. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  1122. return new LSL_Vector();
  1123. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, index);
  1124. if (detectedParams == null)
  1125. return new LSL_Vector(-1.0, -1.0, 0.0);
  1126. return detectedParams.TouchST;
  1127. }
  1128. /// <summary>
  1129. /// See http://wiki.secondlife.com/wiki/LlDetectedTouchUV for details
  1130. /// </summary>
  1131. public LSL_Vector llDetectedTouchUV(int index)
  1132. {
  1133. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  1134. return new LSL_Vector();
  1135. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, index);
  1136. if (detectedParams == null)
  1137. return new LSL_Vector(-1.0, -1.0, 0.0);
  1138. return detectedParams.TouchUV;
  1139. }
  1140. public virtual void llDie()
  1141. {
  1142. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  1143. throw new SelfDeleteException();
  1144. }
  1145. public LSL_Float llGround(LSL_Vector offset)
  1146. {
  1147. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  1148. return new LSL_Float();
  1149. Vector3 pos = m_host.GetWorldPosition() + new Vector3((float) offset.x,
  1150. (float) offset.y,
  1151. (float) offset.z);
  1152. //Get the slope normal. This gives us the equation of the plane tangent to the slope.
  1153. LSL_Vector vsn = llGroundNormal(offset);
  1154. ITerrainChannel heightmap = World.RequestModuleInterface<ITerrainChannel>();
  1155. // Clamp to valid position
  1156. if (pos.X < 0)
  1157. pos.X = 0;
  1158. else if (pos.X >= heightmap.Width)
  1159. pos.X = heightmap.Width - 1;
  1160. if (pos.Y < 0)
  1161. pos.Y = 0;
  1162. else if (pos.Y >= heightmap.Height)
  1163. pos.Y = heightmap.Height - 1;
  1164. //Get the height for the integer coordinates from the Heightmap
  1165. float baseheight = heightmap[(int) pos.X, (int) pos.Y];
  1166. //Calculate the difference between the actual coordinates and the integer coordinates
  1167. float xdiff = pos.X - (int) pos.X;
  1168. float ydiff = pos.Y - (int) pos.Y;
  1169. //Use the equation of the tangent plane to adjust the height to account for slope
  1170. return (((vsn.x*xdiff) + (vsn.y*ydiff))/(-1*vsn.z)) + baseheight;
  1171. }
  1172. public LSL_Float llCloud(LSL_Vector offset)
  1173. {
  1174. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  1175. return new LSL_Float();
  1176. float cloudCover = 0f;
  1177. ICloudModule module = World.RequestModuleInterface<ICloudModule>();
  1178. if (module != null)
  1179. {
  1180. Vector3 pos = m_host.GetWorldPosition();
  1181. int x = (int) (pos.X + offset.x);
  1182. int y = (int) (pos.Y + offset.y);
  1183. cloudCover = module.CloudCover(x, y, 0);
  1184. }
  1185. return cloudCover;
  1186. }
  1187. public LSL_Vector llWind(LSL_Vector offset)
  1188. {
  1189. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  1190. return new LSL_Vector();
  1191. LSL_Vector wind = new LSL_Vector(0, 0, 0);
  1192. IWindModule module = World.RequestModuleInterface<IWindModule>();
  1193. if (module != null)
  1194. {
  1195. Vector3 pos = m_host.GetWorldPosition();
  1196. int x = (int) (pos.X + offset.x);
  1197. int y = (int) (pos.Y + offset.y);
  1198. Vector3 windSpeed = module.WindSpeed(x, y, 0);
  1199. wind.x = windSpeed.X;
  1200. wind.y = windSpeed.Y;
  1201. }
  1202. return wind;
  1203. }
  1204. public void llSetStatus(int status, int value)
  1205. {
  1206. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  1207. int statusrotationaxis = 0;
  1208. if ((status & ScriptBaseClass.STATUS_PHYSICS) == ScriptBaseClass.STATUS_PHYSICS)
  1209. {
  1210. if (value != 0)
  1211. {
  1212. ISceneEntity group = m_host.ParentEntity;
  1213. if (group == null)
  1214. return;
  1215. #if (!ISWIN)
  1216. bool allow = true;
  1217. foreach (ISceneChildEntity part in group.ChildrenEntities())
  1218. {
  1219. IOpenRegionSettingsModule WSModule = group.Scene.RequestModuleInterface<IOpenRegionSettingsModule>();
  1220. if (WSModule != null && WSModule.MaximumPhysPrimScale != -1)
  1221. {
  1222. Vector3 tmp = part.Scale;
  1223. if (tmp.X > WSModule.MaximumPhysPrimScale ||
  1224. tmp.Y > WSModule.MaximumPhysPrimScale ||
  1225. tmp.Z > WSModule.MaximumPhysPrimScale)
  1226. {
  1227. allow = false;
  1228. break;
  1229. }
  1230. }
  1231. }
  1232. #else
  1233. bool allow = !(from part in @group.ChildrenEntities()
  1234. let WSModule = @group.Scene.RequestModuleInterface<IOpenRegionSettingsModule>()
  1235. where WSModule != null && WSModule.MaximumPhysPrimScale != -1
  1236. let tmp = part.Scale
  1237. where
  1238. tmp.X > WSModule.MaximumPhysPrimScale || tmp.Y > WSModule.MaximumPhysPrimScale ||
  1239. tmp.Z > WSModule.MaximumPhysPrimScale
  1240. select WSModule).Any();
  1241. #endif
  1242. if (!allow)
  1243. return;
  1244. m_host.ParentEntity.ScriptSetPhysicsStatus(true);
  1245. }
  1246. else
  1247. {
  1248. m_host.ParentEntity.ScriptSetPhysicsStatus(false);
  1249. }
  1250. }
  1251. if ((status & ScriptBaseClass.STATUS_PHANTOM) == ScriptBaseClass.STATUS_PHANTOM)
  1252. {
  1253. m_host.ScriptSetPhantomStatus(value != 0);
  1254. }
  1255. if ((status & ScriptBaseClass.STATUS_CAST_SHADOWS) == ScriptBaseClass.STATUS_CAST_SHADOWS)
  1256. {
  1257. m_host.AddFlag(PrimFlags.CastShadows);
  1258. }
  1259. if ((status & ScriptBaseClass.STATUS_ROTATE_X) == ScriptBaseClass.STATUS_ROTATE_X)
  1260. {
  1261. statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_X;
  1262. }
  1263. if ((status & ScriptBaseClass.STATUS_ROTATE_Y) == ScriptBaseClass.STATUS_ROTATE_Y)
  1264. {
  1265. statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_Y;
  1266. }
  1267. if ((status & ScriptBaseClass.STATUS_ROTATE_Z) == ScriptBaseClass.STATUS_ROTATE_Z)
  1268. {
  1269. statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_Z;
  1270. }
  1271. if ((status & ScriptBaseClass.STATUS_BLOCK_GRAB) == ScriptBaseClass.STATUS_BLOCK_GRAB)
  1272. {
  1273. m_host.SetBlockGrab(value != 0, false);
  1274. }
  1275. if ((status & ScriptBaseClass.STATUS_BLOCK_GRAB_OBJECT) == ScriptBaseClass.STATUS_BLOCK_GRAB_OBJECT)
  1276. {
  1277. m_host.SetBlockGrab(value != 0, true);
  1278. }
  1279. if ((status & ScriptBaseClass.STATUS_DIE_AT_EDGE) == ScriptBaseClass.STATUS_DIE_AT_EDGE)
  1280. {
  1281. m_host.SetDieAtEdge(value != 0);
  1282. }
  1283. if ((status & ScriptBaseClass.STATUS_RETURN_AT_EDGE) == ScriptBaseClass.STATUS_RETURN_AT_EDGE)
  1284. {
  1285. m_host.SetReturnAtEdge(value != 0);
  1286. }
  1287. if ((status & ScriptBaseClass.STATUS_SANDBOX) == ScriptBaseClass.STATUS_SANDBOX)
  1288. {
  1289. m_host.SetStatusSandbox(value != 0);
  1290. }
  1291. if (statusrotationaxis != 0)
  1292. {
  1293. m_host.SetAxisRotation(statusrotationaxis, value);
  1294. }
  1295. }
  1296. public LSL_Integer llGetStatus(int status)
  1297. {
  1298. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  1299. return new LSL_Integer();
  1300. if (status == ScriptBaseClass.STATUS_PHYSICS)
  1301. {
  1302. return (m_host.GetEffectiveObjectFlags() & (uint) PrimFlags.Physics) == (uint) PrimFlags.Physics
  1303. ? new LSL_Integer(1)
  1304. : new LSL_Integer(0);
  1305. }
  1306. if (status == ScriptBaseClass.STATUS_PHANTOM)
  1307. {
  1308. return (m_host.GetEffectiveObjectFlags() & (uint) PrimFlags.Phantom) == (uint) PrimFlags.Phantom
  1309. ? new LSL_Integer(1)
  1310. : new LSL_Integer(0);
  1311. }
  1312. if (status == ScriptBaseClass.STATUS_CAST_SHADOWS)
  1313. {
  1314. if ((m_host.GetEffectiveObjectFlags() & (uint) PrimFlags.CastShadows) == (uint) PrimFlags.CastShadows)
  1315. return new LSL_Integer(1);
  1316. return new LSL_Integer(0);
  1317. }
  1318. if (status == ScriptBaseClass.STATUS_BLOCK_GRAB)
  1319. {
  1320. return m_host.GetBlockGrab(false) ? new LSL_Integer(1) : new LSL_Integer(0);
  1321. }
  1322. if (status == ScriptBaseClass.STATUS_BLOCK_GRAB_OBJECT)
  1323. {
  1324. return m_host.GetBlockGrab(true) ? new LSL_Integer(1) : new LSL_Integer(0);
  1325. }
  1326. if (status == ScriptBaseClass.STATUS_DIE_AT_EDGE)
  1327. {
  1328. return m_host.GetDieAtEdge() ? new LSL_Integer(1) : new LSL_Integer(0);
  1329. }
  1330. if (status == ScriptBaseClass.STATUS_RETURN_AT_EDGE)
  1331. {
  1332. return m_host.GetReturnAtEdge() ? new LSL_Integer(1) : new LSL_Integer(0);
  1333. }
  1334. if (status == ScriptBaseClass.STATUS_ROTATE_X)
  1335. {
  1336. return m_host.GetAxisRotation(2) == 2 ? new LSL_Integer(1) : new LSL_Integer(0);
  1337. }
  1338. if (status == ScriptBaseClass.STATUS_ROTATE_Y)
  1339. {
  1340. return m_host.GetAxisRotation(4) == 4 ? new LSL_Integer(1) : new LSL_Integer(0);
  1341. }
  1342. if (status == ScriptBaseClass.STATUS_ROTATE_Z)
  1343. {
  1344. return m_host.GetAxisRotation(8) == 8 ? new LSL_Integer(1) : new LSL_Integer(0);
  1345. }
  1346. if (status == ScriptBaseClass.STATUS_SANDBOX)
  1347. {
  1348. return m_host.GetStatusSandbox() ? new LSL_Integer(1) : new LSL_Integer(0);
  1349. }
  1350. return new LSL_Integer(0);
  1351. }
  1352. public void llSetScale(LSL_Vector scale)
  1353. {
  1354. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  1355. SetScale(m_host, scale);
  1356. }
  1357. protected void SetScale(ISceneChildEntity part, LSL_Vector scale)
  1358. {
  1359. if (part == null || part.ParentEntity == null || part.ParentEntity.IsDeleted)
  1360. return;
  1361. IOpenRegionSettingsModule WSModule =
  1362. m_host.ParentEntity.Scene.RequestModuleInterface<IOpenRegionSettingsModule>();
  1363. if (WSModule != null)
  1364. {
  1365. if (WSModule.MinimumPrimScale != -1)
  1366. {
  1367. if (scale.x < WSModule.MinimumPrimScale)
  1368. scale.x = WSModule.MinimumPrimScale;
  1369. if (scale.y < WSModule.MinimumPrimScale)
  1370. scale.y = WSModule.MinimumPrimScale;
  1371. if (scale.z < WSModule.MinimumPrimScale)
  1372. scale.z = WSModule.MinimumPrimScale;
  1373. }
  1374. if (part.ParentEntity.RootChild.PhysActor != null && part.ParentEntity.RootChild.PhysActor.IsPhysical &&
  1375. WSModule.MaximumPhysPrimScale != -1)
  1376. {
  1377. if (scale.x > WSModule.MaximumPhysPrimScale)
  1378. scale.x = WSModule.MaximumPhysPrimScale;
  1379. if (scale.y > WSModule.MaximumPhysPrimScale)
  1380. scale.y = WSModule.MaximumPhysPrimScale;
  1381. if (scale.z > WSModule.MaximumPhysPrimScale)
  1382. scale.z = WSModule.MaximumPhysPrimScale;
  1383. }
  1384. if (WSModule.MaximumPrimScale != -1)
  1385. {
  1386. if (scale.x > WSModule.MaximumPrimScale)
  1387. scale.x = WSModule.MaximumPrimScale;
  1388. if (scale.y > WSModule.MaximumPrimScale)
  1389. scale.y = WSModule.MaximumPrimScale;
  1390. if (scale.z > WSModule.MaximumPrimScale)
  1391. scale.z = WSModule.MaximumPrimScale;
  1392. }
  1393. }
  1394. Vector3 tmp = part.Scale;
  1395. tmp.X = (float) scale.x;
  1396. tmp.Y = (float) scale.y;
  1397. tmp.Z = (float) scale.z;
  1398. part.Scale = tmp;
  1399. part.ScheduleUpdate(PrimUpdateFlags.FindBest);
  1400. }
  1401. public LSL_Vector llGetScale()
  1402. {
  1403. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  1404. return new LSL_Vector();
  1405. Vector3 tmp = m_host.Scale;
  1406. return new LSL_Vector(tmp.X, tmp.Y, tmp.Z);
  1407. }
  1408. public void llSetClickAction(int action)
  1409. {
  1410. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  1411. m_host.ClickAction = (byte) action;
  1412. m_host.ScheduleUpdate(PrimUpdateFlags.FindBest);
  1413. }
  1414. public void llSetColor(LSL_Vector color, int face)
  1415. {
  1416. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  1417. m_host.SetFaceColor(new Vector3((float) color.x, (float) color.y, (float) color.z), face);
  1418. }
  1419. public void SetTexGen(ISceneChildEntity part, int face, int style)
  1420. {
  1421. Primitive.TextureEntry tex = part.Shape.Textures;
  1422. MappingType textype = MappingType.Default;
  1423. if (style == (int) ScriptBaseClass.PRIM_TEXGEN_PLANAR)
  1424. textype = MappingType.Planar;
  1425. if (face >= 0 && face < GetNumberOfSides(part))
  1426. {
  1427. tex.CreateFace((uint) face);
  1428. tex.FaceTextures[face].TexMapType = textype;
  1429. part.UpdateTexture(tex, false);
  1430. return;
  1431. }
  1432. if (face == ScriptBaseClass.ALL_SIDES)
  1433. {
  1434. for (uint i = 0; i < GetNumberOfSides(part); i++)
  1435. {
  1436. if (tex.FaceTextures[i] != null)
  1437. {
  1438. tex.FaceTextures[i].TexMapType = textype;
  1439. }
  1440. tex.DefaultTexture.TexMapType = textype;
  1441. }
  1442. part.UpdateTexture(tex, false);
  1443. }
  1444. }
  1445. public void SetGlow(ISceneChildEntity part, int face, float glow)
  1446. {
  1447. Primitive.TextureEntry tex = part.Shape.Textures;
  1448. if (face >= 0 && face < GetNumberOfSides(part))
  1449. {
  1450. tex.CreateFace((uint) face);
  1451. tex.FaceTextures[face].Glow = glow;
  1452. part.UpdateTexture(tex, false);
  1453. return;
  1454. }
  1455. if (face == ScriptBaseClass.ALL_SIDES)
  1456. {
  1457. for (uint i = 0; i < GetNumberOfSides(part); i++)
  1458. {
  1459. if (tex.FaceTextures[i] != null)
  1460. {
  1461. tex.FaceTextures[i].Glow = glow;
  1462. }
  1463. tex.DefaultTexture.Glow = glow;
  1464. }
  1465. part.UpdateTexture(tex, false);
  1466. }
  1467. }
  1468. public void SetShiny(ISceneChildEntity part, int face, int shiny, Bumpiness bump)
  1469. {
  1470. Shininess sval = new Shininess();
  1471. switch (shiny)
  1472. {
  1473. case 0:
  1474. sval = Shininess.None;
  1475. break;
  1476. case 1:
  1477. sval = Shininess.Low;
  1478. break;
  1479. case 2:
  1480. sval = Shininess.Medium;
  1481. break;
  1482. case 3:
  1483. sval = Shininess.High;
  1484. break;
  1485. default:
  1486. sval = Shininess.None;
  1487. break;
  1488. }
  1489. Primitive.TextureEntry tex = part.Shape.Textures;
  1490. if (face >= 0 && face < GetNumberOfSides(part))
  1491. {
  1492. tex.CreateFace((uint) face);
  1493. tex.FaceTextures[face].Shiny = sval;
  1494. tex.FaceTextures[face].Bump = bump;
  1495. part.UpdateTexture(tex, false);
  1496. return;
  1497. }
  1498. if (face == ScriptBaseClass.ALL_SIDES)
  1499. {
  1500. for (uint i = 0; i < GetNumberOfSides(part); i++)
  1501. {
  1502. if (tex.FaceTextures[i] != null)
  1503. {
  1504. tex.FaceTextures[i].Shiny = sval;
  1505. tex.FaceTextures[i].Bump = bump;
  1506. }
  1507. tex.DefaultTexture.Shiny = sval;
  1508. tex.DefaultTexture.Bump = bump;
  1509. }
  1510. part.UpdateTexture(tex, false);
  1511. }
  1512. }
  1513. public void SetFullBright(ISceneChildEntity part, int face, bool bright)
  1514. {
  1515. Primitive.TextureEntry tex = part.Shape.Textures;
  1516. if (face >= 0 && face < GetNumberOfSides(part))
  1517. {
  1518. tex.CreateFace((uint) face);
  1519. tex.FaceTextures[face].Fullbright = bright;
  1520. part.UpdateTexture(tex, false);
  1521. return;
  1522. }
  1523. if (face == ScriptBaseClass.ALL_SIDES)
  1524. {
  1525. for (uint i = 0; i < GetNumberOfSides(part); i++)
  1526. {
  1527. if (tex.FaceTextures[i] != null)
  1528. {
  1529. tex.FaceTextures[i].Fullbright = bright;
  1530. }
  1531. }
  1532. tex.DefaultTexture.Fullbright = bright;
  1533. part.UpdateTexture(tex, false);
  1534. }
  1535. }
  1536. public LSL_Float llGetAlpha(int face)
  1537. {
  1538. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  1539. return new LSL_Float();
  1540. return GetAlpha(m_host, face);
  1541. }
  1542. protected LSL_Float GetAlpha(ISceneChildEntity part, int face)
  1543. {
  1544. Primitive.TextureEntry tex = part.Shape.Textures;
  1545. if (face == ScriptBaseClass.ALL_SIDES)
  1546. {
  1547. int i;
  1548. double sum = 0.0;
  1549. for (i = 0; i < GetNumberOfSides(part); i++)
  1550. sum += tex.GetFace((uint) i).RGBA.A;
  1551. return sum;
  1552. }
  1553. if (face >= 0 && face < GetNumberOfSides(part))
  1554. {
  1555. return tex.GetFace((uint) face).RGBA.A;
  1556. }
  1557. return 0.0;
  1558. }
  1559. public void llSetAlpha(double alpha, int face)
  1560. {
  1561. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  1562. SetAlpha(m_host, alpha, face);
  1563. }
  1564. public void llSetLinkAlpha(int linknumber, double alpha, int face)
  1565. {
  1566. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  1567. List<ISceneChildEntity> parts = GetLinkParts(linknumber);
  1568. foreach (ISceneChildEntity part in parts)
  1569. SetAlpha(part, alpha, face);
  1570. }
  1571. protected void SetAlpha(ISceneChildEntity part, double alpha, int face)
  1572. {
  1573. Primitive.TextureEntry tex = part.Shape.Textures;
  1574. Color4 texcolor;
  1575. bool changed = false;
  1576. if (face >= 0 && face < GetNumberOfSides(part))
  1577. {
  1578. texcolor = tex.CreateFace((uint) face).RGBA;
  1579. if (texcolor.A != alpha)
  1580. changed = true;
  1581. texcolor.A = Util.Clip((float) alpha, 0.0f, 1.0f);
  1582. tex.FaceTextures[face].RGBA = texcolor;
  1583. if (changed)
  1584. part.UpdateTexture(tex, false);
  1585. }
  1586. else if (face == ScriptBaseClass.ALL_SIDES)
  1587. {
  1588. for (int i = 0; i < GetNumberOfSides(part); i++)
  1589. {
  1590. if (tex.FaceTextures[i] != null)
  1591. {
  1592. texcolor = tex.FaceTextures[i].RGBA;
  1593. if (texcolor.A != alpha)
  1594. changed = true;
  1595. texcolor.A = Util.Clip((float) alpha, 0.0f, 1.0f);
  1596. tex.FaceTextures[i].RGBA = texcolor;
  1597. }
  1598. }
  1599. texcolor = tex.DefaultTexture.RGBA;
  1600. if (texcolor.A != alpha)
  1601. changed = true;
  1602. texcolor.A = Util.Clip((float) alpha, 0.0f, 1.0f);
  1603. tex.DefaultTexture.RGBA = texcolor;
  1604. if (changed)
  1605. part.UpdateTexture(tex, false);
  1606. }
  1607. part.ScheduleUpdate(PrimUpdateFlags.FullUpdate);
  1608. }
  1609. /// <summary>
  1610. /// Set flexi parameters of a part.
  1611. /// FIXME: Much of this code should probably be within the part itself.
  1612. /// </summary>
  1613. /// <param name="part"></param>
  1614. /// <param name="flexi"></param>
  1615. /// <param name="softness"></param>
  1616. /// <param name="gravity"></param>
  1617. /// <param name="friction"></param>
  1618. /// <param name="wind"></param>
  1619. /// <param name="tension"></param>
  1620. /// <param name="Force"></param>
  1621. protected void SetFlexi(ISceneChildEntity part, bool flexi, int softness, float gravity, float friction,
  1622. float wind, float tension, LSL_Vector Force)
  1623. {
  1624. if (part == null)
  1625. return;
  1626. if (flexi)
  1627. {
  1628. part.Shape.PathCurve |= (byte) Extrusion.Flexible;
  1629. part.Shape.FlexiEntry = true; // this setting flexi true isn't working, but the below parameters do
  1630. // work once the prim is already flexi
  1631. part.Shape.FlexiSoftness = softness;
  1632. part.Shape.FlexiGravity = gravity;
  1633. part.Shape.FlexiDrag = friction;
  1634. part.Shape.FlexiWind = wind;
  1635. part.Shape.FlexiTension = tension;
  1636. part.Shape.FlexiForceX = (float) Force.x;
  1637. part.Shape.FlexiForceY = (float) Force.y;
  1638. part.Shape.FlexiForceZ = (float) Force.z;
  1639. part.Shape.PathCurve = 0x80;
  1640. }
  1641. else
  1642. {
  1643. int curve = part.Shape.PathCurve;
  1644. curve &= (int) (~(Extrusion.Flexible));
  1645. part.Shape.PathCurve = (byte) curve;
  1646. part.Shape.FlexiEntry = false;
  1647. }
  1648. part.ParentEntity.HasGroupChanged = true;
  1649. part.ScheduleUpdate(PrimUpdateFlags.FullUpdate);
  1650. }
  1651. /// <summary>
  1652. /// Set a light point on a part
  1653. /// </summary>
  1654. /// FIXME: Much of this code should probably be in SceneObjectGroup
  1655. /// <param name="part"></param>
  1656. /// <param name="light"></param>
  1657. /// <param name="color"></param>
  1658. /// <param name="intensity"></param>
  1659. /// <param name="radius"></param>
  1660. /// <param name="falloff"></param>
  1661. protected void SetPointLight(ISceneChildEntity part, bool light, LSL_Vector color, float intensity, float radius,
  1662. float falloff)
  1663. {
  1664. if (part == null)
  1665. return;
  1666. bool same = true;
  1667. if (light)
  1668. {
  1669. if (part.Shape.LightEntry != true)
  1670. same = false;
  1671. part.Shape.LightEntry = true;
  1672. if (part.Shape.LightColorR != Util.Clip((float) color.x, 0.0f, 1.0f))
  1673. same = false;
  1674. part.Shape.LightColorR = Util.Clip((float) color.x, 0.0f, 1.0f);
  1675. if (part.Shape.LightColorG != Util.Clip((float) color.y, 0.0f, 1.0f))
  1676. same = false;
  1677. part.Shape.LightColorG = Util.Clip((float) color.y, 0.0f, 1.0f);
  1678. if (part.Shape.LightColorB != Util.Clip((float) color.z, 0.0f, 1.0f))
  1679. same = false;
  1680. part.Shape.LightColorB = Util.Clip((float) color.z, 0.0f, 1.0f);
  1681. if (part.Shape.LightIntensity != intensity)
  1682. same = false;
  1683. part.Shape.LightIntensity = intensity;
  1684. if (part.Shape.LightRadius != radius)
  1685. same = false;
  1686. part.Shape.LightRadius = radius;
  1687. if (part.Shape.LightFalloff != falloff)
  1688. same = false;
  1689. part.Shape.LightFalloff = falloff;
  1690. }
  1691. else
  1692. {
  1693. if (part.Shape.LightEntry)
  1694. same = false;
  1695. part.Shape.LightEntry = false;
  1696. }
  1697. if (!same)
  1698. {
  1699. part.ParentEntity.HasGroupChanged = true;
  1700. part.ScheduleUpdate(PrimUpdateFlags.FindBest);
  1701. }
  1702. }
  1703. public LSL_Vector llGetColor(int face)
  1704. {
  1705. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  1706. return new LSL_Vector();
  1707. return GetColor(m_host, face);
  1708. }
  1709. protected LSL_Vector GetColor(ISceneChildEntity part, int face)
  1710. {
  1711. Primitive.TextureEntry tex = part.Shape.Textures;
  1712. Color4 texcolor;
  1713. LSL_Vector rgb = new LSL_Vector();
  1714. int ns = GetNumberOfSides(part);
  1715. if (face == ScriptBaseClass.ALL_SIDES)
  1716. {
  1717. int i;
  1718. for (i = 0; i < ns; i++)
  1719. {
  1720. texcolor = tex.GetFace((uint) i).RGBA;
  1721. rgb.x += texcolor.R;
  1722. rgb.y += texcolor.G;
  1723. rgb.z += texcolor.B;
  1724. }
  1725. float tmp = 1f/ns;
  1726. rgb.x *= tmp;
  1727. rgb.y *= tmp;
  1728. rgb.z *= tmp;
  1729. return rgb;
  1730. }
  1731. if (face >= 0 && face < ns)
  1732. {
  1733. texcolor = tex.GetFace((uint) face).RGBA;
  1734. rgb.x = texcolor.R;
  1735. rgb.y = texcolor.G;
  1736. rgb.z = texcolor.B;
  1737. return rgb;
  1738. }
  1739. return new LSL_Vector();
  1740. }
  1741. public DateTime llSetTexture(string texture, int face)
  1742. {
  1743. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  1744. return DateTime.Now;
  1745. bool found = SetTexture(m_host, texture, face);
  1746. if (!found)
  1747. ShoutError("Could not find texture '" + texture + "'");
  1748. return PScriptSleep(200);
  1749. }
  1750. public DateTime llSetLinkTexture(int linknumber, string texture, int face)
  1751. {
  1752. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  1753. return DateTime.Now;
  1754. List<ISceneChildEntity> parts = GetLinkParts(linknumber);
  1755. foreach (ISceneChildEntity part in parts)
  1756. SetTexture(part, texture, face);
  1757. return PScriptSleep(100);
  1758. }
  1759. protected bool SetTexture(ISceneChildEntity part, string texture, int face)
  1760. {
  1761. UUID textureID = new UUID();
  1762. int ns = GetNumberOfSides(part);
  1763. textureID = InventoryKey(texture, (int) AssetType.Texture);
  1764. if (textureID == UUID.Zero)
  1765. {
  1766. if (!UUID.TryParse(texture, out textureID))
  1767. return false;
  1768. }
  1769. Primitive.TextureEntry tex = part.Shape.Textures;
  1770. if (face >= 0 && face < ns)
  1771. {
  1772. Primitive.TextureEntryFace texface = tex.CreateFace((uint) face);
  1773. texface.TextureID = textureID;
  1774. tex.FaceTextures[face] = texface;
  1775. part.UpdateTexture(tex, false);
  1776. }
  1777. if (face == ScriptBaseClass.ALL_SIDES)
  1778. {
  1779. for (uint i = 0; i < ns; i++)
  1780. {
  1781. if (tex.FaceTextures[i] != null)
  1782. {
  1783. tex.FaceTextures[i].TextureID = textureID;
  1784. }
  1785. }
  1786. tex.DefaultTexture.TextureID = textureID;
  1787. part.UpdateTexture(tex, false);
  1788. }
  1789. return true;
  1790. }
  1791. public DateTime llScaleTexture(double u, double v, int face)
  1792. {
  1793. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  1794. return DateTime.Now;
  1795. ScaleTexture(m_host, u, v, face);
  1796. return PScriptSleep(200);
  1797. }
  1798. protected void ScaleTexture(ISceneChildEntity part, double u, double v, int face)
  1799. {
  1800. Primitive.TextureEntry tex = part.Shape.Textures;
  1801. int ns = GetNumberOfSides(part);
  1802. if (face >= 0 && face < ns)
  1803. {
  1804. Primitive.TextureEntryFace texface = tex.CreateFace((uint) face);
  1805. texface.RepeatU = (float) u;
  1806. texface.RepeatV = (float) v;
  1807. tex.FaceTextures[face] = texface;
  1808. part.UpdateTexture(tex, false);
  1809. return;
  1810. }
  1811. if (face == ScriptBaseClass.ALL_SIDES)
  1812. {
  1813. for (int i = 0; i < ns; i++)
  1814. {
  1815. if (tex.FaceTextures[i] != null)
  1816. {
  1817. tex.FaceTextures[i].RepeatU = (float) u;
  1818. tex.FaceTextures[i].RepeatV = (float) v;
  1819. }
  1820. }
  1821. tex.DefaultTexture.RepeatU = (float) u;
  1822. tex.DefaultTexture.RepeatV = (float) v;
  1823. part.UpdateTexture(tex, false);
  1824. }
  1825. }
  1826. public DateTime llOffsetTexture(double u, double v, int face)
  1827. {
  1828. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  1829. return DateTime.Now;
  1830. OffsetTexture(m_host, u, v, face);
  1831. return PScriptSleep(200);
  1832. }
  1833. protected void OffsetTexture(ISceneChildEntity part, double u, double v, int face)
  1834. {
  1835. Primitive.TextureEntry tex = part.Shape.Textures;
  1836. int ns = GetNumberOfSides(part);
  1837. if (face >= 0 && face < ns)
  1838. {
  1839. Primitive.TextureEntryFace texface = tex.CreateFace((uint) face);
  1840. texface.OffsetU = (float) u;
  1841. texface.OffsetV = (float) v;
  1842. tex.FaceTextures[face] = texface;
  1843. part.UpdateTexture(tex, false);
  1844. return;
  1845. }
  1846. if (face == ScriptBaseClass.ALL_SIDES)
  1847. {
  1848. for (int i = 0; i < ns; i++)
  1849. {
  1850. if (tex.FaceTextures[i] != null)
  1851. {
  1852. tex.FaceTextures[i].OffsetU = (float) u;
  1853. tex.FaceTextures[i].OffsetV = (float) v;
  1854. }
  1855. }
  1856. tex.DefaultTexture.OffsetU = (float) u;
  1857. tex.DefaultTexture.OffsetV = (float) v;
  1858. part.UpdateTexture(tex, false);
  1859. }
  1860. }
  1861. public DateTime llRotateTexture(double rotation, int face)
  1862. {
  1863. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  1864. return DateTime.Now;
  1865. RotateTexture(m_host, rotation, face);
  1866. return PScriptSleep(200);
  1867. }
  1868. protected void RotateTexture(ISceneChildEntity part, double rotation, int face)
  1869. {
  1870. Primitive.TextureEntry tex = part.Shape.Textures;
  1871. int ns = GetNumberOfSides(part);
  1872. if (face >= 0 && face < ns)
  1873. {
  1874. Primitive.TextureEntryFace texface = tex.CreateFace((uint) face);
  1875. texface.Rotation = (float) rotation;
  1876. tex.FaceTextures[face] = texface;
  1877. part.UpdateTexture(tex, false);
  1878. return;
  1879. }
  1880. if (face == ScriptBaseClass.ALL_SIDES)
  1881. {
  1882. for (int i = 0; i < ns; i++)
  1883. {
  1884. if (tex.FaceTextures[i] != null)
  1885. {
  1886. tex.FaceTextures[i].Rotation = (float) rotation;
  1887. }
  1888. }
  1889. tex.DefaultTexture.Rotation = (float) rotation;
  1890. part.UpdateTexture(tex, false);
  1891. return;
  1892. }
  1893. }
  1894. public LSL_String llGetTexture(int face)
  1895. {
  1896. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  1897. return new LSL_String();
  1898. return GetTexture(m_host, face);
  1899. }
  1900. protected LSL_String GetTexture(ISceneChildEntity part, int face)
  1901. {
  1902. Primitive.TextureEntry tex = part.Shape.Textures;
  1903. if (face == ScriptBaseClass.ALL_SIDES)
  1904. {
  1905. face = 0;
  1906. }
  1907. if (face >= 0 && face < GetNumberOfSides(part))
  1908. {
  1909. Primitive.TextureEntryFace texface = tex.GetFace((uint) face);
  1910. TaskInventoryItem item = null;
  1911. m_host.TaskInventory.TryGetValue(texface.TextureID, out item);
  1912. if (item != null)
  1913. return item.Name.ToString();
  1914. return texface.TextureID.ToString();
  1915. }
  1916. return String.Empty;
  1917. }
  1918. public DateTime llSetPos(LSL_Vector pos)
  1919. {
  1920. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  1921. return DateTime.Now;
  1922. SetPos(m_host, pos, true);
  1923. return PScriptSleep(200);
  1924. }
  1925. public LSL_Integer llSetRegionPos(LSL_Vector pos)
  1926. {
  1927. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  1928. return ScriptBaseClass.FALSE;
  1929. SetPos(m_host, pos, false);
  1930. return ScriptBaseClass.TRUE;
  1931. }
  1932. // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos)
  1933. // note linked setpos is capped "differently"
  1934. private LSL_Vector SetPosAdjust(LSL_Vector start, LSL_Vector end)
  1935. {
  1936. if (llVecDist(start, end) > 10.0f*m_ScriptDistanceFactor)
  1937. return start + m_ScriptDistanceFactor*10.0f*llVecNorm(end - start);
  1938. return end;
  1939. }
  1940. protected void SetPos(ISceneChildEntity part, LSL_Vector targetPos, bool checkPos)
  1941. {
  1942. // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos)
  1943. LSL_Vector currentPos = GetPartLocalPos(part);
  1944. float ground = 0;
  1945. bool disable_underground_movement = m_ScriptEngine.Config.GetBoolean("DisableUndergroundMovement", true);
  1946. ITerrainChannel heightmap = World.RequestModuleInterface<ITerrainChannel>();
  1947. if (heightmap != null)
  1948. ground = heightmap.GetNormalizedGroundHeight((int) (float) targetPos.x, (int) (float) targetPos.y);
  1949. if (part.ParentEntity == null)
  1950. return;
  1951. if (part.ParentEntity.RootChild == part)
  1952. {
  1953. ISceneEntity parent = part.ParentEntity;
  1954. if (!part.IsAttachment)
  1955. {
  1956. if (ground != 0 && (targetPos.z < ground) && disable_underground_movement)
  1957. targetPos.z = ground;
  1958. }
  1959. LSL_Vector real_vec = checkPos ? SetPosAdjust(currentPos, targetPos) : targetPos;
  1960. parent.UpdateGroupPosition(new Vector3((float) real_vec.x, (float) real_vec.y, (float) real_vec.z), true);
  1961. }
  1962. else
  1963. {
  1964. LSL_Vector rel_vec = checkPos ? SetPosAdjust(currentPos, targetPos) : targetPos;
  1965. part.FixOffsetPosition((new Vector3((float) rel_vec.x, (float) rel_vec.y, (float) rel_vec.z)), true);
  1966. }
  1967. }
  1968. protected LSL_Vector GetPartLocalPos(ISceneChildEntity part)
  1969. {
  1970. Vector3 tmp;
  1971. if (part.ParentID == 0)
  1972. {
  1973. tmp = part.AbsolutePosition;
  1974. return new LSL_Vector(tmp.X,
  1975. tmp.Y,
  1976. tmp.Z);
  1977. }
  1978. if (m_host.IsRoot)
  1979. {
  1980. tmp = m_host.AttachedPos;
  1981. return new LSL_Vector(tmp.X,
  1982. tmp.Y,
  1983. tmp.Z);
  1984. }
  1985. tmp = part.OffsetPosition;
  1986. return new LSL_Vector(tmp.X,
  1987. tmp.Y,
  1988. tmp.Z);
  1989. }
  1990. public LSL_Vector llGetPos()
  1991. {
  1992. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  1993. return new LSL_Vector();
  1994. Vector3 pos = m_host.GetWorldPosition();
  1995. return new LSL_Vector(pos.X, pos.Y, pos.Z);
  1996. }
  1997. public LSL_Vector llGetLocalPos()
  1998. {
  1999. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  2000. return new LSL_Vector();
  2001. return GetLocalPos(m_host);
  2002. }
  2003. private LSL_Vector GetLocalPos(ISceneChildEntity entity)
  2004. {
  2005. Vector3 tmp;
  2006. if (entity.ParentID != 0)
  2007. {
  2008. tmp = entity.OffsetPosition;
  2009. return new LSL_Vector(tmp.X,
  2010. tmp.Y,
  2011. tmp.Z);
  2012. }
  2013. tmp = entity.AbsolutePosition;
  2014. return new LSL_Vector(tmp.X,
  2015. tmp.Y,
  2016. tmp.Z);
  2017. }
  2018. public DateTime llSetRot(LSL_Rotation rot)
  2019. {
  2020. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  2021. return DateTime.Now;
  2022. // try to let this work as in SL...
  2023. SetLinkRot(m_host, rot);
  2024. return PScriptSleep(200);
  2025. }
  2026. private void SetLinkRot(ISceneChildEntity obj, LSL_Rotation rot)
  2027. {
  2028. if (obj.ParentID == 0)
  2029. {
  2030. // special case: If we are root, rotate complete SOG to new rotation
  2031. SetRot(obj, Rot2Quaternion(rot));
  2032. }
  2033. else
  2034. {
  2035. // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask.
  2036. ISceneEntity group = obj.ParentEntity;
  2037. if (group != null) // a bit paranoid, maybe
  2038. {
  2039. ISceneChildEntity rootPart = group.RootChild;
  2040. if (rootPart != null) // again, better safe than sorry
  2041. {
  2042. SetRot(obj, rootPart.GetRotationOffset()*Rot2Quaternion(rot));
  2043. }
  2044. }
  2045. }
  2046. }
  2047. public DateTime llSetLocalRot(LSL_Rotation rot)
  2048. {
  2049. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  2050. return DateTime.Now;
  2051. SetRot(m_host, Rot2Quaternion(rot));
  2052. return PScriptSleep(200);
  2053. }
  2054. protected void SetRot(ISceneChildEntity part, Quaternion rot)
  2055. {
  2056. part.UpdateRotation(rot);
  2057. // Update rotation does not move the object in the physics scene if it's a linkset.
  2058. //KF: Do NOT use this next line if using ODE physics engine.
  2059. // This need a switch based on .ini Phys Engine type
  2060. //part.ParentGroup.ResetChildPrimPhysicsPositions()
  2061. // So, after thinking about this for a bit, the issue with the part.ParentGroup.AbsolutePosition = part.ParentGroup.AbsolutePosition line
  2062. // is it isn't compatible with vehicles because it causes the vehicle body to have to be broken down and rebuilt
  2063. // It's perfectly okay when the object is not an active physical body though.
  2064. // So, part.ParentGroup.ResetChildPrimPhysicsPositions(); does the thing that Kitto is warning against
  2065. // but only if the object is not physial and active. This is important for rotating doors.
  2066. // without the absoluteposition = absoluteposition happening, the doors do not move in the physics
  2067. // scene
  2068. if (part.PhysActor != null && !part.PhysActor.IsPhysical)
  2069. {
  2070. part.ParentEntity.ResetChildPrimPhysicsPositions();
  2071. }
  2072. }
  2073. /// <summary>
  2074. /// See http://lslwiki.net/lslwiki/wakka.php?wakka=ChildRotation
  2075. /// </summary>
  2076. public LSL_Rotation llGetRot()
  2077. {
  2078. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  2079. return new LSL_Rotation();
  2080. // unlinked or root prim then use llRootRotation
  2081. // see llRootRotaion for references.
  2082. if (m_host.LinkNum == 0 || m_host.LinkNum == 1)
  2083. {
  2084. return llGetRootRotation();
  2085. }
  2086. Quaternion q = m_host.GetWorldRotation();
  2087. return new LSL_Rotation(q.X, q.Y, q.Z, q.W);
  2088. }
  2089. private LSL_Rotation GetPartRot(ISceneChildEntity part)
  2090. {
  2091. Quaternion q;
  2092. if (part.LinkNum == 0 || part.LinkNum == 1) // unlinked or root prim
  2093. {
  2094. if (part.ParentEntity.RootChild.AttachmentPoint != 0)
  2095. {
  2096. IScenePresence avatar = World.GetScenePresence(part.AttachedAvatar);
  2097. if (avatar != null)
  2098. {
  2099. q = (avatar.AgentControlFlags & (uint) AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0
  2100. ? avatar.CameraRotation
  2101. : avatar.Rotation;
  2102. }
  2103. else
  2104. q = part.ParentEntity.GroupRotation; // Likely never get here but just in case
  2105. }
  2106. else
  2107. q = part.ParentEntity.GroupRotation; // just the group rotation
  2108. return new LSL_Rotation(q.X, q.Y, q.Z, q.W);
  2109. }
  2110. q = part.GetWorldRotation();
  2111. return new LSL_Rotation(q.X, q.Y, q.Z, q.W);
  2112. }
  2113. public LSL_Rotation llGetLocalRot()
  2114. {
  2115. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  2116. return new LSL_Rotation();
  2117. return new LSL_Rotation(m_host.GetRotationOffset().X, m_host.GetRotationOffset().Y,
  2118. m_host.GetRotationOffset().Z, m_host.GetRotationOffset().W);
  2119. }
  2120. public void llSetForce(LSL_Vector force, int local)
  2121. {
  2122. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  2123. if (m_host.ParentEntity != null)
  2124. {
  2125. if (!m_host.ParentEntity.IsDeleted)
  2126. {
  2127. if (local != 0)
  2128. force *= llGetRot();
  2129. m_host.ParentEntity.RootChild.SetForce(new Vector3((float) force.x, (float) force.y, (float) force.z));
  2130. }
  2131. }
  2132. }
  2133. public LSL_Vector llGetForce()
  2134. {
  2135. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  2136. return new LSL_Vector();
  2137. LSL_Vector force = new LSL_Vector(0.0, 0.0, 0.0);
  2138. if (m_host.ParentEntity != null)
  2139. {
  2140. if (!m_host.ParentEntity.IsDeleted)
  2141. {
  2142. Vector3 tmpForce = m_host.ParentEntity.RootChild.GetForce();
  2143. force.x = tmpForce.X;
  2144. force.y = tmpForce.Y;
  2145. force.z = tmpForce.Z;
  2146. }
  2147. }
  2148. return force;
  2149. }
  2150. public LSL_Integer llTarget(LSL_Vector position, LSL_Float range)
  2151. {
  2152. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  2153. return m_host.registerTargetWaypoint(
  2154. new Vector3((float) position.x, (float) position.y, (float) position.z), (float) range);
  2155. }
  2156. public void llTargetRemove(int number)
  2157. {
  2158. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  2159. m_host.unregisterTargetWaypoint(number);
  2160. }
  2161. public LSL_Integer llRotTarget(LSL_Rotation rot, double error)
  2162. {
  2163. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  2164. return
  2165. m_host.registerRotTargetWaypoint(
  2166. new Quaternion((float) rot.x, (float) rot.y, (float) rot.z, (float) rot.s), (float) error);
  2167. }
  2168. public void llRotTargetRemove(int number)
  2169. {
  2170. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  2171. m_host.unregisterRotTargetWaypoint(number);
  2172. }
  2173. public void llMoveToTarget(LSL_Vector target, double tau)
  2174. {
  2175. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  2176. m_host.MoveToTarget(new Vector3((float) target.x, (float) target.y, (float) target.z), (float) tau);
  2177. }
  2178. public void llStopMoveToTarget()
  2179. {
  2180. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  2181. m_host.StopMoveToTarget();
  2182. }
  2183. public void llApplyImpulse(LSL_Vector force, int local)
  2184. {
  2185. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  2186. //No energy force yet
  2187. Vector3 v = new Vector3((float) force.x, (float) force.y, (float) force.z);
  2188. float len = v.Length();
  2189. if (len > 20000.0f)
  2190. {
  2191. // v.Normalize();
  2192. v = v*20000.0f/len;
  2193. }
  2194. m_host.ApplyImpulse(v, local != 0);
  2195. }
  2196. public void llApplyRotationalImpulse(LSL_Vector force, int local)
  2197. {
  2198. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  2199. m_host.ApplyAngularImpulse(new Vector3((float) force.x, (float) force.y, (float) force.z), local != 0);
  2200. }
  2201. public void llSetTorque(LSL_Vector torque, int local)
  2202. {
  2203. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  2204. m_host.SetAngularImpulse(new Vector3((float) torque.x, (float) torque.y, (float) torque.z), local != 0);
  2205. }
  2206. public LSL_Vector llGetTorque()
  2207. {
  2208. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  2209. return new LSL_Vector();
  2210. Vector3 torque = m_host.ParentEntity.GetTorque();
  2211. return new LSL_Vector(torque.X, torque.Y, torque.Z);
  2212. }
  2213. public void llSetForceAndTorque(LSL_Vector force, LSL_Vector torque, int local)
  2214. {
  2215. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  2216. llSetForce(force, local);
  2217. llSetTorque(torque, local);
  2218. }
  2219. public LSL_Vector llGetVel()
  2220. {
  2221. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  2222. return new LSL_Vector();
  2223. Vector3 tmp = m_host.IsAttachment
  2224. ? m_host.ParentEntity.Scene.GetScenePresence(m_host.AttachedAvatar).Velocity
  2225. : m_host.Velocity;
  2226. return new LSL_Vector(tmp.X, tmp.Y, tmp.Z);
  2227. }
  2228. public void llSetVelocity(LSL_Vector force, LSL_Integer local)
  2229. {
  2230. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  2231. Vector3 velocity = new Vector3((float) force.x, (float) force.y, (float) force.z);
  2232. if (local == 1)
  2233. {
  2234. Quaternion grot = m_host.GetWorldRotation();
  2235. Quaternion AXgrot = grot;
  2236. Vector3 AXimpulsei = velocity;
  2237. Vector3 newimpulse = AXimpulsei*AXgrot;
  2238. velocity = newimpulse;
  2239. }
  2240. if (m_host.ParentEntity.RootChild.PhysActor != null)
  2241. m_host.ParentEntity.RootChild.PhysActor.Velocity = velocity;
  2242. }
  2243. public void llSetAngularVelocity(LSL_Vector force, LSL_Integer local)
  2244. {
  2245. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  2246. Vector3 rotvelocity = new Vector3((float) force.x, (float) force.y, (float) force.z);
  2247. if (local == 1)
  2248. {
  2249. Quaternion grot = m_host.GetWorldRotation();
  2250. Quaternion AXgrot = grot;
  2251. Vector3 AXimpulsei = rotvelocity;
  2252. Vector3 newimpulse = AXimpulsei*AXgrot;
  2253. rotvelocity = newimpulse;
  2254. }
  2255. if (m_host.ParentEntity.RootChild.PhysActor != null)
  2256. m_host.ParentEntity.RootChild.PhysActor.RotationalVelocity = rotvelocity;
  2257. }
  2258. public LSL_Vector llGetAccel()
  2259. {
  2260. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  2261. return new LSL_Vector();
  2262. Vector3 tmp = m_host.Acceleration;
  2263. return new LSL_Vector(tmp.X, tmp.Y, tmp.Z);
  2264. }
  2265. public LSL_Vector llGetOmega()
  2266. {
  2267. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  2268. return new LSL_Vector();
  2269. Vector3 tmp = m_host.AngularVelocity;
  2270. return new LSL_Vector(tmp.X, tmp.Y, tmp.Z);
  2271. }
  2272. public LSL_Float llGetTimeOfDay() // this is not sl compatible see wiki
  2273. {
  2274. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  2275. return new LSL_Float();
  2276. return (DateTime.Now.TimeOfDay.TotalMilliseconds/1000)%(3600*4);
  2277. }
  2278. public LSL_Float llGetWallclock()
  2279. {
  2280. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  2281. return new LSL_Float();
  2282. return DateTime.Now.TimeOfDay.TotalSeconds;
  2283. }
  2284. public LSL_Float llGetTime()
  2285. {
  2286. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  2287. return new LSL_Float();
  2288. TimeSpan ScriptTime = DateTime.Now - m_timer;
  2289. return ScriptTime.TotalMilliseconds/1000;
  2290. }
  2291. public void llResetTime()
  2292. {
  2293. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  2294. m_timer = DateTime.Now;
  2295. }
  2296. public LSL_Float llGetAndResetTime()
  2297. {
  2298. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  2299. return new LSL_Float();
  2300. TimeSpan ScriptTime = DateTime.Now - m_timer;
  2301. m_timer = DateTime.Now;
  2302. return ScriptTime.TotalMilliseconds/1000;
  2303. }
  2304. public void llSound(string sound, double volume, int queue, int loop)
  2305. {
  2306. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  2307. // This function has been deprecated
  2308. // see http://www.lslwiki.net/lslwiki/wakka.php?wakka=llSound
  2309. Deprecated("llSound");
  2310. if (loop == 1)
  2311. llLoopSound(sound, volume);
  2312. else
  2313. llPlaySound(sound, volume);
  2314. llSetSoundQueueing(queue);
  2315. }
  2316. // Xantor 20080528 PlaySound updated so it accepts an objectinventory name -or- a key to a sound
  2317. // 20080530 Updated to remove code duplication
  2318. public void llPlaySound(string sound, double volume)
  2319. {
  2320. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  2321. // send the sound, once, to all clients in range
  2322. m_host.SendSound(KeyOrName(sound, true).ToString(), volume, false, 0, 0, false, false);
  2323. }
  2324. // Xantor 20080528 we should do this differently.
  2325. // 1) apply the sound to the object
  2326. // 2) schedule full update
  2327. // just sending the sound out once doesn't work so well when other avatars come in view later on
  2328. // or when the prim gets moved, changed, sat on, whatever
  2329. // see large number of mantises (mantes?)
  2330. // 20080530 Updated to remove code duplication
  2331. // 20080530 Stop sound if there is one, otherwise volume only changes don't work
  2332. public void llLoopSound(string sound, double volume)
  2333. {
  2334. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  2335. if (m_host.Sound == KeyOrName(sound, true))
  2336. return;
  2337. if (m_host.Sound != UUID.Zero)
  2338. llStopSound();
  2339. m_host.Sound = KeyOrName(sound, true);
  2340. m_host.SoundGain = volume;
  2341. m_host.SoundFlags = (byte) SoundFlags.Loop; // looping
  2342. if (m_host.SoundRadius == 0)
  2343. m_host.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable?
  2344. m_host.ScheduleUpdate(PrimUpdateFlags.FindBest);
  2345. }
  2346. public void llLoopSoundMaster(string sound, double volume)
  2347. {
  2348. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  2349. m_host.ParentEntity.LoopSoundMasterPrim = m_host;
  2350. lock (m_host.ParentEntity.LoopSoundSlavePrims)
  2351. {
  2352. foreach (ISceneChildEntity prim in m_host.ParentEntity.LoopSoundSlavePrims)
  2353. {
  2354. if (prim.Sound != UUID.Zero)
  2355. llStopSound();
  2356. prim.Sound = KeyOrName(sound, true);
  2357. prim.SoundGain = volume;
  2358. prim.SoundFlags = (byte) SoundFlags.Loop; // looping
  2359. if (prim.SoundRadius == 0)
  2360. prim.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable?
  2361. prim.ScheduleUpdate(PrimUpdateFlags.FindBest);
  2362. }
  2363. }
  2364. if (m_host.Sound != UUID.Zero)
  2365. llStopSound();
  2366. m_host.Sound = KeyOrName(sound, true);
  2367. m_host.SoundGain = volume;
  2368. m_host.SoundFlags = (byte) SoundFlags.Loop; // looping
  2369. if (m_host.SoundRadius == 0)
  2370. m_host.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable?
  2371. m_host.ScheduleUpdate(PrimUpdateFlags.FindBest);
  2372. }
  2373. public void llLoopSoundSlave(string sound, double volume)
  2374. {
  2375. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  2376. lock (m_host.ParentEntity.LoopSoundSlavePrims)
  2377. {
  2378. m_host.ParentEntity.LoopSoundSlavePrims.Add(m_host);
  2379. }
  2380. }
  2381. public void llPlaySoundSlave(string sound, double volume)
  2382. {
  2383. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  2384. // send the sound, once, to all clients in range
  2385. m_host.SendSound(KeyOrName(sound, true).ToString(), volume, false, 0, 0, true, false);
  2386. }
  2387. public void llTriggerSound(string sound, double volume)
  2388. {
  2389. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  2390. // send the sound, once, to all clients in range
  2391. m_host.SendSound(KeyOrName(sound, true).ToString(), volume, true, 0, 0, false, false);
  2392. }
  2393. // Xantor 20080528: Clear prim data of sound instead
  2394. public void llStopSound()
  2395. {
  2396. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  2397. if (m_host.ParentEntity.LoopSoundSlavePrims.Contains(m_host))
  2398. {
  2399. if (m_host.ParentEntity.LoopSoundMasterPrim == m_host)
  2400. {
  2401. foreach (ISceneChildEntity part in m_host.ParentEntity.LoopSoundSlavePrims)
  2402. {
  2403. part.Sound = UUID.Zero;
  2404. part.SoundGain = 0;
  2405. part.SoundFlags = (byte) SoundFlags.None;
  2406. part.ScheduleUpdate(PrimUpdateFlags.FindBest);
  2407. }
  2408. m_host.ParentEntity.LoopSoundMasterPrim = null;
  2409. m_host.ParentEntity.LoopSoundSlavePrims.Clear();
  2410. }
  2411. else
  2412. {
  2413. m_host.Sound = UUID.Zero;
  2414. m_host.SoundGain = 0;
  2415. m_host.SoundFlags = (byte) SoundFlags.None;
  2416. m_host.ScheduleUpdate(PrimUpdateFlags.FindBest);
  2417. }
  2418. }
  2419. else
  2420. {
  2421. m_host.Sound = UUID.Zero;
  2422. m_host.SoundGain = 0;
  2423. m_host.SoundFlags = (byte) SoundFlags.Stop | (byte) SoundFlags.None;
  2424. m_host.ScheduleUpdate(PrimUpdateFlags.FindBest);
  2425. }
  2426. }
  2427. public DateTime llPreloadSound(string sound)
  2428. {
  2429. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  2430. return DateTime.Now;
  2431. m_host.PreloadSound(sound);
  2432. return PScriptSleep(1000);
  2433. }
  2434. /// <summary>
  2435. /// Return a portion of the designated string bounded by
  2436. /// inclusive indices (start and end). As usual, the negative
  2437. /// indices, and the tolerance for out-of-bound values, makes
  2438. /// this more complicated than it might otherwise seem.
  2439. /// </summary>
  2440. public LSL_String llGetSubString(string src, int start, int end)
  2441. {
  2442. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  2443. return new LSL_String();
  2444. // Normalize indices (if negative).
  2445. // After normlaization they may still be
  2446. // negative, but that is now relative to
  2447. // the start, rather than the end, of the
  2448. // sequence.
  2449. if (start < 0)
  2450. {
  2451. start = src.Length + start;
  2452. }
  2453. if (end < 0)
  2454. {
  2455. end = src.Length + end;
  2456. }
  2457. // Conventional substring
  2458. if (start <= end)
  2459. {
  2460. // Implies both bounds are out-of-range.
  2461. if (end < 0 || start >= src.Length)
  2462. {
  2463. return String.Empty;
  2464. }
  2465. // If end is positive, then it directly
  2466. // corresponds to the lengt of the substring
  2467. // needed (plus one of course). BUT, it
  2468. // must be within bounds.
  2469. if (end >= src.Length)
  2470. {
  2471. end = src.Length - 1;
  2472. }
  2473. if (start < 0)
  2474. {
  2475. return src.Substring(0, end + 1);
  2476. }
  2477. // Both indices are positive
  2478. return src.Substring(start, (end + 1) - start);
  2479. }
  2480. // Inverted substring (end < start)
  2481. // Implies both indices are below the
  2482. // lower bound. In the inverted case, that
  2483. // means the entire string will be returned
  2484. // unchanged.
  2485. if (start < 0)
  2486. {
  2487. return src;
  2488. }
  2489. // If both indices are greater than the upper
  2490. // bound the result may seem initially counter
  2491. // intuitive.
  2492. if (end >= src.Length)
  2493. {
  2494. return src;
  2495. }
  2496. if (end < 0)
  2497. {
  2498. return start < src.Length ? src.Substring(start) : String.Empty;
  2499. }
  2500. if (start < src.Length)
  2501. {
  2502. return src.Substring(0, end + 1) + src.Substring(start);
  2503. }
  2504. return src.Substring(0, end + 1);
  2505. }
  2506. /// <summary>
  2507. /// Delete substring removes the specified substring bounded
  2508. /// by the inclusive indices start and end. Indices may be
  2509. /// negative (indicating end-relative) and may be inverted,
  2510. /// i.e. end < start. />
  2511. /// </summary>
  2512. public LSL_String llDeleteSubString(string src, int start, int end)
  2513. {
  2514. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  2515. return new LSL_String();
  2516. // Normalize indices (if negative).
  2517. // After normlaization they may still be
  2518. // negative, but that is now relative to
  2519. // the start, rather than the end, of the
  2520. // sequence.
  2521. if (start < 0)
  2522. {
  2523. start = src.Length + start;
  2524. }
  2525. if (end < 0)
  2526. {
  2527. end = src.Length + end;
  2528. }
  2529. // Conventionally delimited substring
  2530. if (start <= end)
  2531. {
  2532. // If both bounds are outside of the existing
  2533. // string, then return unchanges.
  2534. if (end < 0 || start >= src.Length)
  2535. {
  2536. return src;
  2537. }
  2538. // At least one bound is in-range, so we
  2539. // need to clip the out-of-bound argument.
  2540. if (start < 0)
  2541. {
  2542. start = 0;
  2543. }
  2544. if (end >= src.Length)
  2545. {
  2546. end = src.Length - 1;
  2547. }
  2548. return src.Remove(start, end - start + 1);
  2549. }
  2550. // Inverted substring
  2551. // In this case, out of bounds means that
  2552. // the existing string is part of the cut.
  2553. if (start < 0 || end >= src.Length)
  2554. {
  2555. return String.Empty;
  2556. }
  2557. if (end > 0)
  2558. {
  2559. if (start < src.Length)
  2560. {
  2561. return src.Remove(start).Remove(0, end + 1);
  2562. }
  2563. return src.Remove(0, end + 1);
  2564. }
  2565. if (start < src.Length)
  2566. {
  2567. return src.Remove(start);
  2568. }
  2569. return src;
  2570. }
  2571. /// <summary>
  2572. /// Insert string inserts the specified string identified by src
  2573. /// at the index indicated by index. Index may be negative, in
  2574. /// which case it is end-relative. The index may exceed either
  2575. /// string bound, with the result being a concatenation.
  2576. /// </summary>
  2577. public LSL_String llInsertString(string dest, int index, string src)
  2578. {
  2579. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  2580. return new LSL_String();
  2581. // Normalize indices (if negative).
  2582. // After normlaization they may still be
  2583. // negative, but that is now relative to
  2584. // the start, rather than the end, of the
  2585. // sequence.
  2586. if (index < 0)
  2587. {
  2588. index = dest.Length + index;
  2589. // Negative now means it is less than the lower
  2590. // bound of the string.
  2591. if (index < 0)
  2592. {
  2593. return src + dest;
  2594. }
  2595. }
  2596. if (index >= dest.Length)
  2597. {
  2598. return dest + src;
  2599. }
  2600. // The index is in bounds.
  2601. // In this case the index refers to the index that will
  2602. // be assigned to the first character of the inserted string.
  2603. // So unlike the other string operations, we do not add one
  2604. // to get the correct string length.
  2605. return dest.Substring(0, index) + src + dest.Substring(index);
  2606. }
  2607. public LSL_String llToUpper(string src)
  2608. {
  2609. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  2610. return new LSL_String();
  2611. return src.ToUpper();
  2612. }
  2613. public LSL_String llToLower(string src)
  2614. {
  2615. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  2616. return new LSL_String();
  2617. return src.ToLower();
  2618. }
  2619. public LSL_Integer llGiveMoney(string destination, int amount)
  2620. {
  2621. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  2622. return new LSL_Integer();
  2623. UUID invItemID = InventorySelf();
  2624. if (invItemID == UUID.Zero)
  2625. return 0;
  2626. TaskInventoryItem item = m_host.TaskInventory[invItemID];
  2627. if (item.PermsGranter == UUID.Zero)
  2628. return 0;
  2629. if ((item.PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0)
  2630. {
  2631. LSLError("No permissions to give money");
  2632. return 0;
  2633. }
  2634. UUID toID = new UUID();
  2635. if (!UUID.TryParse(destination, out toID))
  2636. {
  2637. LSLError("Bad key in llGiveMoney");
  2638. return 0;
  2639. }
  2640. IMoneyModule money = World.RequestModuleInterface<IMoneyModule>();
  2641. if (money == null)
  2642. {
  2643. NotImplemented("llGiveMoney");
  2644. return 0;
  2645. }
  2646. bool result = money.ObjectGiveMoney(
  2647. m_host.ParentEntity.UUID, m_host.OwnerID, toID, amount);
  2648. if (result)
  2649. return 1;
  2650. return 0;
  2651. }
  2652. public DateTime llMakeExplosion(int particles, double scale, double vel, double lifetime, double arc,
  2653. string texture, LSL_Vector offset)
  2654. {
  2655. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  2656. return DateTime.Now;
  2657. /*llParticleSystem([
  2658. PSYS_PART_FLAGS, PSYS_PART_INTERP_COLOR_MASK | PSYS_PART_INTERP_SCALE_MASK | PSYS_PART_EMISSIVE_MASK | PSYS_PART_WIND_MASK,
  2659. PSYS_SRC_PATTERN, PSYS_SRC_PATTERN_ANGLE_CONE,
  2660. PSYS_PART_START_COLOR, <1.0, 1.0, 1.0>,
  2661. PSYS_PART_END_COLOR, <1.0, 1.0, 1.0>,
  2662. PSYS_PART_START_ALPHA, 0.50,
  2663. PSYS_PART_END_ALPHA, 0.25,
  2664. PSYS_PART_START_SCALE, <particle_scale, particle_scale, 0.0>,
  2665. PSYS_PART_END_SCALE, <particle_scale * 2 + particle_lifetime, particle_scale * 2 + particle_lifetime, 0.0>,
  2666. PSYS_PART_MAX_AGE, particle_lifetime,
  2667. PSYS_SRC_ACCEL, <0.0, 0.0, 0.0>,
  2668. PSYS_SRC_TEXTURE, source_texture_id,
  2669. PSYS_SRC_BURST_RATE, 1.0,
  2670. PSYS_SRC_ANGLE_BEGIN, 0.0,
  2671. PSYS_SRC_ANGLE_END, source_cone * PI,
  2672. PSYS_SRC_BURST_PART_COUNT, particle_count / 2,
  2673. PSYS_SRC_BURST_RADIUS, 0.0,
  2674. PSYS_SRC_BURST_SPEED_MIN, particle_speed / 3,
  2675. PSYS_SRC_BURST_SPEED_MAX, particle_speed * 2/3,
  2676. PSYS_SRC_MAX_AGE, particle_lifetime / 2,
  2677. PSYS_SRC_OMEGA, <0.0, 0.0, 0.0>
  2678. ]);*/
  2679. List<object> list = new List<object>
  2680. {
  2681. ScriptBaseClass.PSYS_PART_FLAGS,
  2682. ScriptBaseClass.PSYS_PART_INTERP_COLOR_MASK |
  2683. ScriptBaseClass.PSYS_PART_INTERP_SCALE_MASK |
  2684. ScriptBaseClass.PSYS_PART_EMISSIVE_MASK | ScriptBaseClass.PSYS_PART_WIND_MASK,
  2685. ScriptBaseClass.PSYS_SRC_PATTERN,
  2686. ScriptBaseClass.PSYS_SRC_PATTERN_ANGLE_CONE,
  2687. ScriptBaseClass.PSYS_PART_START_COLOR,
  2688. new LSL_Vector(1, 1, 1),
  2689. ScriptBaseClass.PSYS_PART_END_COLOR,
  2690. new LSL_Vector(1, 1, 1),
  2691. ScriptBaseClass.PSYS_PART_START_ALPHA,
  2692. new LSL_Float(0.50),
  2693. ScriptBaseClass.PSYS_PART_END_ALPHA,
  2694. new LSL_Float(0.25),
  2695. ScriptBaseClass.PSYS_PART_START_SCALE,
  2696. new LSL_Vector(scale, scale, 0),
  2697. ScriptBaseClass.PSYS_PART_END_SCALE,
  2698. new LSL_Vector(scale*2 + lifetime, scale*2 + lifetime, 0),
  2699. ScriptBaseClass.PSYS_PART_MAX_AGE,
  2700. new LSL_Float(lifetime),
  2701. ScriptBaseClass.PSYS_SRC_ACCEL,
  2702. new LSL_Vector(0, 0, 0),
  2703. ScriptBaseClass.PSYS_SRC_TEXTURE,
  2704. new LSL_String(texture),
  2705. ScriptBaseClass.PSYS_SRC_BURST_RATE,
  2706. new LSL_Float(1),
  2707. ScriptBaseClass.PSYS_SRC_ANGLE_BEGIN,
  2708. new LSL_Float(0.0),
  2709. ScriptBaseClass.PSYS_SRC_ANGLE_END,
  2710. new LSL_Float(arc*Math.PI),
  2711. ScriptBaseClass.PSYS_SRC_BURST_PART_COUNT,
  2712. new LSL_Integer(particles/2),
  2713. ScriptBaseClass.PSYS_SRC_BURST_RADIUS,
  2714. new LSL_Float(0.0),
  2715. ScriptBaseClass.PSYS_SRC_BURST_SPEED_MIN,
  2716. new LSL_Float(vel/3),
  2717. ScriptBaseClass.PSYS_SRC_BURST_SPEED_MAX,
  2718. new LSL_Float(vel*2/3),
  2719. ScriptBaseClass.PSYS_SRC_MAX_AGE,
  2720. new LSL_Float(lifetime/2),
  2721. ScriptBaseClass.PSYS_SRC_OMEGA,
  2722. new LSL_Vector(0, 0, 0)
  2723. };
  2724. llParticleSystem(new LSL_Types.list(list.ToArray()));
  2725. return PScriptSleep(100);
  2726. }
  2727. public DateTime llMakeFountain(int particles, double scale, double vel, double lifetime, double arc, int bounce,
  2728. string texture, LSL_Vector offset, double bounce_offset)
  2729. {
  2730. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  2731. return DateTime.Now;
  2732. /*llParticleSystem([
  2733. 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,
  2734. PSYS_SRC_PATTERN, PSYS_SRC_PATTERN_ANGLE_CONE,
  2735. PSYS_PART_START_COLOR, <1.0, 1.0, 1.0>,
  2736. PSYS_PART_END_COLOR, <1.0, 1.0, 1.0>,
  2737. PSYS_PART_START_ALPHA, 0.50,
  2738. PSYS_PART_END_ALPHA, 0.25,
  2739. PSYS_PART_START_SCALE, <particle_scale/1.5, particle_scale/1.5, 0.0>,
  2740. PSYS_PART_END_SCALE, <0.0, 0.0, 0.0>,
  2741. PSYS_PART_MAX_AGE, 3.0,
  2742. PSYS_SRC_ACCEL, <1.0, 0.0, -4>,
  2743. PSYS_SRC_TEXTURE, source_texture_id,
  2744. PSYS_SRC_BURST_RATE, 5/particle_count,
  2745. PSYS_SRC_ANGLE_BEGIN, 0.0,
  2746. PSYS_SRC_ANGLE_END, source_cone*PI,
  2747. PSYS_SRC_BURST_PART_COUNT, 1,
  2748. PSYS_SRC_BURST_RADIUS, 0.0,
  2749. PSYS_SRC_BURST_SPEED_MIN, particle_speed,
  2750. PSYS_SRC_BURST_SPEED_MAX, particle_speed,
  2751. PSYS_SRC_MAX_AGE, particle_lifetime/2,
  2752. PSYS_SRC_OMEGA, <0.0, 0.0, 0.0>
  2753. ]);*/
  2754. List<object> list = new List<object>
  2755. {
  2756. ScriptBaseClass.PSYS_PART_FLAGS,
  2757. ScriptBaseClass.PSYS_PART_INTERP_COLOR_MASK |
  2758. ScriptBaseClass.PSYS_PART_INTERP_SCALE_MASK |
  2759. ScriptBaseClass.PSYS_PART_WIND_MASK |
  2760. ScriptBaseClass.PSYS_PART_BOUNCE_MASK | ScriptBaseClass.PSYS_PART_EMISSIVE_MASK,
  2761. ScriptBaseClass.PSYS_SRC_PATTERN,
  2762. ScriptBaseClass.PSYS_SRC_PATTERN_ANGLE_CONE,
  2763. ScriptBaseClass.PSYS_PART_START_COLOR,
  2764. new LSL_Vector(1, 1, 1),
  2765. ScriptBaseClass.PSYS_PART_END_COLOR,
  2766. new LSL_Vector(1, 1, 1),
  2767. ScriptBaseClass.PSYS_PART_START_ALPHA,
  2768. new LSL_Float(0.50),
  2769. ScriptBaseClass.PSYS_PART_END_ALPHA,
  2770. new LSL_Float(0.25),
  2771. ScriptBaseClass.PSYS_PART_START_SCALE,
  2772. new LSL_Vector(scale/1.5, scale/1.5, 0),
  2773. ScriptBaseClass.PSYS_PART_END_SCALE,
  2774. new LSL_Vector(0, 0, 0),
  2775. ScriptBaseClass.PSYS_PART_MAX_AGE,
  2776. new LSL_Float(3),
  2777. ScriptBaseClass.PSYS_SRC_ACCEL,
  2778. new LSL_Vector(1, 0, -4),
  2779. ScriptBaseClass.PSYS_SRC_TEXTURE,
  2780. new LSL_String(texture),
  2781. ScriptBaseClass.PSYS_SRC_BURST_RATE,
  2782. new LSL_Float(5/particles),
  2783. ScriptBaseClass.PSYS_SRC_ANGLE_BEGIN,
  2784. new LSL_Float(0.0),
  2785. ScriptBaseClass.PSYS_SRC_ANGLE_END,
  2786. new LSL_Float(arc*Math.PI),
  2787. ScriptBaseClass.PSYS_SRC_BURST_PART_COUNT,
  2788. new LSL_Integer(1),
  2789. ScriptBaseClass.PSYS_SRC_BURST_RADIUS,
  2790. new LSL_Float(0.0),
  2791. ScriptBaseClass.PSYS_SRC_BURST_SPEED_MIN,
  2792. new LSL_Float(vel),
  2793. ScriptBaseClass.PSYS_SRC_BURST_SPEED_MAX,
  2794. new LSL_Float(vel),
  2795. ScriptBaseClass.PSYS_SRC_MAX_AGE,
  2796. new LSL_Float(lifetime/2),
  2797. ScriptBaseClass.PSYS_SRC_OMEGA,
  2798. new LSL_Vector(0, 0, 0)
  2799. };
  2800. llParticleSystem(new LSL_Types.list(list.ToArray()));
  2801. return PScriptSleep(100);
  2802. }
  2803. public DateTime llMakeSmoke(int particles, double scale, double vel, double lifetime, double arc, string texture,
  2804. LSL_Vector offset)
  2805. {
  2806. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  2807. return DateTime.Now;
  2808. /*llParticleSystem([
  2809. PSYS_PART_FLAGS, PSYS_PART_INTERP_COLOR_MASK | PSYS_PART_INTERP_SCALE_MASK | PSYS_PART_EMISSIVE_MASK | PSYS_PART_WIND_MASK,
  2810. PSYS_SRC_PATTERN, PSYS_SRC_PATTERN_ANGLE_CONE,
  2811. PSYS_PART_START_COLOR, <1.0, 1.0, 1.0>,
  2812. PSYS_PART_END_COLOR, <1.0, 1.0, 1.0>,
  2813. PSYS_PART_START_ALPHA, 1.00,
  2814. PSYS_PART_END_ALPHA, 0.05,
  2815. PSYS_PART_START_SCALE, <particle_scale, particle_scale, 0.0>,
  2816. PSYS_PART_END_SCALE, <10, 10, 0.0>,
  2817. PSYS_PART_MAX_AGE, 3.0,
  2818. PSYS_SRC_ACCEL, <0.0, 0.0, 0.0>,
  2819. PSYS_SRC_TEXTURE, source_texture_id,
  2820. PSYS_SRC_BURST_RATE, 10.0 / particle_count,
  2821. PSYS_SRC_ANGLE_BEGIN, 0.0,
  2822. PSYS_SRC_ANGLE_END, source_cone * PI,
  2823. PSYS_SRC_BURST_PART_COUNT, 1,
  2824. PSYS_SRC_BURST_RADIUS, 0.0,
  2825. PSYS_SRC_BURST_SPEED_MIN, particle_speed,
  2826. PSYS_SRC_BURST_SPEED_MAX, particle_speed,
  2827. PSYS_SRC_MAX_AGE, particle_lifetime / 2,
  2828. PSYS_SRC_OMEGA, <0.0, 0.0, 0.0>
  2829. ]);*/
  2830. List<object> list = new List<object>
  2831. {
  2832. ScriptBaseClass.PSYS_PART_FLAGS,
  2833. ScriptBaseClass.PSYS_PART_INTERP_COLOR_MASK |
  2834. ScriptBaseClass.PSYS_PART_INTERP_SCALE_MASK |
  2835. ScriptBaseClass.PSYS_PART_EMISSIVE_MASK | ScriptBaseClass.PSYS_PART_WIND_MASK,
  2836. ScriptBaseClass.PSYS_SRC_PATTERN,
  2837. ScriptBaseClass.PSYS_SRC_PATTERN_ANGLE_CONE,
  2838. ScriptBaseClass.PSYS_PART_START_COLOR,
  2839. new LSL_Vector(1, 1, 1),
  2840. ScriptBaseClass.PSYS_PART_END_COLOR,
  2841. new LSL_Vector(1, 1, 1),
  2842. ScriptBaseClass.PSYS_PART_START_ALPHA,
  2843. new LSL_Float(1),
  2844. ScriptBaseClass.PSYS_PART_END_ALPHA,
  2845. new LSL_Float(0.05),
  2846. ScriptBaseClass.PSYS_PART_START_SCALE,
  2847. new LSL_Vector(scale, scale, 0),
  2848. ScriptBaseClass.PSYS_PART_END_SCALE,
  2849. new LSL_Vector(10, 10, 0),
  2850. ScriptBaseClass.PSYS_PART_MAX_AGE,
  2851. new LSL_Float(3),
  2852. ScriptBaseClass.PSYS_SRC_ACCEL,
  2853. new LSL_Vector(0, 0, 0),
  2854. ScriptBaseClass.PSYS_SRC_TEXTURE,
  2855. new LSL_String(texture),
  2856. ScriptBaseClass.PSYS_SRC_BURST_RATE,
  2857. new LSL_Float(10/particles),
  2858. ScriptBaseClass.PSYS_SRC_ANGLE_BEGIN,
  2859. new LSL_Float(0.0),
  2860. ScriptBaseClass.PSYS_SRC_ANGLE_END,
  2861. new LSL_Float(arc*Math.PI),
  2862. ScriptBaseClass.PSYS_SRC_BURST_PART_COUNT,
  2863. new LSL_Integer(1),
  2864. ScriptBaseClass.PSYS_SRC_BURST_RADIUS,
  2865. new LSL_Float(0.0),
  2866. ScriptBaseClass.PSYS_SRC_BURST_SPEED_MIN,
  2867. new LSL_Float(vel),
  2868. ScriptBaseClass.PSYS_SRC_BURST_SPEED_MAX,
  2869. new LSL_Float(vel),
  2870. ScriptBaseClass.PSYS_SRC_MAX_AGE,
  2871. new LSL_Float(lifetime/2),
  2872. ScriptBaseClass.PSYS_SRC_OMEGA,
  2873. new LSL_Vector(0, 0, 0)
  2874. };
  2875. llParticleSystem(new LSL_Types.list(list.ToArray()));
  2876. return PScriptSleep(100);
  2877. }
  2878. public DateTime llMakeFire(int particles, double scale, double vel, double lifetime, double arc, string texture,
  2879. LSL_Vector offset)
  2880. {
  2881. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  2882. return DateTime.Now;
  2883. /*llParticleSystem([
  2884. PSYS_PART_FLAGS, PSYS_PART_INTERP_COLOR_MASK | PSYS_PART_INTERP_SCALE_MASK | PSYS_PART_EMISSIVE_MASK | PSYS_PART_WIND_MASK,
  2885. PSYS_SRC_PATTERN, PSYS_SRC_PATTERN_ANGLE_CONE,
  2886. PSYS_PART_START_COLOR, <1.0, 1.0, 1.0>,
  2887. PSYS_PART_END_COLOR, <1.0, 1.0, 1.0>,
  2888. PSYS_PART_START_ALPHA, 0.50,
  2889. PSYS_PART_END_ALPHA, 0.10,
  2890. PSYS_PART_START_SCALE, <particle_scale/2, particle_scale/2, 0.0>,
  2891. PSYS_PART_END_SCALE, <particle_scale, particle_scale, 0.0>,
  2892. PSYS_PART_MAX_AGE, 0.5,
  2893. PSYS_SRC_ACCEL, <0.0, 0.0, 0.0>,
  2894. PSYS_SRC_TEXTURE, source_texture_id,
  2895. PSYS_SRC_BURST_RATE, 5 / particle_count,
  2896. PSYS_SRC_ANGLE_BEGIN, 0.0,
  2897. PSYS_SRC_ANGLE_END, source_cone * PI,
  2898. PSYS_SRC_BURST_PART_COUNT, 1,
  2899. PSYS_SRC_BURST_RADIUS, 0.0,
  2900. PSYS_SRC_BURST_SPEED_MIN, particle_speed,
  2901. PSYS_SRC_BURST_SPEED_MAX, particle_speed,
  2902. PSYS_SRC_MAX_AGE, particle_lifetime / 2,
  2903. PSYS_SRC_OMEGA, <0.0, 0.0, 0.0>
  2904. ]);*/
  2905. List<object> list = new List<object>
  2906. {
  2907. ScriptBaseClass.PSYS_PART_FLAGS,
  2908. ScriptBaseClass.PSYS_PART_INTERP_COLOR_MASK |
  2909. ScriptBaseClass.PSYS_PART_INTERP_SCALE_MASK |
  2910. ScriptBaseClass.PSYS_PART_EMISSIVE_MASK | ScriptBaseClass.PSYS_PART_WIND_MASK,
  2911. ScriptBaseClass.PSYS_SRC_PATTERN,
  2912. ScriptBaseClass.PSYS_SRC_PATTERN_ANGLE_CONE,
  2913. ScriptBaseClass.PSYS_PART_START_COLOR,
  2914. new LSL_Vector(1, 1, 1),
  2915. ScriptBaseClass.PSYS_PART_END_COLOR,
  2916. new LSL_Vector(1, 1, 1),
  2917. ScriptBaseClass.PSYS_PART_START_ALPHA,
  2918. new LSL_Float(0.50),
  2919. ScriptBaseClass.PSYS_PART_END_ALPHA,
  2920. new LSL_Float(0.10),
  2921. ScriptBaseClass.PSYS_PART_START_SCALE,
  2922. new LSL_Vector(scale/2, scale/2, 0),
  2923. ScriptBaseClass.PSYS_PART_END_SCALE,
  2924. new LSL_Vector(scale, scale, 0),
  2925. ScriptBaseClass.PSYS_PART_MAX_AGE,
  2926. new LSL_Float(0.50),
  2927. ScriptBaseClass.PSYS_SRC_ACCEL,
  2928. new LSL_Vector(0, 0, 0),
  2929. ScriptBaseClass.PSYS_SRC_TEXTURE,
  2930. new LSL_String(texture),
  2931. ScriptBaseClass.PSYS_SRC_BURST_RATE,
  2932. new LSL_Float(5/particles),
  2933. ScriptBaseClass.PSYS_SRC_ANGLE_BEGIN,
  2934. new LSL_Float(0.0),
  2935. ScriptBaseClass.PSYS_SRC_ANGLE_END,
  2936. new LSL_Float(arc*Math.PI),
  2937. ScriptBaseClass.PSYS_SRC_BURST_PART_COUNT,
  2938. new LSL_Integer(1),
  2939. ScriptBaseClass.PSYS_SRC_BURST_RADIUS,
  2940. new LSL_Float(0.0),
  2941. ScriptBaseClass.PSYS_SRC_BURST_SPEED_MIN,
  2942. new LSL_Float(vel),
  2943. ScriptBaseClass.PSYS_SRC_BURST_SPEED_MAX,
  2944. new LSL_Float(vel),
  2945. ScriptBaseClass.PSYS_SRC_MAX_AGE,
  2946. new LSL_Float(lifetime/2),
  2947. ScriptBaseClass.PSYS_SRC_OMEGA,
  2948. new LSL_Vector(0, 0, 0)
  2949. };
  2950. llParticleSystem(new LSL_Types.list(list.ToArray()));
  2951. return PScriptSleep(100);
  2952. }
  2953. public DateTime llRezAtRoot(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param)
  2954. {
  2955. return llRezPrim(inventory, pos, vel, rot, param, true, true, true, true);
  2956. }
  2957. /// <summary>
  2958. /// This isn't really an LSL function, just a way to merge llRezAtRoot and llRezObject into one
  2959. /// </summary>
  2960. /// <param name="inventory"></param>
  2961. /// <param name="pos"></param>
  2962. /// <param name="vel"></param>
  2963. /// <param name="rot"></param>
  2964. /// <param name="param"></param>
  2965. /// <param name="isRezAtRoot"></param>
  2966. /// <param name="SetDieAtEdge"></param>
  2967. /// <param name="CheckPos"></param>
  2968. /// <returns></returns>
  2969. public DateTime llRezPrim(string inventory, LSL_Types.Vector3 pos, LSL_Types.Vector3 vel,
  2970. LSL_Types.Quaternion rot, int param, bool isRezAtRoot, bool SetDieAtEdge,
  2971. bool CheckPos)
  2972. {
  2973. return llRezPrim(inventory, pos, vel, rot, param, isRezAtRoot, false, SetDieAtEdge, CheckPos);
  2974. }
  2975. /// <summary>
  2976. /// This isn't really an LSL function, just a way to merge llRezAtRoot and llRezObject into one
  2977. /// </summary>
  2978. /// <param name="inventory"></param>
  2979. /// <param name="pos"></param>
  2980. /// <param name="vel"></param>
  2981. /// <param name="rot"></param>
  2982. /// <param name="param"></param>
  2983. /// <param name="isRezAtRoot"></param>
  2984. /// <param name="doRecoil"></param>
  2985. /// <param name="SetDieAtEdge"></param>
  2986. /// <param name="CheckPos"></param>
  2987. /// <returns></returns>
  2988. public DateTime llRezPrim(string inventory, LSL_Types.Vector3 pos, LSL_Types.Vector3 vel,
  2989. LSL_Types.Quaternion rot, int param, bool isRezAtRoot, bool doRecoil,
  2990. bool SetDieAtEdge, bool CheckPos)
  2991. {
  2992. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.Low, "llRezPrim", m_host, "LSL", m_itemID))
  2993. return DateTime.Now;
  2994. if (m_ScriptEngine.Config.GetBoolean("AllowllRezObject", true))
  2995. {
  2996. if (Double.IsNaN(rot.x) || Double.IsNaN(rot.y) || Double.IsNaN(rot.z) || Double.IsNaN(rot.s))
  2997. return DateTime.Now;
  2998. if (CheckPos)
  2999. {
  3000. float dist = (float) llVecDist(llGetPos(), pos);
  3001. if (dist > m_ScriptDistanceFactor*10.0f)
  3002. return DateTime.Now;
  3003. }
  3004. TaskInventoryDictionary partInventory = (TaskInventoryDictionary) m_host.TaskInventory.Clone();
  3005. foreach (KeyValuePair<UUID, TaskInventoryItem> inv in partInventory)
  3006. {
  3007. if (inv.Value.Name == inventory)
  3008. {
  3009. // make sure we're an object.
  3010. if (inv.Value.InvType != (int) InventoryType.Object)
  3011. {
  3012. llSay(0, "Unable to create requested object. Object is missing from database.");
  3013. return DateTime.Now;
  3014. }
  3015. Vector3 llpos = new Vector3((float) pos.x, (float) pos.y, (float) pos.z);
  3016. Vector3 llvel = new Vector3((float) vel.x, (float) vel.y, (float) vel.z);
  3017. ISceneEntity new_group = RezObject(m_host, inv.Value, llpos, Rot2Quaternion(rot), llvel, param,
  3018. m_host.UUID, isRezAtRoot);
  3019. new_group.OnFinishedPhysicalRepresentationBuilding += delegate()
  3020. {
  3021. //Do this after the physics engine has built the prim
  3022. float groupmass =
  3023. new_group.GetMass();
  3024. //Recoil to the av
  3025. if (m_host.IsAttachment &&
  3026. doRecoil &&
  3027. (new_group.RootChild.Flags &
  3028. PrimFlags.Physics) ==
  3029. PrimFlags.Physics)
  3030. {
  3031. IScenePresence SP =
  3032. m_host.ParentEntity.Scene
  3033. .GetScenePresence(
  3034. m_host.OwnerID);
  3035. if (SP != null)
  3036. {
  3037. //Push the av backwards (For every action, there is an equal, but opposite reaction)
  3038. Vector3 impulse = llvel*
  3039. groupmass;
  3040. impulse.X = impulse.X < 1
  3041. ? impulse
  3042. .X
  3043. : impulse
  3044. .X >
  3045. -1
  3046. ? impulse
  3047. .X
  3048. : -1;
  3049. impulse.Y = impulse.Y < 1
  3050. ? impulse
  3051. .Y
  3052. : impulse
  3053. .Y >
  3054. -1
  3055. ? impulse
  3056. .Y
  3057. : -1;
  3058. impulse.Z = impulse.Z < 1
  3059. ? impulse
  3060. .Z
  3061. : impulse
  3062. .Z >
  3063. -1
  3064. ? impulse
  3065. .Z
  3066. : -1;
  3067. SP.PushForce(impulse);
  3068. }
  3069. }
  3070. };
  3071. // If either of these are null, then there was an unknown error.
  3072. if (new_group == null || new_group.RootChild == null)
  3073. continue;
  3074. // objects rezzed with this method are die_at_edge by default.
  3075. if (SetDieAtEdge)
  3076. new_group.RootChild.SetDieAtEdge(true);
  3077. // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
  3078. return PScriptSleep(100);
  3079. }
  3080. }
  3081. llSay(0, "Could not find object " + inventory);
  3082. }
  3083. return DateTime.Now;
  3084. }
  3085. /// <summary>
  3086. /// Rez an object into the scene from a prim's inventory.
  3087. /// </summary>
  3088. /// <param name="sourcePart"></param>
  3089. /// <param name="item"></param>
  3090. /// <param name="pos"></param>
  3091. /// <param name="rot"></param>
  3092. /// <param name="vel"></param>
  3093. /// <param name="param"></param>
  3094. /// <param name="RezzedFrom"></param>
  3095. /// <param name="RezObjectAtRoot"></param>
  3096. /// <returns>The SceneObjectGroup rezzed or null if rez was unsuccessful</returns>
  3097. public ISceneEntity RezObject(
  3098. ISceneChildEntity sourcePart, TaskInventoryItem item,
  3099. Vector3 pos, Quaternion rot, Vector3 vel, int param, UUID RezzedFrom, bool RezObjectAtRoot)
  3100. {
  3101. if (item != null)
  3102. {
  3103. UUID ownerID = item.OwnerID;
  3104. byte[] rezAsset = World.AssetService.GetData(item.AssetID.ToString());
  3105. if (rezAsset != null)
  3106. {
  3107. string xmlData = Utils.BytesToString(rezAsset);
  3108. ISceneEntity group = SceneEntitySerializer.SceneObjectSerializer.FromOriginalXmlFormat(xmlData,
  3109. World);
  3110. if (group == null)
  3111. return null;
  3112. string reason;
  3113. if (!World.Permissions.CanRezObject(group.ChildrenEntities().Count, ownerID, pos, out reason))
  3114. {
  3115. World.GetScenePresence(ownerID)
  3116. .ControllingClient.SendAlertMessage("You do not have permission to rez objects here: " +
  3117. reason);
  3118. return null;
  3119. }
  3120. List<ISceneChildEntity> partList = group.ChildrenEntities();
  3121. // we set it's position in world.
  3122. // llRezObject sets the whole group at the position, while llRezAtRoot rezzes the group based on the root prim's position
  3123. // See: http://lslwiki.net/lslwiki/wakka.php?wakka=llRezAtRoot
  3124. // Shorthand: llRezAtRoot rezzes the root prim of the group at the position
  3125. // llRezObject rezzes the center of group at the position
  3126. if (RezObjectAtRoot)
  3127. //This sets it right...
  3128. group.AbsolutePosition = pos;
  3129. else
  3130. {
  3131. // center is on average of all positions
  3132. // less root prim position
  3133. #if (!ISWIN)
  3134. Vector3 offset = Vector3.Zero;
  3135. foreach (ISceneChildEntity child in partList)
  3136. {
  3137. offset += child.AbsolutePosition;
  3138. }
  3139. #else
  3140. Vector3 offset = partList.Aggregate(Vector3.Zero,
  3141. (current, child) => current + child.AbsolutePosition);
  3142. #endif
  3143. offset /= partList.Count;
  3144. offset -= group.AbsolutePosition;
  3145. offset += pos;
  3146. group.AbsolutePosition = offset;
  3147. }
  3148. ISceneChildEntity rootPart = group.GetChildPart(group.UUID);
  3149. // Since renaming the item in the inventory does not affect the name stored
  3150. // in the serialization, transfer the correct name from the inventory to the
  3151. // object itself before we rez.
  3152. rootPart.Name = item.Name;
  3153. rootPart.Description = item.Description;
  3154. group.SetGroup(sourcePart.GroupID, group.OwnerID, false);
  3155. if (rootPart.OwnerID != item.OwnerID)
  3156. {
  3157. if (World.Permissions.PropagatePermissions())
  3158. {
  3159. if ((item.CurrentPermissions & 8) != 0)
  3160. {
  3161. foreach (ISceneChildEntity part in partList)
  3162. {
  3163. part.EveryoneMask = item.EveryonePermissions;
  3164. part.NextOwnerMask = item.NextPermissions;
  3165. }
  3166. }
  3167. group.ApplyNextOwnerPermissions();
  3168. }
  3169. }
  3170. foreach (ISceneChildEntity part in partList)
  3171. {
  3172. if (part.OwnerID != item.OwnerID)
  3173. {
  3174. part.LastOwnerID = part.OwnerID;
  3175. part.OwnerID = item.OwnerID;
  3176. part.Inventory.ChangeInventoryOwner(item.OwnerID);
  3177. }
  3178. else if ((item.CurrentPermissions & 8) != 0) // Slam!
  3179. {
  3180. part.EveryoneMask = item.EveryonePermissions;
  3181. part.NextOwnerMask = item.NextPermissions;
  3182. }
  3183. }
  3184. rootPart.TrimPermissions();
  3185. if (group.RootChild.Shape.PCode == (byte) PCode.Prim)
  3186. {
  3187. group.ClearPartAttachmentData();
  3188. }
  3189. group.UpdateGroupRotationR(rot);
  3190. //group.ApplyPhysics(m_physicalPrim);
  3191. World.SceneGraph.AddPrimToScene(group);
  3192. if ((group.RootChild.Flags & PrimFlags.Physics) == PrimFlags.Physics)
  3193. {
  3194. group.RootChild.PhysActor.OnPhysicalRepresentationChanged += delegate
  3195. {
  3196. float groupmass =
  3197. group.GetMass();
  3198. //Apply the velocity to the object
  3199. //llApplyImpulse(new LSL_Vector(llvel.X * groupmass, llvel.Y * groupmass, llvel.Z * groupmass), 0);
  3200. // @Above: Err.... no. Read http://lslwiki.net/lslwiki/wakka.php?wakka=llRezObject
  3201. // Notice the "Creates ("rezzes") object's inventory object centered at position pos (in region coordinates) with velocity vel"
  3202. // This means SET the velocity to X, not just temperarily add it!
  3203. // -- Revolution Smythe
  3204. llSetForce(
  3205. new LSL_Vector(vel*
  3206. groupmass),
  3207. 0);
  3208. group.RootChild.PhysActor
  3209. .ForceSetVelocity(vel*
  3210. groupmass);
  3211. group.RootChild.PhysActor
  3212. .Velocity = vel*
  3213. groupmass;
  3214. };
  3215. }
  3216. group.CreateScriptInstances(param, true, StateSource.ScriptedRez, RezzedFrom, false);
  3217. if (!World.Permissions.BypassPermissions())
  3218. {
  3219. if ((item.CurrentPermissions & (uint) PermissionMask.Copy) == 0)
  3220. sourcePart.Inventory.RemoveInventoryItem(item.ItemID);
  3221. }
  3222. group.ScheduleGroupUpdate(PrimUpdateFlags.FullUpdate);
  3223. return rootPart.ParentEntity;
  3224. }
  3225. }
  3226. return null;
  3227. }
  3228. public DateTime llRezObject(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param)
  3229. {
  3230. return llRezPrim(inventory, pos, vel, rot, param, false, true, true, true);
  3231. }
  3232. public void llLookAt(LSL_Vector target, double strength, double damping)
  3233. {
  3234. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3235. LookAt(target, strength, damping, m_host);
  3236. }
  3237. public void llLinkLookAt(LSL_Integer link, LSL_Vector target, double strength, double damping)
  3238. {
  3239. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3240. List<ISceneChildEntity> parts = GetLinkParts(link);
  3241. foreach (ISceneChildEntity part in parts)
  3242. LookAt(target, strength, damping, part);
  3243. }
  3244. private void LookAt(LSL_Vector target, double strength, double damping, ISceneChildEntity obj)
  3245. {
  3246. // Determine where we are looking from
  3247. LSL_Vector from = new LSL_Vector(obj.GetWorldPosition());
  3248. // Work out the normalised vector from the source to the target
  3249. LSL_Vector delta = llVecNorm(target - from);
  3250. LSL_Vector angle = new LSL_Vector(0, 0, 0)
  3251. {
  3252. x = llAtan2(delta.z, delta.y) - ScriptBaseClass.PI_BY_TWO,
  3253. y = llAtan2(delta.x, llSqrt((delta.y*delta.y) + (delta.z*delta.z)))
  3254. };
  3255. // Calculate the yaw
  3256. // subtracting PI_BY_TWO is required to compensate for the odd SL co-ordinate system
  3257. // Calculate pitch
  3258. // we need to convert from a vector describing
  3259. // the angles of rotation in radians into rotation value
  3260. LSL_Types.Quaternion rot = llEuler2Rot(angle);
  3261. //If the strength is 0, or we are non-physical, set the rotation
  3262. if (strength == 0 || obj.PhysActor == null || !obj.PhysActor.IsPhysical)
  3263. SetLinkRot(obj, rot);
  3264. else
  3265. obj.startLookAt(Rot2Quaternion(rot), (float) strength, (float) damping);
  3266. }
  3267. public void llRotLookAt(LSL_Rotation target, double strength, double damping)
  3268. {
  3269. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3270. Quaternion rot = new Quaternion((float) target.x, (float) target.y, (float) target.z, (float) target.s);
  3271. m_host.RotLookAt(rot, (float) strength, (float) damping);
  3272. }
  3273. public void llLinkRotLookAt(LSL_Integer link, LSL_Rotation target, double strength, double damping)
  3274. {
  3275. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3276. Quaternion rot = new Quaternion((float) target.x, (float) target.y, (float) target.z, (float) target.s);
  3277. List<ISceneChildEntity> parts = GetLinkParts(link);
  3278. foreach (ISceneChildEntity part in parts)
  3279. part.RotLookAt(rot, (float) strength, (float) damping);
  3280. }
  3281. public void llStopLookAt()
  3282. {
  3283. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3284. m_host.StopLookAt();
  3285. }
  3286. public void llSetTimerEvent(double sec)
  3287. {
  3288. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3289. if (sec != 0.0 && sec < m_MinTimerInterval)
  3290. sec = m_MinTimerInterval;
  3291. // Setting timer repeat
  3292. TimerPlugin timerPlugin = (TimerPlugin) m_ScriptEngine.GetScriptPlugin("Timer");
  3293. timerPlugin.SetTimerEvent(m_host.UUID, m_itemID, sec);
  3294. }
  3295. public virtual DateTime llSleep(double sec)
  3296. {
  3297. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  3298. return DateTime.Now;
  3299. return PScriptSleep((int) (sec*1000));
  3300. }
  3301. public LSL_Float llGetObjectMass(string id)
  3302. {
  3303. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  3304. return new LSL_Float();
  3305. UUID key = new UUID();
  3306. if (UUID.TryParse(id, out key))
  3307. {
  3308. try
  3309. {
  3310. ISceneChildEntity obj = World.GetSceneObjectPart(key);
  3311. if (obj != null)
  3312. return obj.GetMass();
  3313. // the object is null so the key is for an avatar
  3314. IScenePresence avatar = World.GetScenePresence(key);
  3315. if (avatar != null)
  3316. if (avatar.IsChildAgent)
  3317. // reference http://www.lslwiki.net/lslwiki/wakka.php?wakka=llGetObjectMass
  3318. // child agents have a mass of 1.0
  3319. return 1;
  3320. else
  3321. return avatar.PhysicsActor.Mass;
  3322. }
  3323. catch (KeyNotFoundException)
  3324. {
  3325. return 0; // The Object/Agent not in the region so just return zero
  3326. }
  3327. }
  3328. return 0;
  3329. }
  3330. public LSL_Float llGetMassMKS()
  3331. {
  3332. return llGetMass()*100;
  3333. }
  3334. public LSL_Float llGetMass()
  3335. {
  3336. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  3337. return new LSL_Float();
  3338. if (m_host.IsAttachment)
  3339. {
  3340. IScenePresence SP = m_host.ParentEntity.Scene.GetScenePresence(m_host.OwnerID);
  3341. return SP != null ? SP.PhysicsActor.Mass : 0.0;
  3342. }
  3343. return m_host.GetMass();
  3344. }
  3345. public void llCollisionFilter(string name, string id, int accept)
  3346. {
  3347. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3348. m_host.CollisionFilter.Clear();
  3349. m_host.CollisionFilter.Add(accept, id ?? name);
  3350. }
  3351. public void llTakeControls(int controls, int accept, int pass_on)
  3352. {
  3353. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3354. TaskInventoryItem item;
  3355. lock (m_host.TaskInventory)
  3356. {
  3357. if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
  3358. return;
  3359. item = m_host.TaskInventory[InventorySelf()];
  3360. }
  3361. if (item.PermsGranter != UUID.Zero)
  3362. {
  3363. IScenePresence presence = World.GetScenePresence(item.PermsGranter);
  3364. if (presence != null)
  3365. {
  3366. if ((item.PermsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0)
  3367. {
  3368. IScriptControllerModule m = presence.RequestModuleInterface<IScriptControllerModule>();
  3369. if (m != null)
  3370. m.RegisterControlEventsToScript(controls, accept, pass_on, m_host, m_itemID);
  3371. }
  3372. }
  3373. }
  3374. }
  3375. public void llReleaseControls()
  3376. {
  3377. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3378. TaskInventoryItem item;
  3379. lock (m_host.TaskInventory)
  3380. {
  3381. if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
  3382. return;
  3383. item = m_host.TaskInventory[InventorySelf()];
  3384. }
  3385. if (item.PermsGranter != UUID.Zero)
  3386. {
  3387. IScenePresence presence = World.GetScenePresence(item.PermsGranter);
  3388. if (presence != null)
  3389. {
  3390. if ((item.PermsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0)
  3391. {
  3392. // Unregister controls from Presence
  3393. IScriptControllerModule m = presence.RequestModuleInterface<IScriptControllerModule>();
  3394. if (m != null)
  3395. m.UnRegisterControlEventsToScript(m_localID, m_itemID);
  3396. // Remove Take Control permission.
  3397. item.PermsMask &= ~ScriptBaseClass.PERMISSION_TAKE_CONTROLS;
  3398. }
  3399. }
  3400. }
  3401. }
  3402. public void llReleaseURL(string url)
  3403. {
  3404. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3405. if (m_UrlModule != null)
  3406. m_UrlModule.ReleaseURL(url);
  3407. }
  3408. /// <summary>
  3409. /// Attach the object containing this script to the avatar that owns it.
  3410. /// </summary>
  3411. /// <returns>true if the attach suceeded, false if it did not</returns>
  3412. public bool AttachToAvatar(int attachmentPoint, bool temp)
  3413. {
  3414. IScenePresence presence = World.GetScenePresence(m_host.OwnerID);
  3415. IAttachmentsModule attachmentsModule = World.RequestModuleInterface<IAttachmentsModule>();
  3416. if (attachmentsModule != null)
  3417. return attachmentsModule.AttachObjectFromInworldObject(m_localID, presence.ControllingClient,
  3418. m_host.ParentEntity, attachmentPoint, temp);
  3419. else
  3420. return false;
  3421. }
  3422. /// <summary>
  3423. /// Detach the object containing this script from the avatar it is attached to.
  3424. /// </summary>
  3425. /// <remarks>
  3426. /// Nothing happens if the object is not attached.
  3427. /// </remarks>
  3428. public void DetachFromAvatar()
  3429. {
  3430. Util.FireAndForget(DetachWrapper, m_host);
  3431. }
  3432. private void DetachWrapper(object o)
  3433. {
  3434. ISceneEntity grp = ((ISceneChildEntity) o).ParentEntity;
  3435. IScenePresence presence = World.GetScenePresence(grp.OwnerID);
  3436. IAttachmentsModule attachmentsModule = World.RequestModuleInterface<IAttachmentsModule>();
  3437. if (attachmentsModule != null)
  3438. attachmentsModule.DetachSingleAttachmentToInventory(grp.GroupID, presence.ControllingClient);
  3439. }
  3440. public void llAttachToAvatarTemp(int attachmentPoint)
  3441. {
  3442. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3443. if (m_host.ParentEntity.RootChild.AttachmentPoint != 0)
  3444. return;
  3445. TaskInventoryItem item;
  3446. lock (m_host.TaskInventory)
  3447. {
  3448. if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
  3449. return;
  3450. item = m_host.TaskInventory[InventorySelf()];
  3451. }
  3452. if (item.PermsGranter != m_host.OwnerID)
  3453. return;
  3454. if ((item.NextPermissions & (uint) PermissionMask.Transfer) != (uint) PermissionMask.Transfer)
  3455. {
  3456. ShoutError("No permission to transfer");
  3457. return;
  3458. }
  3459. if ((item.PermsMask & ScriptBaseClass.PERMISSION_ATTACH) != 0)
  3460. {
  3461. AttachToAvatar(attachmentPoint, true);
  3462. }
  3463. }
  3464. public void llAttachToAvatar(int attachmentPoint)
  3465. {
  3466. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3467. if (m_host.ParentEntity.RootChild.AttachmentPoint != 0)
  3468. return;
  3469. TaskInventoryItem item;
  3470. lock (m_host.TaskInventory)
  3471. {
  3472. if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
  3473. return;
  3474. item = m_host.TaskInventory[InventorySelf()];
  3475. }
  3476. if (item.PermsGranter != m_host.OwnerID)
  3477. return;
  3478. if ((item.PermsMask & ScriptBaseClass.PERMISSION_ATTACH) != 0)
  3479. {
  3480. AttachToAvatar(attachmentPoint, false);
  3481. }
  3482. }
  3483. public void llDetachFromAvatar()
  3484. {
  3485. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3486. if (m_host.ParentEntity.RootChild.AttachmentPoint == 0)
  3487. return;
  3488. TaskInventoryItem item;
  3489. lock (m_host.TaskInventory)
  3490. {
  3491. if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
  3492. return;
  3493. item = m_host.TaskInventory[InventorySelf()];
  3494. }
  3495. if (item.PermsGranter != m_host.OwnerID)
  3496. return;
  3497. if ((item.PermsMask & ScriptBaseClass.PERMISSION_ATTACH) != 0)
  3498. DetachFromAvatar();
  3499. }
  3500. public void llTakeCamera(string avatar)
  3501. {
  3502. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3503. Deprecated("llTakeCamera");
  3504. }
  3505. public void llReleaseCamera(string avatar)
  3506. {
  3507. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3508. Deprecated("llReleaseCamera");
  3509. llClearCameraParams();
  3510. }
  3511. public LSL_String llGetOwner()
  3512. {
  3513. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  3514. return new LSL_String();
  3515. return m_host.OwnerID.ToString();
  3516. }
  3517. public DateTime llInstantMessage(string user, string message)
  3518. {
  3519. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  3520. return DateTime.Now;
  3521. // We may be able to use ClientView.SendInstantMessage here, but we need a client instance.
  3522. // InstantMessageModule.OnInstantMessage searches through a list of scenes for a client matching the toAgent,
  3523. // but I don't think we have a list of scenes available from here.
  3524. // (We also don't want to duplicate the code in OnInstantMessage if we can avoid it.)
  3525. UUID friendTransactionID = UUID.Random();
  3526. GridInstantMessage msg = new GridInstantMessage
  3527. {
  3528. fromAgentID = m_host.UUID,
  3529. toAgentID = UUID.Parse(user),
  3530. imSessionID = friendTransactionID,
  3531. fromAgentName = m_host.Name
  3532. };
  3533. // This is the item we're mucking with here
  3534. // Cap the message length at 1024.
  3535. if (message != null && message.Length > 1024)
  3536. msg.message = message.Substring(0, 1024);
  3537. else
  3538. msg.message = message;
  3539. msg.dialog = (byte) InstantMessageDialog.MessageFromObject;
  3540. msg.fromGroup = false;
  3541. msg.offline = 0;
  3542. msg.ParentEstateID = 0;
  3543. msg.Position = m_host.AbsolutePosition;
  3544. msg.RegionID = World.RegionInfo.RegionID;
  3545. msg.binaryBucket
  3546. = Util.StringToBytes256(
  3547. "{0}/{1}/{2}/{3}",
  3548. World.RegionInfo.RegionName,
  3549. (int) Math.Floor(m_host.AbsolutePosition.X),
  3550. (int) Math.Floor(m_host.AbsolutePosition.Y),
  3551. (int) Math.Floor(m_host.AbsolutePosition.Z));
  3552. if (m_TransferModule != null)
  3553. {
  3554. m_TransferModule.SendInstantMessage(msg);
  3555. }
  3556. return PScriptSleep(2000);
  3557. }
  3558. public DateTime llEmail(string address, string subject, string message)
  3559. {
  3560. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.Low, "llEmail", m_host, "LSL", m_itemID))
  3561. return DateTime.Now;
  3562. IEmailModule emailModule = World.RequestModuleInterface<IEmailModule>();
  3563. if (emailModule == null)
  3564. {
  3565. ShoutError("llEmail: email module not configured");
  3566. return DateTime.Now;
  3567. }
  3568. emailModule.SendEmail(m_host.UUID, address, subject, message, World);
  3569. return PScriptSleep(20000);
  3570. }
  3571. public void llGetNextEmail(string address, string subject)
  3572. {
  3573. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3574. IEmailModule emailModule = World.RequestModuleInterface<IEmailModule>();
  3575. if (emailModule == null)
  3576. {
  3577. ShoutError("llGetNextEmail: email module not configured");
  3578. return;
  3579. }
  3580. emailModule.GetNextEmailAsync(m_host.UUID, address, subject, email =>
  3581. {
  3582. if (email == null)
  3583. return;
  3584. m_ScriptEngine.PostScriptEvent(
  3585. m_itemID, m_host.UUID, "email",
  3586. new Object[]
  3587. {
  3588. new LSL_String(email.time),
  3589. new LSL_String(email.sender)
  3590. ,
  3591. new LSL_String(
  3592. email.subject),
  3593. new LSL_String(
  3594. email.message),
  3595. new LSL_Integer(
  3596. email.numLeft)
  3597. }
  3598. );
  3599. }, World);
  3600. }
  3601. public LSL_String llGetKey()
  3602. {
  3603. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  3604. return m_host.UUID.ToString();
  3605. }
  3606. public void llSetBuoyancy(double buoyancy)
  3607. {
  3608. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3609. if (m_host.ParentEntity != null)
  3610. {
  3611. if (!m_host.ParentEntity.IsDeleted)
  3612. {
  3613. m_host.ParentEntity.RootChild.SetBuoyancy((float) buoyancy);
  3614. }
  3615. }
  3616. }
  3617. /// <summary>
  3618. /// Attempt to clamp the object on the Z axis at the given height over tau seconds.
  3619. /// </summary>
  3620. /// <param name="height">Height to hover. Height of zero disables hover.</param>
  3621. /// <param name="water">False if height is calculated just from ground, otherwise uses ground or water depending on whichever is higher</param>
  3622. /// <param name="tau">Number of seconds over which to reach target</param>
  3623. public void llSetHoverHeight(double height, int water, double tau)
  3624. {
  3625. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3626. if (m_host.PhysActor != null)
  3627. {
  3628. PIDHoverType hoverType = PIDHoverType.Ground;
  3629. if (water != 0)
  3630. {
  3631. hoverType = PIDHoverType.GroundAndWater;
  3632. }
  3633. m_host.SetHoverHeight((float) height, hoverType, (float) tau);
  3634. }
  3635. }
  3636. public void llStopHover()
  3637. {
  3638. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3639. if (m_host.PhysActor != null)
  3640. {
  3641. m_host.SetHoverHeight(0f, PIDHoverType.Ground, 0f);
  3642. }
  3643. }
  3644. public void llMinEventDelay(double delay)
  3645. {
  3646. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3647. m_ScriptEngine.SetMinEventDelay(m_itemID, m_host.UUID, delay);
  3648. }
  3649. /// <summary>
  3650. /// llSoundPreload is deprecated. In SL this appears to do absolutely nothing
  3651. /// and is documented to have no delay.
  3652. /// </summary>
  3653. public void llSoundPreload(string sound)
  3654. {
  3655. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3656. }
  3657. public LSL_Integer llStringLength(string str)
  3658. {
  3659. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  3660. if (str.Length > 0)
  3661. {
  3662. return str.Length;
  3663. }
  3664. return 0;
  3665. }
  3666. public void llStartAnimation(string anim)
  3667. {
  3668. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3669. UUID invItemID = InventorySelf();
  3670. if (invItemID == UUID.Zero)
  3671. return;
  3672. TaskInventoryItem item;
  3673. lock (m_host.TaskInventory)
  3674. {
  3675. if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
  3676. return;
  3677. item = m_host.TaskInventory[InventorySelf()];
  3678. }
  3679. if (item.PermsGranter == UUID.Zero)
  3680. return;
  3681. if ((item.PermsMask & ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION) != 0)
  3682. {
  3683. IScenePresence presence = World.GetScenePresence(item.PermsGranter);
  3684. if (presence != null)
  3685. {
  3686. // Do NOT try to parse UUID, animations cannot be triggered by ID
  3687. UUID animID = InventoryKey(anim, (int) AssetType.Animation);
  3688. if (animID == UUID.Zero)
  3689. {
  3690. if (UUID.TryParse(anim, out animID))
  3691. presence.Animator.AddAnimation(animID, m_host.UUID);
  3692. else
  3693. {
  3694. bool RetVal = presence.Animator.AddAnimation(anim, m_host.UUID);
  3695. if (!RetVal)
  3696. {
  3697. IChatModule chatModule = World.RequestModuleInterface<IChatModule>();
  3698. if (chatModule != null)
  3699. chatModule.SimChat("Could not find animation '" + anim + "'.",
  3700. ChatTypeEnum.DebugChannel, 2147483647, m_host.AbsolutePosition,
  3701. m_host.Name, m_host.UUID, false, World);
  3702. }
  3703. }
  3704. }
  3705. else
  3706. presence.Animator.AddAnimation(animID, m_host.UUID);
  3707. }
  3708. }
  3709. }
  3710. public void llStopAnimation(string anim)
  3711. {
  3712. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3713. UUID invItemID = InventorySelf();
  3714. if (invItemID == UUID.Zero)
  3715. return;
  3716. TaskInventoryItem item;
  3717. lock (m_host.TaskInventory)
  3718. {
  3719. if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
  3720. return;
  3721. item = m_host.TaskInventory[InventorySelf()];
  3722. }
  3723. if (item.PermsGranter == UUID.Zero)
  3724. return;
  3725. if ((item.PermsMask & ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION) != 0)
  3726. {
  3727. UUID animID = new UUID();
  3728. if (!UUID.TryParse(anim, out animID))
  3729. {
  3730. animID = InventoryKey(anim, false);
  3731. }
  3732. IScenePresence presence = World.GetScenePresence(item.PermsGranter);
  3733. if (presence != null)
  3734. {
  3735. if (animID == UUID.Zero)
  3736. {
  3737. if (UUID.TryParse(anim, out animID))
  3738. presence.Animator.RemoveAnimation(animID);
  3739. else
  3740. {
  3741. bool RetVal = presence.Animator.RemoveAnimation(anim);
  3742. if (!RetVal)
  3743. {
  3744. IChatModule chatModule = World.RequestModuleInterface<IChatModule>();
  3745. if (chatModule != null)
  3746. chatModule.SimChat("Could not find animation '" + anim + "'.",
  3747. ChatTypeEnum.DebugChannel, 2147483647, m_host.AbsolutePosition,
  3748. m_host.Name, m_host.UUID, false, World);
  3749. }
  3750. }
  3751. }
  3752. else
  3753. presence.Animator.RemoveAnimation(animID);
  3754. }
  3755. }
  3756. }
  3757. public void llPointAt(LSL_Vector pos)
  3758. {
  3759. }
  3760. public void llStopPointAt()
  3761. {
  3762. }
  3763. public void llTargetOmega(LSL_Vector axis, LSL_Float spinrate, LSL_Float gain)
  3764. {
  3765. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3766. m_host.OmegaAxis = new Vector3((float) axis.x, (float) axis.y, (float) axis.z);
  3767. m_host.OmegaGain = gain;
  3768. m_host.OmegaSpinRate = spinrate;
  3769. m_host.GenerateRotationalVelocityFromOmega();
  3770. ScriptData script = ScriptProtection.GetScript(m_itemID);
  3771. if (script != null)
  3772. script.TargetOmegaWasSet = true;
  3773. m_host.ScheduleTerseUpdate();
  3774. //m_host.SendTerseUpdateToAllClients();
  3775. }
  3776. public LSL_Integer llGetStartParameter()
  3777. {
  3778. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  3779. return m_ScriptEngine.GetStartParameter(m_itemID, m_host.UUID);
  3780. }
  3781. public void llGodLikeRezObject(string inventory, LSL_Vector pos)
  3782. {
  3783. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3784. if (m_ScriptEngine.Config.GetBoolean("AllowGodFunctions", false))
  3785. {
  3786. if (World.Permissions.CanRunConsoleCommand(m_host.OwnerID))
  3787. {
  3788. byte[] asset = World.AssetService.GetData(inventory);
  3789. ISceneEntity group
  3790. = SceneEntitySerializer.SceneObjectSerializer.FromOriginalXmlFormat(UUID.Zero,
  3791. Utils.BytesToString(asset),
  3792. World);
  3793. if (group == null)
  3794. return;
  3795. group.IsDeleted = false;
  3796. foreach (ISceneChildEntity part in group.ChildrenEntities())
  3797. part.IsLoading = false;
  3798. group.OwnerID = m_host.OwnerID;
  3799. group.RootChild.AddFlag(PrimFlags.CreateSelected);
  3800. // If we're rezzing an attachment then don't ask AddNewSceneObject() to update the client since
  3801. // we'll be doing that later on. Scheduling more than one full update during the attachment
  3802. // process causes some clients to fail to display the attachment properly.
  3803. World.SceneGraph.AddPrimToScene(group);
  3804. // if attachment we set it's asset id so object updates can reflect that
  3805. // if not, we set it's position in world.
  3806. group.AbsolutePosition = new Vector3((float) pos.x, (float) pos.y, (float) pos.z);
  3807. IScenePresence SP = World.GetScenePresence(m_host.OwnerID);
  3808. if (SP != null)
  3809. group.SetGroup(m_host.GroupID, SP.UUID, false);
  3810. if (group.RootChild.Shape.PCode == (byte) PCode.Prim)
  3811. group.ClearPartAttachmentData();
  3812. // Fire on_rez
  3813. group.CreateScriptInstances(0, true, StateSource.ScriptedRez, UUID.Zero, false);
  3814. group.ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate);
  3815. }
  3816. }
  3817. }
  3818. public void llRequestPermissions(string agent, int perm)
  3819. {
  3820. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3821. UUID agentID = new UUID();
  3822. if (!UUID.TryParse(agent, out agentID))
  3823. return;
  3824. UUID invItemID = InventorySelf();
  3825. if (invItemID == UUID.Zero)
  3826. return; // Not in a prim? How??
  3827. TaskInventoryItem item;
  3828. lock (m_host.TaskInventory)
  3829. {
  3830. item = m_host.TaskInventory[invItemID];
  3831. }
  3832. if (agentID == UUID.Zero || perm == 0) // Releasing permissions
  3833. {
  3834. llReleaseControls();
  3835. item.PermsGranter = UUID.Zero;
  3836. item.PermsMask = 0;
  3837. m_ScriptEngine.PostScriptEvent(m_itemID, m_host.UUID, new EventParams(
  3838. "run_time_permissions", new Object[]
  3839. {
  3840. new LSL_Integer
  3841. (0)
  3842. },
  3843. new DetectParams[0]), EventPriority.FirstStart);
  3844. return;
  3845. }
  3846. if (item.PermsGranter != agentID || (perm & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0)
  3847. llReleaseControls();
  3848. if (m_host.ParentEntity.IsAttachment && (UUID) agent == m_host.ParentEntity.RootChild.AttachedAvatar)
  3849. {
  3850. // When attached, certain permissions are implicit if requested from owner
  3851. int implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS |
  3852. ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
  3853. ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
  3854. ScriptBaseClass.PERMISSION_ATTACH |
  3855. ScriptBaseClass.PERMISSION_TRACK_CAMERA;
  3856. if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
  3857. {
  3858. lock (m_host.TaskInventory)
  3859. {
  3860. m_host.TaskInventory[invItemID].PermsGranter = agentID;
  3861. m_host.TaskInventory[invItemID].PermsMask = perm;
  3862. }
  3863. m_ScriptEngine.PostScriptEvent(m_itemID, m_host.UUID, new EventParams(
  3864. "run_time_permissions", new Object[]
  3865. {
  3866. new LSL_Integer
  3867. (perm)
  3868. },
  3869. new DetectParams[0]),
  3870. EventPriority.FirstStart);
  3871. return;
  3872. }
  3873. }
  3874. else if (m_host.ParentEntity.SitTargetAvatar.Contains(agentID)) // Sitting avatar
  3875. {
  3876. // When agent is sitting, certain permissions are implicit if requested from sitting agent
  3877. int implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
  3878. ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
  3879. ScriptBaseClass.PERMISSION_TRACK_CAMERA |
  3880. ScriptBaseClass.PERMISSION_TAKE_CONTROLS;
  3881. if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
  3882. {
  3883. lock (m_host.TaskInventory)
  3884. {
  3885. m_host.TaskInventory[invItemID].PermsGranter = agentID;
  3886. m_host.TaskInventory[invItemID].PermsMask = perm;
  3887. }
  3888. m_ScriptEngine.PostScriptEvent(m_itemID, m_host.UUID, new EventParams(
  3889. "run_time_permissions", new Object[]
  3890. {
  3891. new LSL_Integer
  3892. (perm)
  3893. },
  3894. new DetectParams[0]),
  3895. EventPriority.FirstStart);
  3896. return;
  3897. }
  3898. }
  3899. IScenePresence presence = World.GetScenePresence(agentID);
  3900. if (presence != null)
  3901. {
  3902. string ownerName = "";
  3903. IScenePresence ownerPresence = World.GetScenePresence(m_host.ParentEntity.RootChild.OwnerID);
  3904. ownerName = ownerPresence == null ? resolveName(m_host.OwnerID) : ownerPresence.Name;
  3905. if (ownerName == String.Empty)
  3906. ownerName = "(hippos)";
  3907. if (!m_waitingForScriptAnswer)
  3908. {
  3909. lock (m_host.TaskInventory)
  3910. {
  3911. m_host.TaskInventory[invItemID].PermsGranter = agentID;
  3912. m_host.TaskInventory[invItemID].PermsMask = 0;
  3913. }
  3914. presence.ControllingClient.OnScriptAnswer += handleScriptAnswer;
  3915. m_waitingForScriptAnswer = true;
  3916. }
  3917. presence.ControllingClient.SendScriptQuestion(
  3918. m_host.UUID, m_host.ParentEntity.RootChild.Name, ownerName, invItemID, perm);
  3919. return;
  3920. }
  3921. // Requested agent is not in range, refuse perms
  3922. m_ScriptEngine.PostScriptEvent(m_itemID, m_host.UUID, new EventParams(
  3923. "run_time_permissions", new Object[]
  3924. {
  3925. new LSL_Integer(0)
  3926. },
  3927. new DetectParams[0]), EventPriority.FirstStart);
  3928. }
  3929. private void handleScriptAnswer(IClientAPI client, UUID taskID, UUID itemID, int answer)
  3930. {
  3931. if (taskID != m_host.UUID)
  3932. return;
  3933. UUID invItemID = InventorySelf();
  3934. if (invItemID == UUID.Zero)
  3935. return;
  3936. client.OnScriptAnswer -= handleScriptAnswer;
  3937. m_waitingForScriptAnswer = false;
  3938. if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0)
  3939. llReleaseControls();
  3940. lock (m_host.TaskInventory)
  3941. {
  3942. m_host.TaskInventory[invItemID].PermsMask = answer;
  3943. }
  3944. m_ScriptEngine.PostScriptEvent(m_itemID, m_host.UUID, new EventParams(
  3945. "run_time_permissions", new Object[]
  3946. {
  3947. new LSL_Integer(
  3948. answer)
  3949. },
  3950. new DetectParams[0]), EventPriority.FirstStart);
  3951. }
  3952. public LSL_String llGetPermissionsKey()
  3953. {
  3954. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  3955. lock (m_host.TaskInventory)
  3956. {
  3957. foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
  3958. {
  3959. if (item.Type == 10 && item.ItemID == m_itemID)
  3960. {
  3961. return item.PermsGranter.ToString();
  3962. }
  3963. }
  3964. }
  3965. return UUID.Zero.ToString();
  3966. }
  3967. public LSL_Integer llGetPermissions()
  3968. {
  3969. lock (m_host.TaskInventory)
  3970. {
  3971. foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
  3972. {
  3973. if (item.Type == 10 && item.ItemID == m_itemID)
  3974. {
  3975. int perms = item.PermsMask;
  3976. if (m_automaticLinkPermission)
  3977. perms |= ScriptBaseClass.PERMISSION_CHANGE_LINKS;
  3978. return perms;
  3979. }
  3980. }
  3981. }
  3982. return 0;
  3983. }
  3984. public LSL_Integer llGetLinkNumber()
  3985. {
  3986. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  3987. if (m_host.ParentEntity.ChildrenEntities().Count > 1)
  3988. {
  3989. return m_host.LinkNum;
  3990. }
  3991. return 0;
  3992. }
  3993. public void llSetLinkColor(int linknumber, LSL_Vector color, int face)
  3994. {
  3995. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  3996. List<ISceneChildEntity> parts = GetLinkParts(linknumber);
  3997. foreach (ISceneChildEntity part in parts)
  3998. part.SetFaceColor(new Vector3((float) color.x, (float) color.y, (float) color.z), face);
  3999. }
  4000. public DateTime llCreateLink(string target, int parent)
  4001. {
  4002. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  4003. return DateTime.Now;
  4004. UUID invItemID = InventorySelf();
  4005. UUID targetID;
  4006. if (!UUID.TryParse(target, out targetID))
  4007. return DateTime.Now;
  4008. TaskInventoryItem item;
  4009. lock (m_host.TaskInventory)
  4010. {
  4011. item = m_host.TaskInventory[invItemID];
  4012. }
  4013. if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
  4014. && !m_automaticLinkPermission)
  4015. {
  4016. ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
  4017. return DateTime.Now;
  4018. }
  4019. IClientAPI client = null;
  4020. IScenePresence sp = World.GetScenePresence(item.PermsGranter);
  4021. if (sp != null)
  4022. client = sp.ControllingClient;
  4023. ISceneChildEntity targetPart = World.GetSceneObjectPart(targetID);
  4024. if (targetPart.ParentEntity.RootChild.AttachmentPoint != 0)
  4025. return DateTime.Now;
  4026. // Fail silently if attached
  4027. ISceneEntity parentPrim = null;
  4028. ISceneEntity childPrim = null;
  4029. if (parent != 0)
  4030. {
  4031. parentPrim = m_host.ParentEntity;
  4032. childPrim = targetPart.ParentEntity;
  4033. }
  4034. else
  4035. {
  4036. parentPrim = targetPart.ParentEntity;
  4037. childPrim = m_host.ParentEntity;
  4038. }
  4039. // byte uf = childPrim.RootPart.UpdateFlag;
  4040. parentPrim.LinkToGroup(childPrim);
  4041. // if (uf != (Byte)0)
  4042. // parent.RootPart.UpdateFlag = uf;
  4043. parentPrim.TriggerScriptChangedEvent(Changed.LINK);
  4044. parentPrim.RootChild.CreateSelected = true;
  4045. parentPrim.ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate);
  4046. if (client != null)
  4047. parentPrim.GetProperties(client);
  4048. return PScriptSleep(1000);
  4049. }
  4050. public void llBreakLink(int linknum)
  4051. {
  4052. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  4053. UUID invItemID = InventorySelf();
  4054. lock (m_host.TaskInventory)
  4055. {
  4056. if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
  4057. && !m_automaticLinkPermission)
  4058. {
  4059. ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
  4060. return;
  4061. }
  4062. }
  4063. if (linknum < ScriptBaseClass.LINK_THIS)
  4064. return;
  4065. ISceneEntity parentPrim = m_host.ParentEntity;
  4066. if (parentPrim.RootChild.AttachmentPoint != 0)
  4067. return; // Fail silently if attached
  4068. ISceneChildEntity childPrim = null;
  4069. if (linknum == ScriptBaseClass.LINK_ROOT)
  4070. {
  4071. }
  4072. else if (linknum == ScriptBaseClass.LINK_SET ||
  4073. ScriptBaseClass.LINK_ALL_OTHERS ||
  4074. ScriptBaseClass.LINK_ALL_CHILDREN ||
  4075. ScriptBaseClass.LINK_THIS)
  4076. {
  4077. foreach (ISceneChildEntity part in parentPrim.ChildrenEntities())
  4078. {
  4079. if (part.UUID != m_host.UUID)
  4080. {
  4081. childPrim = part;
  4082. break;
  4083. }
  4084. }
  4085. }
  4086. else
  4087. {
  4088. IEntity target = m_host.ParentEntity.GetLinkNumPart(linknum);
  4089. if (target is ISceneChildEntity)
  4090. {
  4091. childPrim = target as ISceneChildEntity;
  4092. }
  4093. else
  4094. return;
  4095. if (childPrim.UUID == m_host.UUID)
  4096. childPrim = null;
  4097. }
  4098. if (linknum == ScriptBaseClass.LINK_ROOT)
  4099. {
  4100. // Restructuring Multiple Prims.
  4101. List<ISceneChildEntity> parts = new List<ISceneChildEntity>(parentPrim.ChildrenEntities());
  4102. parts.Remove(parentPrim.RootChild);
  4103. foreach (ISceneChildEntity part in parts)
  4104. {
  4105. parentPrim.DelinkFromGroup(part, true);
  4106. }
  4107. parentPrim.ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate);
  4108. parentPrim.TriggerScriptChangedEvent(Changed.LINK);
  4109. if (parts.Count > 0)
  4110. {
  4111. ISceneChildEntity newRoot = parts[0];
  4112. parts.Remove(newRoot);
  4113. foreach (ISceneChildEntity part in parts)
  4114. {
  4115. newRoot.ParentEntity.LinkToGroup(part.ParentEntity);
  4116. }
  4117. newRoot.ParentEntity.ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate);
  4118. }
  4119. }
  4120. else
  4121. {
  4122. if (childPrim == null)
  4123. return;
  4124. parentPrim.DelinkFromGroup(childPrim, true);
  4125. childPrim.ParentEntity.ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate);
  4126. parentPrim.ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate);
  4127. parentPrim.TriggerScriptChangedEvent(Changed.LINK);
  4128. }
  4129. }
  4130. public void llBreakAllLinks()
  4131. {
  4132. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  4133. ISceneEntity parentPrim = m_host.ParentEntity;
  4134. if (parentPrim.RootChild.AttachmentPoint != 0)
  4135. return; // Fail silently if attached
  4136. List<ISceneChildEntity> parts = new List<ISceneChildEntity>(parentPrim.ChildrenEntities());
  4137. parts.Remove(parentPrim.RootChild);
  4138. foreach (ISceneChildEntity part in parts)
  4139. {
  4140. parentPrim.DelinkFromGroup(part, true);
  4141. parentPrim.TriggerScriptChangedEvent(Changed.LINK);
  4142. part.ParentEntity.ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate);
  4143. }
  4144. parentPrim.ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate);
  4145. }
  4146. public LSL_String llGetLinkKey(int linknum)
  4147. {
  4148. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  4149. IEntity target = m_host.ParentEntity.GetLinkNumPart(linknum);
  4150. if (target != null)
  4151. {
  4152. return target.UUID.ToString();
  4153. }
  4154. return UUID.Zero.ToString();
  4155. }
  4156. /// <summary>
  4157. /// The rules governing the returned name are not simple. The only
  4158. /// time a blank name is returned is if the target prim has a blank
  4159. /// name. If no prim with the given link number can be found then
  4160. /// usually NULL_KEY is returned but there are exceptions.
  4161. /// In a single unlinked prim, A call with 0 returns the name, all
  4162. /// other values for link number return NULL_KEY
  4163. /// In link sets it is more complicated.
  4164. /// If the script is in the root prim:-
  4165. /// A zero link number returns NULL_KEY.
  4166. /// Positive link numbers return the name of the prim, or NULL_KEY
  4167. /// if a prim does not exist at that position.
  4168. /// Negative link numbers return the name of the first child prim.
  4169. /// If the script is in a child prim:-
  4170. /// Link numbers 0 or 1 return the name of the root prim.
  4171. /// Positive link numbers return the name of the prim or NULL_KEY
  4172. /// if a prim does not exist at that position.
  4173. /// Negative numbers return the name of the root prim.
  4174. /// References
  4175. /// http://lslwiki.net/lslwiki/wakka.php?wakka=llGetLinkName
  4176. /// Mentions NULL_KEY being returned
  4177. /// http://wiki.secondlife.com/wiki/LlGetLinkName
  4178. /// Mentions using the LINK_* constants, some of which are negative
  4179. /// </summary>
  4180. public LSL_String llGetLinkName(int linknum)
  4181. {
  4182. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  4183. // simplest case, this prims link number
  4184. if (linknum == m_host.LinkNum)
  4185. return m_host.Name;
  4186. // Single prim
  4187. if (m_host.LinkNum == 0)
  4188. {
  4189. if (linknum == 1)
  4190. return m_host.Name;
  4191. IEntity entity = m_host.ParentEntity.GetLinkNumPart(linknum);
  4192. if (entity != null)
  4193. return entity.Name;
  4194. return UUID.Zero.ToString();
  4195. }
  4196. // Link set
  4197. IEntity part = null;
  4198. part = m_host.LinkNum == 1
  4199. ? m_host.ParentEntity.GetLinkNumPart(linknum < 0 ? 2 : linknum)
  4200. : m_host.ParentEntity.GetLinkNumPart(linknum < 2 ? 1 : linknum);
  4201. if (part != null)
  4202. return part.Name;
  4203. return UUID.Zero.ToString();
  4204. }
  4205. public LSL_Integer llGetInventoryNumber(int type)
  4206. {
  4207. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  4208. int count = 0;
  4209. lock (m_host.TaskInventory)
  4210. {
  4211. #if (!ISWIN)
  4212. foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
  4213. if (item.Type == type || type == -1)
  4214. count++;
  4215. #else
  4216. count += m_host.TaskInventory.Values.Count(item => item.Type == type || type == -1);
  4217. #endif
  4218. }
  4219. return count;
  4220. }
  4221. public LSL_String llGetInventoryName(int type, int number)
  4222. {
  4223. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  4224. ArrayList keys = new ArrayList();
  4225. lock (m_host.TaskInventory)
  4226. {
  4227. foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
  4228. {
  4229. if (inv.Value.Type == type || type == -1)
  4230. {
  4231. keys.Add(inv.Value.Name);
  4232. }
  4233. }
  4234. }
  4235. if (keys.Count == 0)
  4236. return String.Empty;
  4237. keys.Sort();
  4238. if (keys.Count > number)
  4239. {
  4240. return (string) keys[number];
  4241. }
  4242. return String.Empty;
  4243. }
  4244. public LSL_Float llGetEnergy()
  4245. {
  4246. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  4247. return new LSL_Float();
  4248. return 1.0f;
  4249. }
  4250. public DateTime llGiveInventory(string destination, string inventory)
  4251. {
  4252. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  4253. return DateTime.Now;
  4254. bool found = false;
  4255. UUID destId = UUID.Zero;
  4256. UUID objId = UUID.Zero;
  4257. int assetType = 0;
  4258. string objName = String.Empty;
  4259. if (!UUID.TryParse(destination, out destId))
  4260. {
  4261. llSay(0, "Could not parse key " + destination);
  4262. return DateTime.Now;
  4263. }
  4264. // move the first object found with this inventory name
  4265. lock (m_host.TaskInventory)
  4266. {
  4267. foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
  4268. {
  4269. if (inv.Value.Name == inventory)
  4270. {
  4271. found = true;
  4272. objId = inv.Key;
  4273. assetType = inv.Value.Type;
  4274. objName = inv.Value.Name;
  4275. break;
  4276. }
  4277. }
  4278. }
  4279. if (!found)
  4280. {
  4281. llSay(0, String.Format("Could not find object '{0}'", inventory));
  4282. throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory));
  4283. }
  4284. // check if destination is an avatar
  4285. if (World.GetScenePresence(destId) != null ||
  4286. m_host.ParentEntity.Scene.RequestModuleInterface<IAgentInfoService>().GetUserInfo(destId.ToString()) !=
  4287. null)
  4288. {
  4289. // destination is an avatar
  4290. InventoryItemBase agentItem = null;
  4291. ILLClientInventory inventoryModule = World.RequestModuleInterface<ILLClientInventory>();
  4292. if (inventoryModule != null)
  4293. agentItem = inventoryModule.MoveTaskInventoryItemToUserInventory(destId, UUID.Zero, m_host, objId,
  4294. false);
  4295. if (agentItem == null)
  4296. return DateTime.Now;
  4297. byte[] bucket = new byte[17];
  4298. bucket[0] = (byte) assetType;
  4299. byte[] objBytes = agentItem.ID.GetBytes();
  4300. Array.Copy(objBytes, 0, bucket, 1, 16);
  4301. GridInstantMessage msg = new GridInstantMessage(World,
  4302. m_host.UUID, m_host.Name + ", an object owned by " +
  4303. resolveName(m_host.OwnerID) + ",", destId,
  4304. (byte) InstantMessageDialog.InventoryOffered,
  4305. false,
  4306. objName + "'\n'" + m_host.Name + "' is located at " +
  4307. m_host.AbsolutePosition.ToString() + " in '" +
  4308. World.RegionInfo.RegionName,
  4309. agentItem.ID, true, m_host.AbsolutePosition,
  4310. bucket);
  4311. if (m_TransferModule != null)
  4312. m_TransferModule.SendInstantMessage(msg);
  4313. }
  4314. else
  4315. {
  4316. // destination is an object
  4317. ILLClientInventory inventoryModule = World.RequestModuleInterface<ILLClientInventory>();
  4318. if (inventoryModule != null)
  4319. inventoryModule.MoveTaskInventoryItemToObject(destId, m_host, objId);
  4320. }
  4321. return PScriptSleep(3000);
  4322. }
  4323. public void llRemoveInventory(string name)
  4324. {
  4325. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  4326. lock (m_host.TaskInventory)
  4327. {
  4328. foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
  4329. {
  4330. if (item.Name == name)
  4331. {
  4332. if (item.ItemID == m_itemID)
  4333. throw new ScriptDeleteException();
  4334. m_host.Inventory.RemoveInventoryItem(item.ItemID);
  4335. return;
  4336. }
  4337. }
  4338. }
  4339. }
  4340. public void llSetText(string text, LSL_Vector color, LSL_Float alpha)
  4341. {
  4342. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  4343. Vector3 av3 = new Vector3(Util.Clip((float) color.x, 0.0f, 1.0f),
  4344. Util.Clip((float) color.y, 0.0f, 1.0f),
  4345. Util.Clip((float) color.z, 0.0f, 1.0f));
  4346. m_host.SetText(text.Length > 254 ? text.Remove(254) : text, av3, Util.Clip((float) alpha, 0.0f, 1.0f));
  4347. //m_host.ParentGroup.HasGroupChanged = true;
  4348. //m_host.ParentGroup.ScheduleGroupForFullUpdate();
  4349. }
  4350. public LSL_Float llWater(LSL_Vector offset)
  4351. {
  4352. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  4353. return new LSL_Float();
  4354. return World.RegionInfo.RegionSettings.WaterHeight;
  4355. }
  4356. public void llPassTouches(int pass)
  4357. {
  4358. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  4359. m_host.PassTouch = pass;
  4360. }
  4361. public LSL_Key llRequestAgentData(string id, int data)
  4362. {
  4363. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  4364. UUID uuid = (UUID) id;
  4365. UserInfo pinfo = null;
  4366. UserAccount account;
  4367. UserInfoCacheEntry ce;
  4368. if (!m_userInfoCache.TryGetValue(uuid, out ce))
  4369. {
  4370. account = World.UserAccountService.GetUserAccount(World.RegionInfo.AllScopeIDs, uuid);
  4371. if (account == null)
  4372. {
  4373. m_userInfoCache[uuid] = null; // Cache negative
  4374. return UUID.Zero.ToString();
  4375. }
  4376. ce = new UserInfoCacheEntry {time = Util.EnvironmentTickCount(), account = account};
  4377. pinfo = World.RequestModuleInterface<IAgentInfoService>().GetUserInfo(uuid.ToString());
  4378. ce.pinfo = pinfo;
  4379. m_userInfoCache[uuid] = ce;
  4380. }
  4381. else
  4382. {
  4383. if (ce == null)
  4384. {
  4385. return UUID.Zero.ToString();
  4386. }
  4387. account = ce.account;
  4388. pinfo = ce.pinfo;
  4389. }
  4390. if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) >= 20000)
  4391. {
  4392. ce.time = Util.EnvironmentTickCount();
  4393. ce.pinfo = World.RequestModuleInterface<IAgentInfoService>().GetUserInfo(uuid.ToString());
  4394. pinfo = ce.pinfo;
  4395. }
  4396. string reply = String.Empty;
  4397. switch (data)
  4398. {
  4399. case 1: // DATA_ONLINE (0|1)
  4400. if (pinfo != null && pinfo.IsOnline)
  4401. reply = "1";
  4402. else
  4403. reply = "0";
  4404. break;
  4405. case 2: // DATA_NAME (First Last)
  4406. reply = account.Name;
  4407. break;
  4408. case 3: // DATA_BORN (YYYY-MM-DD)
  4409. DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0);
  4410. born = born.AddSeconds(account.Created);
  4411. reply = born.ToString("yyyy-MM-dd");
  4412. break;
  4413. case 4: // DATA_RATING (0,0,0,0,0,0)
  4414. reply = "0,0,0,0,0,0";
  4415. break;
  4416. case 8: // DATA_PAYINFO (0|1|2|3)
  4417. if ((account.UserFlags & ScriptBaseClass.PAYMENT_INFO_ON_FILE) ==
  4418. ScriptBaseClass.PAYMENT_INFO_ON_FILE)
  4419. reply = ScriptBaseClass.PAYMENT_INFO_ON_FILE.ToString();
  4420. if ((account.UserFlags & ScriptBaseClass.PAYMENT_INFO_USED) == ScriptBaseClass.PAYMENT_INFO_USED)
  4421. reply = ScriptBaseClass.PAYMENT_INFO_USED.ToString();
  4422. reply = "0";
  4423. break;
  4424. default:
  4425. return UUID.Zero.ToString(); // Raise no event
  4426. }
  4427. UUID rq = UUID.Random();
  4428. DataserverPlugin dataserverPlugin = (DataserverPlugin) m_ScriptEngine.GetScriptPlugin("Dataserver");
  4429. UUID tid = dataserverPlugin.RegisterRequest(m_host.UUID,
  4430. m_itemID, rq.ToString());
  4431. dataserverPlugin.AddReply(rq.ToString(), reply, 100);
  4432. ScriptSleep(200);
  4433. return tid.ToString();
  4434. }
  4435. public LSL_Key llRequestInventoryData(string name)
  4436. {
  4437. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  4438. TaskInventoryDictionary itemDictionary = (TaskInventoryDictionary) m_host.TaskInventory.Clone();
  4439. foreach (TaskInventoryItem item in itemDictionary.Values)
  4440. {
  4441. if (item.Type == 3 && item.Name == name)
  4442. {
  4443. UUID rq = UUID.Random();
  4444. DataserverPlugin dataserverPlugin = (DataserverPlugin) m_ScriptEngine.GetScriptPlugin("Dataserver");
  4445. UUID tid = dataserverPlugin.RegisterRequest(m_host.UUID,
  4446. m_itemID, rq.ToString());
  4447. Vector3 region = new Vector3(
  4448. World.RegionInfo.RegionLocX,
  4449. World.RegionInfo.RegionLocY,
  4450. 0);
  4451. World.AssetService.Get(item.AssetID.ToString(), this,
  4452. delegate(string i, object sender, AssetBase a)
  4453. {
  4454. AssetLandmark lm = new AssetLandmark(a);
  4455. float rx = (uint) (lm.RegionHandle >> 32);
  4456. float ry = (uint) lm.RegionHandle;
  4457. region = lm.Position + new Vector3(rx, ry, 0) - region;
  4458. string reply = region.ToString();
  4459. dataserverPlugin.AddReply(rq.ToString(),
  4460. reply, 1000);
  4461. });
  4462. ScriptSleep(1000);
  4463. return tid.ToString();
  4464. }
  4465. }
  4466. ScriptSleep(1000);
  4467. return String.Empty;
  4468. }
  4469. public void llSetDamage(double damage)
  4470. {
  4471. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  4472. m_host.ParentEntity.Damage = (float) damage;
  4473. ICombatModule combatModule = World.RequestModuleInterface<ICombatModule>();
  4474. if (combatModule != null)
  4475. combatModule.AddDamageToPrim(m_host.ParentEntity);
  4476. }
  4477. public DateTime llTeleportAgentHome(LSL_Key _agent)
  4478. {
  4479. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  4480. return DateTime.Now;
  4481. string agent = _agent.ToString();
  4482. UUID agentId = new UUID();
  4483. if (UUID.TryParse(agent, out agentId))
  4484. {
  4485. IScenePresence presence = World.GetScenePresence(agentId);
  4486. if (presence != null)
  4487. {
  4488. // agent must be over the owners land
  4489. IParcelManagementModule parcelManagement = World.RequestModuleInterface<IParcelManagementModule>();
  4490. if (parcelManagement != null)
  4491. {
  4492. if (m_host.OwnerID != parcelManagement.GetLandObject(
  4493. presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID &&
  4494. !World.Permissions.CanIssueEstateCommand(m_host.OwnerID, false))
  4495. {
  4496. return PScriptSleep(5000);
  4497. }
  4498. }
  4499. //Send disable cancel so that the agent cannot attempt to stay in the region
  4500. presence.ControllingClient.SendTeleportStart((uint) TeleportFlags.DisableCancel);
  4501. IEntityTransferModule transferModule = World.RequestModuleInterface<IEntityTransferModule>();
  4502. if (transferModule != null)
  4503. transferModule.TeleportHome(agentId, presence.ControllingClient);
  4504. else
  4505. presence.ControllingClient.SendTeleportFailed("Unable to perform teleports on this simulator.");
  4506. }
  4507. }
  4508. return PScriptSleep(5000);
  4509. }
  4510. public DateTime llTextBox(string agent, string message, int chatChannel)
  4511. {
  4512. IDialogModule dm = World.RequestModuleInterface<IDialogModule>();
  4513. if (dm == null)
  4514. return DateTime.Now;
  4515. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  4516. return DateTime.Now;
  4517. UUID av = new UUID();
  4518. if (!UUID.TryParse(agent, out av))
  4519. {
  4520. LSLError("First parameter to llDialog needs to be a key");
  4521. return DateTime.Now;
  4522. }
  4523. if (message != null && message.Length > 1024)
  4524. message = message.Substring(0, 1024);
  4525. dm.SendTextBoxToUser(av, message, chatChannel, m_host.Name, m_host.UUID, m_host.OwnerID);
  4526. return PScriptSleep(1000);
  4527. }
  4528. public void llModifyLand(int action, int brush)
  4529. {
  4530. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  4531. ITerrainModule tm = World.RequestModuleInterface<ITerrainModule>();
  4532. if (tm != null)
  4533. {
  4534. tm.ModifyTerrain(m_host.OwnerID, m_host.AbsolutePosition, (byte) brush, (byte) action, m_host.OwnerID);
  4535. }
  4536. }
  4537. public void llCollisionSound(string impact_sound, double impact_volume)
  4538. {
  4539. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  4540. UUID soundId = UUID.Zero;
  4541. if (!UUID.TryParse(impact_sound, out soundId))
  4542. {
  4543. lock (m_host.TaskInventory)
  4544. {
  4545. foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
  4546. {
  4547. if (item.Type == (int) AssetType.Sound && item.Name == impact_sound)
  4548. {
  4549. soundId = item.AssetID;
  4550. break;
  4551. }
  4552. }
  4553. }
  4554. }
  4555. //We do allow UUID.Zero here for scripts that want to disable the collision sound (such as "")
  4556. m_host.CollisionSound = soundId;
  4557. m_host.CollisionSoundVolume = (float) impact_volume;
  4558. }
  4559. public void llCollisionSprite(string impact_sprite)
  4560. {
  4561. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  4562. // Since this is broken in SL, we can do this however we want, until they fix it.
  4563. m_host.CollisionSprite = UUID.Parse(impact_sprite);
  4564. }
  4565. public LSL_String llGetAnimation(string id)
  4566. {
  4567. // This should only return a value if the avatar is in the same region
  4568. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  4569. UUID avatar = (UUID) id;
  4570. IScenePresence presence = World.GetScenePresence(avatar);
  4571. if (presence == null)
  4572. return "";
  4573. if (m_host.ParentEntity.Scene.RegionInfo.RegionHandle == presence.Scene.RegionInfo.RegionHandle)
  4574. {
  4575. Dictionary<UUID, string> animationstateNames = AnimationSet.Animations.AnimStateNames;
  4576. AnimationSet currentAnims = presence.Animator.Animations;
  4577. string currentAnimationState = String.Empty;
  4578. if (animationstateNames.TryGetValue(currentAnims.ImplicitDefaultAnimation.AnimID,
  4579. out currentAnimationState))
  4580. return currentAnimationState;
  4581. }
  4582. return String.Empty;
  4583. }
  4584. public void llMessageLinked(int linknumber, int num, string msg, string id)
  4585. {
  4586. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  4587. List<ISceneChildEntity> parts = GetLinkParts(linknumber);
  4588. foreach (ISceneChildEntity part in parts)
  4589. {
  4590. int linkNumber = m_host.LinkNum;
  4591. if (m_host.ParentEntity.ChildrenEntities().Count == 1)
  4592. linkNumber = 0;
  4593. object[] resobj = new object[]
  4594. {
  4595. new LSL_Integer(linkNumber), new LSL_Integer(num), new LSL_String(msg),
  4596. new LSL_String(id)
  4597. };
  4598. m_ScriptEngine.PostObjectEvent(part.UUID, "link_message", resobj);
  4599. }
  4600. }
  4601. public void llPushObject(string target, LSL_Vector impulse, LSL_Vector ang_impulse, int local)
  4602. {
  4603. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  4604. bool pushAllowed = false;
  4605. bool pusheeIsAvatar = false;
  4606. UUID targetID = UUID.Zero;
  4607. if (!UUID.TryParse(target, out targetID))
  4608. return;
  4609. IScenePresence pusheeav = null;
  4610. Vector3 PusheePos = Vector3.Zero;
  4611. ISceneChildEntity pusheeob = null;
  4612. IScenePresence avatar = World.GetScenePresence(targetID);
  4613. if (avatar != null)
  4614. {
  4615. pusheeIsAvatar = true;
  4616. // Pushee is in GodMode this pushing object isn't owned by them
  4617. if (avatar.GodLevel > 0 && m_host.OwnerID != targetID)
  4618. return;
  4619. pusheeav = avatar;
  4620. // Find pushee position
  4621. // Pushee Linked?
  4622. if (pusheeav.ParentID != UUID.Zero)
  4623. {
  4624. ISceneChildEntity parentobj = World.GetSceneObjectPart(pusheeav.ParentID);
  4625. PusheePos = parentobj != null ? parentobj.AbsolutePosition : pusheeav.AbsolutePosition;
  4626. }
  4627. else
  4628. {
  4629. PusheePos = pusheeav.AbsolutePosition;
  4630. }
  4631. }
  4632. if (!pusheeIsAvatar)
  4633. {
  4634. // not an avatar so push is not affected by parcel flags
  4635. pusheeob = World.GetSceneObjectPart(UUID.Parse(target));
  4636. // We can't find object
  4637. if (pusheeob == null)
  4638. return;
  4639. // Object not pushable. Not an attachment and has no physics component
  4640. if (!pusheeob.IsAttachment && pusheeob.PhysActor == null)
  4641. return;
  4642. PusheePos = pusheeob.AbsolutePosition;
  4643. pushAllowed = true;
  4644. }
  4645. else
  4646. {
  4647. IParcelManagementModule parcelManagement = World.RequestModuleInterface<IParcelManagementModule>();
  4648. if (World.RegionInfo.RegionSettings.RestrictPushing)
  4649. {
  4650. pushAllowed = m_host.OwnerID == targetID ||
  4651. m_host.ParentEntity.Scene.Permissions.IsGod(m_host.OwnerID);
  4652. }
  4653. else
  4654. {
  4655. if (parcelManagement != null)
  4656. {
  4657. ILandObject targetlandObj = parcelManagement.GetLandObject(PusheePos.X, PusheePos.Y);
  4658. if (targetlandObj == null)
  4659. // We didn't find the parcel but region isn't push restricted so assume it's ok
  4660. pushAllowed = true;
  4661. else
  4662. {
  4663. // Parcel push restriction
  4664. pushAllowed = (targetlandObj.LandData.Flags & (uint) ParcelFlags.RestrictPushObject) !=
  4665. (uint) ParcelFlags.RestrictPushObject ||
  4666. m_host.ParentEntity.Scene.Permissions.CanPushObject(m_host.OwnerID,
  4667. targetlandObj);
  4668. }
  4669. }
  4670. }
  4671. }
  4672. if (pushAllowed)
  4673. {
  4674. float distance = (PusheePos - m_host.AbsolutePosition).Length();
  4675. float distance_term = distance*distance*distance; // Script Energy
  4676. float pusher_mass = m_host.GetMass();
  4677. const float PUSH_ATTENUATION_DISTANCE = 17f;
  4678. const float PUSH_ATTENUATION_SCALE = 5f;
  4679. float distance_attenuation = 1f;
  4680. if (distance > PUSH_ATTENUATION_DISTANCE)
  4681. {
  4682. float normalized_units = 1f + (distance - PUSH_ATTENUATION_DISTANCE)/PUSH_ATTENUATION_SCALE;
  4683. distance_attenuation = 1f/normalized_units;
  4684. }
  4685. Vector3 applied_linear_impulse = new Vector3((float) impulse.x, (float) impulse.y, (float) impulse.z);
  4686. {
  4687. float impulse_length = applied_linear_impulse.Length();
  4688. float desired_energy = impulse_length*pusher_mass;
  4689. if (desired_energy > 0f)
  4690. desired_energy += distance_term;
  4691. float scaling_factor = 1f;
  4692. scaling_factor *= distance_attenuation;
  4693. applied_linear_impulse *= scaling_factor;
  4694. }
  4695. if (pusheeIsAvatar)
  4696. {
  4697. if (pusheeav != null)
  4698. {
  4699. PhysicsActor pa = pusheeav.PhysicsActor;
  4700. if (pa != null)
  4701. {
  4702. if (local != 0)
  4703. {
  4704. applied_linear_impulse *= m_host.GetWorldRotation();
  4705. }
  4706. //Put a limit on it...
  4707. int MaxPush = (int) pusheeav.PhysicsActor.Mass*25;
  4708. if (applied_linear_impulse.X > 0 &&
  4709. Math.Abs(applied_linear_impulse.X) > MaxPush)
  4710. applied_linear_impulse.X = MaxPush;
  4711. if (applied_linear_impulse.X < 0 &&
  4712. Math.Abs(applied_linear_impulse.X) > MaxPush)
  4713. applied_linear_impulse.X = -MaxPush;
  4714. if (applied_linear_impulse.Y > 0 &&
  4715. Math.Abs(applied_linear_impulse.X) > MaxPush)
  4716. applied_linear_impulse.Y = MaxPush;
  4717. if (applied_linear_impulse.Y < 0 &&
  4718. Math.Abs(applied_linear_impulse.X) > MaxPush)
  4719. applied_linear_impulse.Y = -MaxPush;
  4720. if (applied_linear_impulse.Z > 0 &&
  4721. Math.Abs(applied_linear_impulse.X) > MaxPush)
  4722. applied_linear_impulse.Z = MaxPush;
  4723. if (applied_linear_impulse.Z < 0 &&
  4724. Math.Abs(applied_linear_impulse.Z) > MaxPush)
  4725. applied_linear_impulse.Z = -MaxPush;
  4726. pa.AddForce(applied_linear_impulse, true);
  4727. }
  4728. }
  4729. }
  4730. else
  4731. {
  4732. if (pusheeob.PhysActor != null)
  4733. {
  4734. pusheeob.ApplyImpulse(applied_linear_impulse, local != 0);
  4735. }
  4736. }
  4737. }
  4738. }
  4739. public void llPassCollisions(int pass)
  4740. {
  4741. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  4742. m_host.PassCollisions = pass;
  4743. }
  4744. public LSL_String llGetScriptName()
  4745. {
  4746. string result = String.Empty;
  4747. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  4748. lock (m_host.TaskInventory)
  4749. {
  4750. foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
  4751. {
  4752. if (item.Type == 10 && item.ItemID == m_itemID)
  4753. {
  4754. result = item.Name ?? String.Empty;
  4755. break;
  4756. }
  4757. }
  4758. }
  4759. return result;
  4760. }
  4761. public LSL_Integer llGetNumberOfSides()
  4762. {
  4763. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  4764. return GetNumberOfSides(m_host);
  4765. }
  4766. protected int GetNumberOfSides(ISceneChildEntity part)
  4767. {
  4768. int sides = part.GetNumberOfSides();
  4769. if (part.GetPrimType() == PrimType.SPHERE && part.Shape.ProfileHollow > 0)
  4770. {
  4771. // Make up for a bug where LSL shows 4 sides rather than 2
  4772. sides += 2;
  4773. }
  4774. return sides;
  4775. }
  4776. /* The new / changed functions were tested with the following LSL script:
  4777. default
  4778. {
  4779. state_entry()
  4780. {
  4781. rotation rot = llEuler2Rot(<0,70,0> * DEG_TO_RAD);
  4782. llOwnerSay("to get here, we rotate over: "+ (string) llRot2Axis(rot));
  4783. llOwnerSay("and we rotate for: "+ (llRot2Angle(rot) * RAD_TO_DEG));
  4784. // convert back and forth between quaternion <-> vector and angle
  4785. rotation newrot = llAxisAngle2Rot(llRot2Axis(rot),llRot2Angle(rot));
  4786. llOwnerSay("Old rotation was: "+(string) rot);
  4787. llOwnerSay("re-converted rotation is: "+(string) newrot);
  4788. llSetRot(rot); // to check the parameters in the prim
  4789. }
  4790. }
  4791. */
  4792. // Xantor 29/apr/2008
  4793. // Returns rotation described by rotating angle radians about axis.
  4794. // q = cos(a/2) + i (x * sin(a/2)) + j (y * sin(a/2)) + k (z * sin(a/2))
  4795. public LSL_Rotation llAxisAngle2Rot(LSL_Vector axis, LSL_Float angle)
  4796. {
  4797. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  4798. return new LSL_Rotation();
  4799. double s = Math.Cos(angle*0.5);
  4800. double t = Math.Sin(angle*0.5);
  4801. double x = axis.x*t;
  4802. double y = axis.y*t;
  4803. double z = axis.z*t;
  4804. return new LSL_Rotation(x, y, z, s);
  4805. }
  4806. // Xantor 29/apr/2008
  4807. // converts a Quaternion to X,Y,Z axis rotations
  4808. public LSL_Vector llRot2Axis(LSL_Rotation rot)
  4809. {
  4810. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  4811. return new LSL_Vector();
  4812. double x, y, z;
  4813. if (rot.s > 1) // normalization needed
  4814. {
  4815. double length = Math.Sqrt(rot.x*rot.x + rot.y*rot.y +
  4816. rot.z*rot.z + rot.s*rot.s);
  4817. if (length == 0)
  4818. return new LSL_Vector(0, 0, 0);
  4819. length = 1/length;
  4820. rot.x *= length;
  4821. rot.y *= length;
  4822. rot.z *= length;
  4823. rot.s *= length;
  4824. }
  4825. // double angle = 2 * Math.Acos(rot.s);
  4826. double s = Math.Sqrt(1 - rot.s*rot.s);
  4827. if (s < 0.001)
  4828. {
  4829. x = 1;
  4830. y = z = 0;
  4831. }
  4832. else
  4833. {
  4834. s = 1/s;
  4835. x = rot.x*s; // normalise axis
  4836. y = rot.y*s;
  4837. z = rot.z*s;
  4838. }
  4839. return new LSL_Vector(x, y, z);
  4840. }
  4841. // Returns the angle of a quaternion (see llRot2Axis for the axis)
  4842. public LSL_Float llRot2Angle(LSL_Rotation rot)
  4843. {
  4844. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  4845. return new LSL_Float();
  4846. if (rot.s > 1) // normalization needed
  4847. {
  4848. double length = Math.Sqrt(rot.x*rot.x + rot.y*rot.y +
  4849. rot.z*rot.z + rot.s*rot.s);
  4850. if (length == 0)
  4851. return 0;
  4852. // rot.x /= length;
  4853. // rot.y /= length;
  4854. // rot.z /= length;
  4855. rot.s /= length;
  4856. }
  4857. double angle = 2*Math.Acos(rot.s);
  4858. return angle;
  4859. }
  4860. public LSL_Float llAcos(double val)
  4861. {
  4862. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  4863. return new LSL_Float();
  4864. return Math.Acos(val);
  4865. }
  4866. public LSL_Float llAsin(double val)
  4867. {
  4868. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  4869. return new LSL_Float();
  4870. return Math.Asin(val);
  4871. }
  4872. public LSL_Float llAngleBetween(LSL_Rotation a, LSL_Rotation b)
  4873. {
  4874. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  4875. return new LSL_Float();
  4876. double aa = (a.x*a.x + a.y*a.y + a.z*a.z + a.s*a.s);
  4877. double bb = (b.x*b.x + b.y*b.y + b.z*b.z + b.s*b.s);
  4878. double aa_bb = aa*bb;
  4879. if (aa_bb == 0) return 0.0;
  4880. double ab = (a.x*b.x + a.y*b.y + a.z*b.z + a.s*b.s);
  4881. double quotient = (ab*ab)/aa_bb;
  4882. if (quotient >= 1.0) return 0.0;
  4883. return Math.Acos(2*quotient - 1);
  4884. }
  4885. public LSL_String llGetInventoryKey(string name)
  4886. {
  4887. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  4888. return new LSL_String();
  4889. lock (m_host.TaskInventory)
  4890. {
  4891. foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
  4892. {
  4893. if (inv.Value.Name == name)
  4894. {
  4895. return (inv.Value.CurrentPermissions &
  4896. (uint) (PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) ==
  4897. (uint) (PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)
  4898. ? inv.Value.AssetID.ToString()
  4899. : UUID.Zero.ToString();
  4900. }
  4901. }
  4902. }
  4903. return UUID.Zero.ToString();
  4904. }
  4905. public void llAllowInventoryDrop(int add)
  4906. {
  4907. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  4908. m_host.ParentEntity.RootChild.AllowedDrop = add != 0;
  4909. // Update the object flags
  4910. m_host.ParentEntity.RootChild.aggregateScriptEvents();
  4911. }
  4912. public LSL_Vector llGetSunDirection()
  4913. {
  4914. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  4915. return new LSL_Vector();
  4916. LSL_Vector SunDoubleVector3;
  4917. // have to convert from Vector3 (float) to LSL_Vector (double)
  4918. Vector3 SunFloatVector3 = World.RegionInfo.RegionSettings.SunVector;
  4919. SunDoubleVector3.x = SunFloatVector3.X;
  4920. SunDoubleVector3.y = SunFloatVector3.Y;
  4921. SunDoubleVector3.z = SunFloatVector3.Z;
  4922. return SunDoubleVector3;
  4923. }
  4924. public LSL_Vector llGetTextureOffset(int face)
  4925. {
  4926. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  4927. return new LSL_Vector();
  4928. return GetTextureOffset(m_host, face);
  4929. }
  4930. protected LSL_Vector GetTextureOffset(ISceneChildEntity part, int face)
  4931. {
  4932. Primitive.TextureEntry tex = part.Shape.Textures;
  4933. LSL_Vector offset = new LSL_Vector();
  4934. if (face == ScriptBaseClass.ALL_SIDES)
  4935. {
  4936. face = 0;
  4937. }
  4938. if (face >= 0 && face < GetNumberOfSides(part))
  4939. {
  4940. offset.x = tex.GetFace((uint) face).OffsetU;
  4941. offset.y = tex.GetFace((uint) face).OffsetV;
  4942. offset.z = 0.0;
  4943. return offset;
  4944. }
  4945. return offset;
  4946. }
  4947. public LSL_Vector llGetTextureScale(int side)
  4948. {
  4949. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  4950. return new LSL_Vector();
  4951. Primitive.TextureEntry tex = m_host.Shape.Textures;
  4952. LSL_Vector scale;
  4953. if (side == -1)
  4954. {
  4955. side = 0;
  4956. }
  4957. scale.x = tex.GetFace((uint) side).RepeatU;
  4958. scale.y = tex.GetFace((uint) side).RepeatV;
  4959. scale.z = 0.0;
  4960. return scale;
  4961. }
  4962. public LSL_Float llGetTextureRot(int face)
  4963. {
  4964. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  4965. return new LSL_Float();
  4966. return GetTextureRot(m_host, face);
  4967. }
  4968. protected LSL_Float GetTextureRot(ISceneChildEntity part, int face)
  4969. {
  4970. Primitive.TextureEntry tex = part.Shape.Textures;
  4971. if (face == -1)
  4972. {
  4973. face = 0;
  4974. }
  4975. if (face >= 0 && face < GetNumberOfSides(part))
  4976. {
  4977. return tex.GetFace((uint) face).Rotation;
  4978. }
  4979. return 0.0;
  4980. }
  4981. public LSL_Integer llSubStringIndex(string source, string pattern)
  4982. {
  4983. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  4984. return source.IndexOf(pattern);
  4985. }
  4986. public LSL_String llGetOwnerKey(string id)
  4987. {
  4988. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  4989. UUID key = new UUID();
  4990. if (UUID.TryParse(id, out key))
  4991. {
  4992. try
  4993. {
  4994. ISceneChildEntity obj = World.GetSceneObjectPart(key);
  4995. if (obj == null)
  4996. return id; // the key is for an agent so just return the key
  4997. return obj.OwnerID.ToString();
  4998. }
  4999. catch (KeyNotFoundException)
  5000. {
  5001. return id; // The Object/Agent not in the region so just return the key
  5002. }
  5003. }
  5004. return UUID.Zero.ToString();
  5005. }
  5006. public LSL_Vector llGetCenterOfMass()
  5007. {
  5008. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  5009. return new LSL_Vector();
  5010. Vector3 center = m_host.GetGeometricCenter();
  5011. return new LSL_Vector(center.X, center.Y, center.Z);
  5012. }
  5013. public LSL_List llListSort(LSL_List src, int stride, int ascending)
  5014. {
  5015. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  5016. return new LSL_List();
  5017. if (stride <= 0)
  5018. {
  5019. stride = 1;
  5020. }
  5021. return src.Sort(stride, ascending);
  5022. }
  5023. public LSL_Integer llGetListLength(LSL_List src)
  5024. {
  5025. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  5026. if (src == new LSL_List(new object[0]))
  5027. {
  5028. return 0;
  5029. }
  5030. return src.Length;
  5031. }
  5032. public LSL_Integer llList2Integer(LSL_List src, int index)
  5033. {
  5034. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  5035. if (index < 0)
  5036. {
  5037. index = src.Length + index;
  5038. }
  5039. if (index >= src.Length || index < 0)
  5040. {
  5041. return 0;
  5042. }
  5043. try
  5044. {
  5045. if (src.Data[index] is LSL_Integer)
  5046. return (LSL_Integer) src.Data[index];
  5047. if (src.Data[index] is LSL_Float)
  5048. return Convert.ToInt32(((LSL_Float) src.Data[index]).value);
  5049. return new LSL_Integer(src.Data[index].ToString());
  5050. }
  5051. catch (FormatException)
  5052. {
  5053. return 0;
  5054. }
  5055. catch (InvalidCastException)
  5056. {
  5057. return 0;
  5058. }
  5059. }
  5060. public LSL_Float llList2Float(LSL_List src, int index)
  5061. {
  5062. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  5063. return new LSL_Float();
  5064. if (index < 0)
  5065. {
  5066. index = src.Length + index;
  5067. }
  5068. if (index >= src.Length || index < 0)
  5069. {
  5070. return 0.0;
  5071. }
  5072. try
  5073. {
  5074. if (src.Data[index] is LSL_Integer)
  5075. return Convert.ToDouble(((LSL_Integer) src.Data[index]).value);
  5076. if (src.Data[index] is LSL_Float)
  5077. return Convert.ToDouble(((LSL_Float) src.Data[index]).value);
  5078. if (src.Data[index] is LSL_String)
  5079. return Convert.ToDouble(((LSL_String) src.Data[index]).m_string);
  5080. return Convert.ToDouble(src.Data[index]);
  5081. }
  5082. catch (FormatException)
  5083. {
  5084. return 0.0;
  5085. }
  5086. catch (InvalidCastException)
  5087. {
  5088. return 0.0;
  5089. }
  5090. }
  5091. public LSL_String llList2String(LSL_List src, int index)
  5092. {
  5093. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  5094. if (index < 0)
  5095. {
  5096. index = src.Length + index;
  5097. }
  5098. if (index >= src.Length || index < 0)
  5099. {
  5100. return String.Empty;
  5101. }
  5102. return new LSL_String(src.Data[index].ToString());
  5103. }
  5104. public LSL_String llList2Key(LSL_List src, int index)
  5105. {
  5106. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  5107. if (index < 0)
  5108. {
  5109. index = src.Length + index;
  5110. }
  5111. if (index >= src.Length || index < 0)
  5112. {
  5113. return "";
  5114. }
  5115. return src.Data[index].ToString();
  5116. }
  5117. public LSL_Vector llList2Vector(LSL_List src, int index)
  5118. {
  5119. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  5120. return new LSL_Vector();
  5121. if (index < 0)
  5122. {
  5123. index = src.Length + index;
  5124. }
  5125. if (index >= src.Length || index < 0)
  5126. {
  5127. return new LSL_Vector(0, 0, 0);
  5128. }
  5129. if (src.Data[index] is LSL_Vector)
  5130. {
  5131. return (LSL_Vector) src.Data[index];
  5132. }
  5133. return new LSL_Vector(src.Data[index].ToString());
  5134. }
  5135. public LSL_Rotation llList2Rot(LSL_List src, int index)
  5136. {
  5137. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  5138. return new LSL_Rotation();
  5139. if (index < 0)
  5140. {
  5141. index = src.Length + index;
  5142. }
  5143. if (index >= src.Length || index < 0)
  5144. {
  5145. return new LSL_Rotation(0, 0, 0, 1);
  5146. }
  5147. if (src.Data[index] is LSL_Rotation)
  5148. {
  5149. return (LSL_Rotation) src.Data[index];
  5150. }
  5151. return new LSL_Rotation(src.Data[index].ToString());
  5152. }
  5153. public LSL_List llList2List(LSL_List src, int start, int end)
  5154. {
  5155. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  5156. return new LSL_List();
  5157. return src.GetSublist(start, end);
  5158. }
  5159. public LSL_List llDeleteSubList(LSL_List src, int start, int end)
  5160. {
  5161. return src.DeleteSublist(start, end);
  5162. }
  5163. public LSL_Integer llGetListEntryType(LSL_List src, int index)
  5164. {
  5165. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  5166. if (index < 0)
  5167. {
  5168. index = src.Length + index;
  5169. }
  5170. if (index >= src.Length)
  5171. {
  5172. return 0;
  5173. }
  5174. if (src.Data[index] is LSL_Integer || src.Data[index] is Int32)
  5175. return ScriptBaseClass.TYPE_INTEGER;
  5176. if (src.Data[index] is LSL_Float || src.Data[index] is Single || src.Data[index] is Double)
  5177. return ScriptBaseClass.TYPE_FLOAT;
  5178. if (src.Data[index] is LSL_String || src.Data[index] is String)
  5179. {
  5180. UUID tuuid;
  5181. if (UUID.TryParse(src.Data[index].ToString(), out tuuid))
  5182. {
  5183. return ScriptBaseClass.TYPE_KEY;
  5184. }
  5185. return ScriptBaseClass.TYPE_STRING;
  5186. }
  5187. if (src.Data[index] is LSL_Vector)
  5188. return ScriptBaseClass.TYPE_VECTOR;
  5189. if (src.Data[index] is LSL_Rotation)
  5190. return ScriptBaseClass.TYPE_ROTATION;
  5191. if (src.Data[index] is LSL_List)
  5192. return 7; //Extension of LSL by us
  5193. return ScriptBaseClass.TYPE_INVALID;
  5194. }
  5195. /// <summary>
  5196. /// Process the supplied list and return the
  5197. /// content of the list formatted as a comma
  5198. /// separated list. There is a space after
  5199. /// each comma.
  5200. /// </summary>
  5201. public LSL_String llList2CSV(LSL_List src)
  5202. {
  5203. string ret = String.Empty;
  5204. int x = 0;
  5205. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  5206. if (src.Data.Length > 0)
  5207. {
  5208. ret = src.Data[x++].ToString();
  5209. for (; x < src.Data.Length; x++)
  5210. {
  5211. ret += ", " + src.Data[x].ToString();
  5212. }
  5213. }
  5214. return ret;
  5215. }
  5216. /// <summary>
  5217. /// The supplied string is scanned for commas
  5218. /// and converted into a list. Commas are only
  5219. /// effective if they are encountered outside
  5220. /// of &apos;&lt;&apos; &apos;&gt;&apos; delimiters. Any whitespace
  5221. /// before or after an element is trimmed.
  5222. /// </summary>
  5223. public LSL_List llCSV2List(string src)
  5224. {
  5225. LSL_List result = new LSL_List();
  5226. int parens = 0;
  5227. int start = 0;
  5228. int length = 0;
  5229. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  5230. return new LSL_List();
  5231. for (int i = 0; i < src.Length; i++)
  5232. {
  5233. switch (src[i])
  5234. {
  5235. case '<':
  5236. parens++;
  5237. length++;
  5238. break;
  5239. case '>':
  5240. if (parens > 0)
  5241. parens--;
  5242. length++;
  5243. break;
  5244. case ',':
  5245. if (parens == 0)
  5246. {
  5247. result.Add(new LSL_String(src.Substring(start, length).Trim()));
  5248. start += length + 1;
  5249. length = 0;
  5250. }
  5251. else
  5252. {
  5253. length++;
  5254. }
  5255. break;
  5256. default:
  5257. length++;
  5258. break;
  5259. }
  5260. }
  5261. result.Add(new LSL_String(src.Substring(start, length).Trim()));
  5262. return result;
  5263. }
  5264. /// <summary>
  5265. /// Randomizes the list, be arbitrarily reordering
  5266. /// sublists of stride elements. As the stride approaches
  5267. /// the size of the list, the options become very
  5268. /// limited.
  5269. /// </summary>
  5270. /// <remarks>
  5271. /// This could take a while for very large list
  5272. /// sizes.
  5273. /// </remarks>
  5274. public LSL_List llListRandomize(LSL_List src, int stride)
  5275. {
  5276. LSL_List result;
  5277. Random rand = new Random();
  5278. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  5279. return new LSL_List();
  5280. if (stride <= 0)
  5281. {
  5282. stride = 1;
  5283. }
  5284. // Stride MUST be a factor of the list length
  5285. // If not, then return the src list. This also
  5286. // traps those cases where stride > length.
  5287. if (src.Length != stride && src.Length%stride == 0)
  5288. {
  5289. int chunkk = src.Length/stride;
  5290. int[] chunks = new int[chunkk];
  5291. for (int i = 0; i < chunkk; i++)
  5292. chunks[i] = i;
  5293. // Knuth shuffle the chunkk index
  5294. for (int i = chunkk - 1; i >= 1; i--)
  5295. {
  5296. // Elect an unrandomized chunk to swap
  5297. int index = rand.Next(i + 1);
  5298. // and swap position with first unrandomized chunk
  5299. int tmp = chunks[i];
  5300. chunks[i] = chunks[index];
  5301. chunks[index] = tmp;
  5302. }
  5303. // Construct the randomized list
  5304. result = new LSL_List();
  5305. for (int i = 0; i < chunkk; i++)
  5306. {
  5307. for (int j = 0; j < stride; j++)
  5308. {
  5309. result.Add(src.Data[chunks[i]*stride + j]);
  5310. }
  5311. }
  5312. }
  5313. else
  5314. {
  5315. object[] array = new object[src.Length];
  5316. Array.Copy(src.Data, 0, array, 0, src.Length);
  5317. result = new LSL_List(array);
  5318. }
  5319. return result;
  5320. }
  5321. /// <summary>
  5322. /// Elements in the source list starting with 0 and then
  5323. /// every i+stride. If the stride is negative then the scan
  5324. /// is backwards producing an inverted result.
  5325. /// Only those elements that are also in the specified
  5326. /// range are included in the result.
  5327. /// </summary>
  5328. public LSL_List llList2ListStrided(LSL_List src, int start, int end, int stride)
  5329. {
  5330. LSL_List result = new LSL_List();
  5331. int[] si = new int[2];
  5332. int[] ei = new int[2];
  5333. bool twopass = false;
  5334. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  5335. return new LSL_List();
  5336. // First step is always to deal with negative indices
  5337. if (start < 0)
  5338. start = src.Length + start;
  5339. if (end < 0)
  5340. end = src.Length + end;
  5341. // Out of bounds indices are OK, just trim them
  5342. // accordingly
  5343. if (start > src.Length)
  5344. start = src.Length;
  5345. if (end > src.Length)
  5346. end = src.Length;
  5347. if (stride == 0)
  5348. stride = 1;
  5349. // There may be one or two ranges to be considered
  5350. if (start != end)
  5351. {
  5352. if (start <= end)
  5353. {
  5354. si[0] = start;
  5355. ei[0] = end;
  5356. }
  5357. else
  5358. {
  5359. si[1] = start;
  5360. ei[1] = src.Length;
  5361. si[0] = 0;
  5362. ei[0] = end;
  5363. twopass = true;
  5364. }
  5365. // The scan always starts from the beginning of the
  5366. // source list, but members are only selected if they
  5367. // fall within the specified sub-range. The specified
  5368. // range values are inclusive.
  5369. // A negative stride reverses the direction of the
  5370. // scan producing an inverted list as a result.
  5371. if (stride > 0)
  5372. {
  5373. for (int i = 0; i < src.Length; i += stride)
  5374. {
  5375. if (i <= ei[0] && i >= si[0])
  5376. result.Add(src.Data[i]);
  5377. if (twopass && i >= si[1] && i <= ei[1])
  5378. result.Add(src.Data[i]);
  5379. }
  5380. }
  5381. else if (stride < 0)
  5382. {
  5383. for (int i = src.Length - 1; i >= 0; i += stride)
  5384. {
  5385. if (i <= ei[0] && i >= si[0])
  5386. result.Add(src.Data[i]);
  5387. if (twopass && i >= si[1] && i <= ei[1])
  5388. result.Add(src.Data[i]);
  5389. }
  5390. }
  5391. }
  5392. else
  5393. {
  5394. if (start%stride == 0)
  5395. {
  5396. result.Add(src.Data[start]);
  5397. }
  5398. }
  5399. return result;
  5400. }
  5401. public LSL_Integer llGetRegionAgentCount()
  5402. {
  5403. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  5404. IEntityCountModule entityCountModule = World.RequestModuleInterface<IEntityCountModule>();
  5405. if (entityCountModule != null)
  5406. return new LSL_Integer(entityCountModule.RootAgents);
  5407. else
  5408. return new LSL_Integer(0);
  5409. }
  5410. public LSL_Vector llGetRegionCorner()
  5411. {
  5412. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  5413. return new LSL_Vector();
  5414. return new LSL_Vector(World.RegionInfo.RegionLocX, World.RegionInfo.RegionLocY, 0);
  5415. }
  5416. /// <summary>
  5417. /// Insert the list identified by &lt;src&gt; into the
  5418. /// list designated by &lt;dest&gt; such that the first
  5419. /// new element has the index specified by &lt;index&gt;
  5420. /// </summary>
  5421. public LSL_List llListInsertList(LSL_List dest, LSL_List src, int index)
  5422. {
  5423. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  5424. return new LSL_List();
  5425. LSL_List pref = null;
  5426. LSL_List suff = null;
  5427. if (index < 0)
  5428. {
  5429. index = index + dest.Length;
  5430. if (index < 0)
  5431. {
  5432. index = 0;
  5433. }
  5434. }
  5435. if (index != 0)
  5436. {
  5437. pref = dest.GetSublist(0, index - 1);
  5438. if (index < dest.Length)
  5439. {
  5440. suff = dest.GetSublist(index, -1);
  5441. return pref + src + suff;
  5442. }
  5443. return pref + src;
  5444. }
  5445. if (index < dest.Length)
  5446. {
  5447. suff = dest.GetSublist(index, -1);
  5448. return src + suff;
  5449. }
  5450. return src;
  5451. }
  5452. /// <summary>
  5453. /// Returns the index of the first occurrence of test
  5454. /// in src.
  5455. /// </summary>
  5456. public LSL_Integer llListFindList(LSL_List src, LSL_List test)
  5457. {
  5458. int index = -1;
  5459. int length = src.Length - test.Length + 1;
  5460. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  5461. // If either list is empty, do not match
  5462. if (src.Length != 0 && test.Length != 0)
  5463. {
  5464. for (int i = 0; i < length; i++)
  5465. {
  5466. if (src.Data[i].Equals(test.Data[0]) || test.Data[0].Equals(src.Data[i]))
  5467. {
  5468. int j;
  5469. for (j = 1; j < test.Length; j++)
  5470. if (!(src.Data[i + j].Equals(test.Data[j]) || test.Data[j].Equals(src.Data[i + j])))
  5471. break;
  5472. if (j == test.Length)
  5473. {
  5474. index = i;
  5475. break;
  5476. }
  5477. }
  5478. }
  5479. }
  5480. return index;
  5481. }
  5482. public LSL_String llGetObjectName()
  5483. {
  5484. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  5485. return m_host.Name ?? String.Empty;
  5486. }
  5487. public void llSetObjectName(string name)
  5488. {
  5489. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  5490. m_host.Name = name ?? String.Empty;
  5491. }
  5492. public LSL_String llGetDate()
  5493. {
  5494. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  5495. DateTime date = DateTime.Now.ToUniversalTime();
  5496. string result = date.ToString("yyyy-MM-dd");
  5497. return result;
  5498. }
  5499. public LSL_Integer llEdgeOfWorld(LSL_Vector pos, LSL_Vector dir)
  5500. {
  5501. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  5502. // edge will be used to pass the Region Coordinates offset
  5503. // we want to check for a neighboring sim
  5504. LSL_Vector edge = new LSL_Vector(0, 0, 0);
  5505. if (dir.x == 0)
  5506. {
  5507. if (dir.y == 0)
  5508. {
  5509. // Direction vector is 0,0 so return
  5510. // false since we're staying in the sim
  5511. return 0;
  5512. }
  5513. // Y is the only valid direction
  5514. edge.y = dir.y/Math.Abs(dir.y);
  5515. }
  5516. else
  5517. {
  5518. LSL_Float mag;
  5519. if (dir.x > 0)
  5520. {
  5521. mag = (World.RegionInfo.RegionSizeX - pos.x)/dir.x;
  5522. }
  5523. else
  5524. {
  5525. mag = (pos.x/dir.x);
  5526. }
  5527. mag = Math.Abs(mag);
  5528. edge.y = pos.y + (dir.y*mag);
  5529. if (edge.y > World.RegionInfo.RegionSizeY || edge.y < 0)
  5530. {
  5531. // Y goes out of bounds first
  5532. edge.y = dir.y/Math.Abs(dir.y);
  5533. }
  5534. else
  5535. {
  5536. // X goes out of bounds first or its a corner exit
  5537. edge.y = 0;
  5538. edge.x = dir.x/Math.Abs(dir.x);
  5539. }
  5540. }
  5541. IGridRegisterModule service = World.RequestModuleInterface<IGridRegisterModule>();
  5542. List<GridRegion> neighbors = new List<GridRegion>();
  5543. if (service != null)
  5544. neighbors = service.GetNeighbors(World);
  5545. int neighborX = World.RegionInfo.RegionLocX + (int) dir.x;
  5546. int neighborY = World.RegionInfo.RegionLocY + (int) dir.y;
  5547. #if (!ISWIN)
  5548. foreach (GridRegion neighbor in neighbors)
  5549. if (neighbor.RegionLocX == neighborX && neighbor.RegionLocY == neighborY)
  5550. return LSL_Integer.TRUE;
  5551. #else
  5552. if (neighbors.Any(neighbor => neighbor.RegionLocX == neighborX && neighbor.RegionLocY == neighborY))
  5553. {
  5554. return LSL_Integer.TRUE;
  5555. }
  5556. #endif
  5557. return LSL_Integer.FALSE;
  5558. }
  5559. /// <summary>
  5560. /// Fully implemented
  5561. /// </summary>
  5562. public LSL_Integer llGetAgentInfo(string id)
  5563. {
  5564. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  5565. UUID key = new UUID();
  5566. if (!UUID.TryParse(id, out key))
  5567. {
  5568. return 0;
  5569. }
  5570. int flags = 0;
  5571. IScenePresence agent = World.GetScenePresence(key);
  5572. if (agent == null)
  5573. {
  5574. return 0;
  5575. }
  5576. if (agent.IsChildAgent)
  5577. return 0; // Fail if they are not in the same region
  5578. // note: in OpenSim, sitting seems to cancel AGENT_ALWAYS_RUN, unlike SL
  5579. if (agent.SetAlwaysRun)
  5580. {
  5581. flags |= ScriptBaseClass.AGENT_ALWAYS_RUN;
  5582. }
  5583. IAttachmentsModule attachMod = World.RequestModuleInterface<IAttachmentsModule>();
  5584. if (attachMod != null)
  5585. {
  5586. ISceneEntity[] att = attachMod.GetAttachmentsForAvatar(agent.UUID);
  5587. if (att.Length > 0)
  5588. {
  5589. flags |= ScriptBaseClass.AGENT_ATTACHMENTS;
  5590. #if (!ISWIN)
  5591. foreach (ISceneEntity gobj in att)
  5592. {
  5593. if (gobj != null)
  5594. {
  5595. if (gobj.RootChild.Inventory.ContainsScripts())
  5596. {
  5597. flags |= ScriptBaseClass.AGENT_SCRIPTED;
  5598. break;
  5599. }
  5600. }
  5601. }
  5602. #else
  5603. if (att.Where(gobj => gobj != null).Any(gobj => gobj.RootChild.Inventory.ContainsScripts()))
  5604. {
  5605. flags |= ScriptBaseClass.AGENT_SCRIPTED;
  5606. }
  5607. #endif
  5608. }
  5609. }
  5610. if ((agent.AgentControlFlags & (uint) AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0)
  5611. {
  5612. flags |= ScriptBaseClass.AGENT_FLYING;
  5613. flags |= ScriptBaseClass.AGENT_IN_AIR;
  5614. // flying always implies in-air, even if colliding with e.g. a wall
  5615. }
  5616. if ((agent.AgentControlFlags & (uint) AgentManager.ControlFlags.AGENT_CONTROL_AWAY) != 0)
  5617. {
  5618. flags |= ScriptBaseClass.AGENT_AWAY;
  5619. }
  5620. // seems to get unset, even if in mouselook, when avatar is sitting on a prim???
  5621. if ((agent.AgentControlFlags & (uint) AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0)
  5622. {
  5623. flags |= ScriptBaseClass.AGENT_MOUSELOOK;
  5624. }
  5625. if ((agent.State & (byte) AgentState.Typing) != 0)
  5626. {
  5627. flags |= ScriptBaseClass.AGENT_TYPING;
  5628. }
  5629. if (agent.IsBusy)
  5630. {
  5631. flags |= ScriptBaseClass.AGENT_BUSY;
  5632. }
  5633. string agentMovementAnimation = agent.Animator.CurrentMovementAnimation;
  5634. if (agentMovementAnimation == "CROUCH")
  5635. {
  5636. flags |= ScriptBaseClass.AGENT_CROUCHING;
  5637. }
  5638. if (agentMovementAnimation == "WALK" || agentMovementAnimation == "CROUCHWALK")
  5639. {
  5640. flags |= ScriptBaseClass.AGENT_WALKING;
  5641. }
  5642. // not colliding implies in air. Note: flying also implies in-air, even if colliding (see above)
  5643. // note: AGENT_IN_AIR and AGENT_WALKING seem to be mutually exclusive states in SL.
  5644. // note: this may need some tweaking when walking downhill. you "fall down" for a brief instant
  5645. // and don't collide when walking downhill, which instantly registers as in-air, briefly. should
  5646. // there be some minimum non-collision threshold time before claiming the avatar is in-air?
  5647. if ((flags & ScriptBaseClass.AGENT_WALKING) == 0 &&
  5648. agent.PhysicsActor != null &&
  5649. !agent.PhysicsActor.IsColliding)
  5650. {
  5651. flags |= ScriptBaseClass.AGENT_IN_AIR;
  5652. }
  5653. if (agent.ParentID != UUID.Zero)
  5654. {
  5655. flags |= ScriptBaseClass.AGENT_ON_OBJECT;
  5656. flags |= ScriptBaseClass.AGENT_SITTING;
  5657. }
  5658. if (agent.Animator.Animations.ImplicitDefaultAnimation.AnimID
  5659. == AnimationSet.Animations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
  5660. {
  5661. flags |= ScriptBaseClass.AGENT_SITTING;
  5662. }
  5663. return flags;
  5664. }
  5665. public LSL_String llGetAgentLanguage(string id)
  5666. {
  5667. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  5668. IAgentConnector AgentFrontend = Framework.Utilities.DataManager.RequestPlugin<IAgentConnector>();
  5669. if (AgentFrontend == null)
  5670. return "en-us";
  5671. IAgentInfo Agent = AgentFrontend.GetAgent(new UUID(id));
  5672. if (Agent == null)
  5673. return "en-us";
  5674. if (Agent.LanguageIsPublic)
  5675. {
  5676. return Agent.Language;
  5677. }
  5678. return "en-us";
  5679. }
  5680. /// <summary>
  5681. /// http://wiki.secondlife.com/wiki/LlGetAgentList
  5682. /// The list of options is currently not used in SL
  5683. /// scope is one of:-
  5684. /// AGENT_LIST_REGION - all in the region
  5685. /// AGENT_LIST_PARCEL - all in the same parcel as the scripted object
  5686. /// AGENT_LIST_PARCEL_OWNER - all in any parcel owned by the owner of the
  5687. /// current parcel.
  5688. /// </summary>
  5689. public LSL_List llGetAgentList(LSL_Integer scope, LSL_List options)
  5690. {
  5691. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  5692. return new LSL_List();
  5693. // the constants are 1, 2 and 4 so bits are being set, but you
  5694. // get an error "INVALID_SCOPE" if it is anything but 1, 2 and 4
  5695. bool regionWide = scope == ScriptBaseClass.AGENT_LIST_REGION;
  5696. bool parcelOwned = scope == ScriptBaseClass.AGENT_LIST_PARCEL_OWNER;
  5697. bool parcel = scope == ScriptBaseClass.AGENT_LIST_PARCEL;
  5698. LSL_List result = new LSL_List();
  5699. if (!regionWide && !parcelOwned && !parcel)
  5700. {
  5701. result.Add("INVALID_SCOPE");
  5702. return result;
  5703. }
  5704. Vector3 pos;
  5705. UUID id = UUID.Zero;
  5706. if (parcel || parcelOwned)
  5707. {
  5708. pos = m_host.GetWorldPosition();
  5709. IParcelManagementModule parcelManagement = World.RequestModuleInterface<IParcelManagementModule>();
  5710. ILandObject land = parcelManagement.GetLandObject(pos.X, pos.Y);
  5711. if (land == null)
  5712. {
  5713. id = UUID.Zero;
  5714. }
  5715. else
  5716. {
  5717. if (parcelOwned)
  5718. {
  5719. id = land.LandData.OwnerID;
  5720. }
  5721. else
  5722. {
  5723. id = land.LandData.GlobalID;
  5724. }
  5725. }
  5726. }
  5727. World.ForEachScenePresence(delegate(IScenePresence ssp)
  5728. {
  5729. // Gods are not listed in SL
  5730. if (!ssp.IsDeleted && ssp.GodLevel == 0.0 && !ssp.IsChildAgent)
  5731. {
  5732. if (!regionWide)
  5733. {
  5734. pos = ssp.AbsolutePosition;
  5735. IParcelManagementModule parcelManagement =
  5736. World.RequestModuleInterface<IParcelManagementModule>();
  5737. ILandObject land = parcelManagement.GetLandObject(pos.X, pos.Y);
  5738. if (land != null)
  5739. {
  5740. if (parcelOwned && land.LandData.OwnerID == id ||
  5741. parcel && land.LandData.GlobalID == id)
  5742. {
  5743. result.Add(ssp.UUID.ToString());
  5744. }
  5745. }
  5746. }
  5747. else
  5748. {
  5749. result.Add(ssp.UUID.ToString());
  5750. }
  5751. }
  5752. // Maximum of 100 results
  5753. if (result.Length > 99)
  5754. {
  5755. return;
  5756. }
  5757. });
  5758. return result;
  5759. }
  5760. public DateTime llAdjustSoundVolume(double volume)
  5761. {
  5762. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  5763. return DateTime.Now;
  5764. m_host.AdjustSoundGain(volume);
  5765. return PScriptSleep(100);
  5766. }
  5767. public void llSetSoundQueueing(int queue)
  5768. {
  5769. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  5770. m_host.SetSoundQueueing(queue);
  5771. }
  5772. public void llSetSoundRadius(double radius)
  5773. {
  5774. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  5775. m_host.SoundRadius = radius;
  5776. }
  5777. public LSL_String llGetDisplayName(string id)
  5778. {
  5779. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  5780. UUID key = new UUID();
  5781. if (UUID.TryParse(id, out key))
  5782. {
  5783. IScenePresence presence = World.GetScenePresence(key);
  5784. if (presence != null)
  5785. {
  5786. IProfileConnector connector = Framework.Utilities.DataManager.RequestPlugin<IProfileConnector>();
  5787. if (connector != null)
  5788. return connector.GetUserProfile(presence.UUID).DisplayName;
  5789. }
  5790. }
  5791. return String.Empty;
  5792. }
  5793. public LSL_String llGetUsername(string id)
  5794. {
  5795. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  5796. UUID key = new UUID();
  5797. if (UUID.TryParse(id, out key))
  5798. {
  5799. IScenePresence presence = World.GetScenePresence(key);
  5800. if (presence != null)
  5801. return presence.Name;
  5802. }
  5803. return String.Empty;
  5804. }
  5805. public LSL_String llKey2Name(string id)
  5806. {
  5807. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  5808. UUID key = new UUID();
  5809. if (UUID.TryParse(id, out key))
  5810. {
  5811. IScenePresence presence = World.GetScenePresence(key);
  5812. if (presence != null)
  5813. return presence.Name;
  5814. if (World.GetSceneObjectPart(key) != null)
  5815. {
  5816. return World.GetSceneObjectPart(key).Name;
  5817. }
  5818. }
  5819. return String.Empty;
  5820. }
  5821. public void llSetTextureAnim(int mode, int face, int sizex, int sizey, double start, double length, double rate)
  5822. {
  5823. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  5824. SetTextureAnim(m_host, mode, face, sizex, sizey, start, length, rate);
  5825. }
  5826. public void llSetLinkTextureAnim(int linknumber, int mode, int face, int sizex, int sizey, double start,
  5827. double length, double rate)
  5828. {
  5829. List<ISceneChildEntity> parts = GetLinkParts(linknumber);
  5830. foreach (var part in parts)
  5831. {
  5832. SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate);
  5833. }
  5834. }
  5835. private void SetTextureAnim(ISceneChildEntity part, int mode, int face, int sizex, int sizey, double start,
  5836. double length, double rate)
  5837. {
  5838. Primitive.TextureAnimation pTexAnim = new Primitive.TextureAnimation
  5839. {
  5840. Flags =
  5841. (Primitive.TextureAnimMode)
  5842. mode
  5843. };
  5844. //ALL_SIDES
  5845. if (face == ScriptBaseClass.ALL_SIDES)
  5846. face = 255;
  5847. pTexAnim.Face = (uint) face;
  5848. pTexAnim.Length = (float) length;
  5849. pTexAnim.Rate = (float) rate;
  5850. pTexAnim.SizeX = (uint) sizex;
  5851. pTexAnim.SizeY = (uint) sizey;
  5852. pTexAnim.Start = (float) start;
  5853. part.AddTextureAnimation(pTexAnim);
  5854. part.ScheduleUpdate(PrimUpdateFlags.FindBest);
  5855. }
  5856. public void llTriggerSoundLimited(string sound, double volume, LSL_Vector top_north_east,
  5857. LSL_Vector bottom_south_west)
  5858. {
  5859. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  5860. double radius1 = (float) llVecDist(llGetPos(), top_north_east);
  5861. double radius2 = (float) llVecDist(llGetPos(), bottom_south_west);
  5862. double radius = Math.Abs(radius1 - radius2);
  5863. m_host.SendSound(KeyOrName(sound, true).ToString(), volume, true, 0, (float) radius, false, false);
  5864. }
  5865. public DateTime llEjectFromLand(string pest)
  5866. {
  5867. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  5868. return DateTime.Now;
  5869. UUID agentId = new UUID();
  5870. if (UUID.TryParse(pest, out agentId))
  5871. {
  5872. IScenePresence presence = World.GetScenePresence(agentId);
  5873. if (presence != null)
  5874. {
  5875. // agent must be over the owners land
  5876. IParcelManagementModule parcelManagement = World.RequestModuleInterface<IParcelManagementModule>();
  5877. if (parcelManagement != null)
  5878. {
  5879. if (m_host.OwnerID != parcelManagement.GetLandObject(
  5880. presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID &&
  5881. !World.Permissions.CanIssueEstateCommand(m_host.OwnerID, false))
  5882. {
  5883. return PScriptSleep(5000);
  5884. }
  5885. }
  5886. IEntityTransferModule transferModule = World.RequestModuleInterface<IEntityTransferModule>();
  5887. if (transferModule != null)
  5888. transferModule.TeleportHome(agentId, presence.ControllingClient);
  5889. else
  5890. presence.ControllingClient.SendTeleportFailed("Unable to perform teleports on this simulator.");
  5891. }
  5892. }
  5893. return PScriptSleep(5000);
  5894. }
  5895. public LSL_Integer llOverMyLand(string id)
  5896. {
  5897. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  5898. UUID key = new UUID();
  5899. if (UUID.TryParse(id, out key))
  5900. {
  5901. IScenePresence presence = World.GetScenePresence(key);
  5902. IParcelManagementModule parcelManagement = World.RequestModuleInterface<IParcelManagementModule>();
  5903. if (presence != null) // object is an avatar
  5904. {
  5905. if (parcelManagement != null)
  5906. {
  5907. if (m_host.OwnerID
  5908. == parcelManagement.GetLandObject(
  5909. presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID)
  5910. return 1;
  5911. }
  5912. }
  5913. else // object is not an avatar
  5914. {
  5915. ISceneChildEntity obj = World.GetSceneObjectPart(key);
  5916. if (obj != null)
  5917. if (parcelManagement != null)
  5918. {
  5919. if (m_host.OwnerID
  5920. == parcelManagement.GetLandObject(
  5921. obj.AbsolutePosition.X, obj.AbsolutePosition.Y).LandData.OwnerID)
  5922. return 1;
  5923. }
  5924. }
  5925. }
  5926. return 0;
  5927. }
  5928. public LSL_String llGetLandOwnerAt(LSL_Vector pos)
  5929. {
  5930. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  5931. IParcelManagementModule parcelManagement = World.RequestModuleInterface<IParcelManagementModule>();
  5932. if (parcelManagement != null)
  5933. {
  5934. ILandObject land = parcelManagement.GetLandObject((float) pos.x, (float) pos.y);
  5935. if (land != null)
  5936. return land.LandData.OwnerID.ToString();
  5937. }
  5938. return UUID.Zero.ToString();
  5939. }
  5940. /// <summary>
  5941. /// According to http://lslwiki.net/lslwiki/wakka.php?wakka=llGetAgentSize
  5942. /// only the height of avatars vary and that says:
  5943. /// Width (x) and depth (y) are constant. (0.45m and 0.6m respectively).
  5944. /// </summary>
  5945. public LSL_Vector llGetAgentSize(string id)
  5946. {
  5947. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  5948. return new LSL_Vector();
  5949. IScenePresence avatar = World.GetScenePresence((UUID) id);
  5950. LSL_Vector agentSize;
  5951. if (avatar == null || avatar.IsChildAgent) // Fail if not in the same region
  5952. {
  5953. agentSize = ScriptBaseClass.ZERO_VECTOR;
  5954. }
  5955. else
  5956. {
  5957. IAvatarAppearanceModule appearance = avatar.RequestModuleInterface<IAvatarAppearanceModule>();
  5958. agentSize = appearance != null
  5959. ? new LSL_Vector(0.45, 0.6, appearance.Appearance.AvatarHeight)
  5960. : ScriptBaseClass.ZERO_VECTOR;
  5961. }
  5962. return agentSize;
  5963. }
  5964. public LSL_Integer llSameGroup(string agent)
  5965. {
  5966. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  5967. return new LSL_Integer();
  5968. UUID agentId = new UUID();
  5969. if (!UUID.TryParse(agent, out agentId))
  5970. return new LSL_Integer(0);
  5971. IScenePresence presence = World.GetScenePresence(agentId);
  5972. if (presence == null || presence.IsChildAgent) // Return flase for child agents
  5973. return new LSL_Integer(0);
  5974. IClientAPI client = presence.ControllingClient;
  5975. if (m_host.GroupID == client.ActiveGroupId)
  5976. return new LSL_Integer(1);
  5977. return new LSL_Integer(0);
  5978. }
  5979. public void llUnSit(string id)
  5980. {
  5981. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  5982. UUID key = new UUID();
  5983. if (UUID.TryParse(id, out key))
  5984. {
  5985. IScenePresence av = World.GetScenePresence(key);
  5986. if (av != null)
  5987. {
  5988. if (m_host.ParentEntity.SitTargetAvatar.Contains(key))
  5989. {
  5990. // if the avatar is sitting on this object, then
  5991. // we can unsit them. We don't want random scripts unsitting random people
  5992. // Lets avoid the popcorn avatar scenario.
  5993. av.StandUp();
  5994. }
  5995. else
  5996. {
  5997. // If the object owner also owns the parcel
  5998. // or
  5999. // if the land is group owned and the object is group owned by the same group
  6000. // or
  6001. // if the object is owned by a person with estate access.
  6002. IParcelManagementModule parcelManagement =
  6003. World.RequestModuleInterface<IParcelManagementModule>();
  6004. if (parcelManagement != null)
  6005. {
  6006. ILandObject parcel = parcelManagement.GetLandObject(av.AbsolutePosition.X,
  6007. av.AbsolutePosition.Y);
  6008. if (parcel != null)
  6009. {
  6010. if (m_host.OwnerID == parcel.LandData.OwnerID ||
  6011. (m_host.OwnerID == m_host.GroupID && m_host.GroupID == parcel.LandData.GroupID
  6012. && parcel.LandData.IsGroupOwned) || World.Permissions.IsGod(m_host.OwnerID))
  6013. {
  6014. av.StandUp();
  6015. }
  6016. }
  6017. }
  6018. }
  6019. }
  6020. }
  6021. }
  6022. public LSL_Vector llGroundSlope(LSL_Vector offset)
  6023. {
  6024. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  6025. return new LSL_Vector();
  6026. //Get the slope normal. This gives us the equation of the plane tangent to the slope.
  6027. LSL_Vector vsn = llGroundNormal(offset);
  6028. //Plug the x,y coordinates of the slope normal into the equation of the plane to get
  6029. //the height of that point on the plane. The resulting vector gives the slope.
  6030. Vector3 vsl = new Vector3
  6031. {
  6032. X = (float) vsn.x,
  6033. Y = (float) vsn.y,
  6034. Z = (float) (((vsn.x*vsn.x) + (vsn.y*vsn.y))/(-1*vsn.z))
  6035. };
  6036. vsl.Normalize();
  6037. //Normalization might be overkill here
  6038. return new LSL_Vector(vsl.X, vsl.Y, vsl.Z);
  6039. }
  6040. public LSL_Vector llGroundNormal(LSL_Vector offset)
  6041. {
  6042. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  6043. return new LSL_Vector();
  6044. Vector3 pos = m_host.GetWorldPosition() + new Vector3((float) offset.x,
  6045. (float) offset.y,
  6046. (float) offset.z);
  6047. ITerrainChannel heightmap = World.RequestModuleInterface<ITerrainChannel>();
  6048. // Clamp to valid position
  6049. if (pos.X < 0)
  6050. pos.X = 0;
  6051. else if (pos.X >= heightmap.Width)
  6052. pos.X = heightmap.Width - 1;
  6053. if (pos.Y < 0)
  6054. pos.Y = 0;
  6055. else if (pos.Y >= heightmap.Height)
  6056. pos.Y = heightmap.Height - 1;
  6057. //Find two points in addition to the position to define a plane
  6058. Vector3 p0 = new Vector3(pos.X, pos.Y,
  6059. heightmap[(int) pos.X, (int) pos.Y]);
  6060. Vector3 p1 = new Vector3();
  6061. Vector3 p2 = new Vector3();
  6062. if ((pos.X + 1.0f) >= heightmap.Width)
  6063. p1 = new Vector3(pos.X + 1.0f, pos.Y,
  6064. heightmap[(int) pos.X, (int) pos.Y]);
  6065. else
  6066. p1 = new Vector3(pos.X + 1.0f, pos.Y,
  6067. heightmap[(int) (pos.X + 1.0f), (int) pos.Y]);
  6068. if ((pos.Y + 1.0f) >= heightmap.Height)
  6069. p2 = new Vector3(pos.X, pos.Y + 1.0f,
  6070. heightmap[(int) pos.X, (int) pos.Y]);
  6071. else
  6072. p2 = new Vector3(pos.X, pos.Y + 1.0f,
  6073. heightmap[(int) pos.X, (int) (pos.Y + 1.0f)]);
  6074. //Find normalized vectors from p0 to p1 and p0 to p2
  6075. Vector3 v0 = new Vector3(p1.X - p0.X, p1.Y - p0.Y, p1.Z - p0.Z);
  6076. Vector3 v1 = new Vector3(p2.X - p0.X, p2.Y - p0.Y, p2.Z - p0.Z);
  6077. // v0.Normalize();
  6078. // v1.Normalize();
  6079. //Find the cross product of the vectors (the slope normal).
  6080. Vector3 vsn = new Vector3
  6081. {
  6082. X = (v0.Y*v1.Z) - (v0.Z*v1.Y),
  6083. Y = (v0.Z*v1.X) - (v0.X*v1.Z),
  6084. Z = (v0.X*v1.Y) - (v0.Y*v1.X)
  6085. };
  6086. vsn.Normalize();
  6087. //I believe the crossproduct of two normalized vectors is a normalized vector so
  6088. //this normalization may be overkill
  6089. // then don't normalize them just the result
  6090. return new LSL_Vector(vsn.X, vsn.Y, vsn.Z);
  6091. }
  6092. public LSL_Vector llGroundContour(LSL_Vector offset)
  6093. {
  6094. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  6095. return new LSL_Vector();
  6096. LSL_Vector x = llGroundSlope(offset);
  6097. return new LSL_Vector(-x.y, x.x, 0.0);
  6098. }
  6099. public LSL_Integer llGetAttached()
  6100. {
  6101. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  6102. return new LSL_Integer();
  6103. return (int) m_host.ParentEntity.RootChild.AttachmentPoint;
  6104. }
  6105. public LSL_Integer llGetFreeMemory()
  6106. {
  6107. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  6108. return new LSL_Integer();
  6109. // Make scripts designed for LSO happy
  6110. return 16384;
  6111. }
  6112. public LSL_Integer llSetMemoryLimit(LSL_Integer limit)
  6113. {
  6114. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  6115. return new LSL_Integer();
  6116. // Make scripts designed for LSO happy
  6117. return 16384;
  6118. }
  6119. public LSL_Integer llGetMemoryLimit()
  6120. {
  6121. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  6122. return new LSL_Integer();
  6123. // Make scripts designed for LSO happy
  6124. return 16384;
  6125. }
  6126. public LSL_Integer llGetSPMaxMemory()
  6127. {
  6128. //TODO: Not implemented!
  6129. return 0;
  6130. }
  6131. public LSL_Integer llGetUsedMemory()
  6132. {
  6133. //TODO: Not implemented!
  6134. return 0;
  6135. }
  6136. public void llScriptProfiler(LSL_Integer profilerFlags)
  6137. {
  6138. //TODO: We don't support this, not implemented
  6139. }
  6140. public LSL_Integer llGetFreeURLs()
  6141. {
  6142. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  6143. return new LSL_Integer();
  6144. if (m_UrlModule != null)
  6145. return new LSL_Integer(m_UrlModule.GetFreeUrls());
  6146. return new LSL_Integer(0);
  6147. }
  6148. public LSL_String llGetRegionName()
  6149. {
  6150. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  6151. return new LSL_String();
  6152. return World.RegionInfo.RegionName;
  6153. }
  6154. public LSL_Float llGetRegionTimeDilation()
  6155. {
  6156. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  6157. return new LSL_Float();
  6158. return World.TimeDilation;
  6159. }
  6160. /// <summary>
  6161. /// Returns the value reported in the client Statistics window
  6162. /// </summary>
  6163. public LSL_Float llGetRegionFPS()
  6164. {
  6165. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  6166. return new LSL_Float();
  6167. ISimFrameMonitor reporter =
  6168. (ISimFrameMonitor)
  6169. World.RequestModuleInterface<IMonitorModule>()
  6170. .GetMonitor(World.RegionInfo.RegionID.ToString(), MonitorModuleHelper.SimFrameStats);
  6171. if (reporter != null)
  6172. return reporter.LastReportedSimFPS;
  6173. return 0;
  6174. }
  6175. /* particle system rules should be coming into this routine as doubles, that is
  6176. rule[0] should be an integer from this list and rule[1] should be the arg
  6177. for the same integer. wiki.secondlife.com has most of this mapping, but some
  6178. came from http://www.caligari-designs.com/p4u2
  6179. We iterate through the list for 'Count' elements, incrementing by two for each
  6180. iteration and set the members of Primitive.ParticleSystem, one at a time.
  6181. */
  6182. public enum PrimitiveRule
  6183. {
  6184. PSYS_PART_FLAGS = 0,
  6185. PSYS_PART_START_COLOR = 1,
  6186. PSYS_PART_START_ALPHA = 2,
  6187. PSYS_PART_END_COLOR = 3,
  6188. PSYS_PART_END_ALPHA = 4,
  6189. PSYS_PART_START_SCALE = 5,
  6190. PSYS_PART_END_SCALE = 6,
  6191. PSYS_PART_MAX_AGE = 7,
  6192. PSYS_SRC_ACCEL = 8,
  6193. PSYS_SRC_PATTERN = 9,
  6194. PSYS_SRC_INNERANGLE = 10,
  6195. PSYS_SRC_OUTERANGLE = 11,
  6196. PSYS_SRC_TEXTURE = 12,
  6197. PSYS_SRC_BURST_RATE = 13,
  6198. PSYS_SRC_BURST_PART_COUNT = 15,
  6199. PSYS_SRC_BURST_RADIUS = 16,
  6200. PSYS_SRC_BURST_SPEED_MIN = 17,
  6201. PSYS_SRC_BURST_SPEED_MAX = 18,
  6202. PSYS_SRC_MAX_AGE = 19,
  6203. PSYS_SRC_TARGET_KEY = 20,
  6204. PSYS_SRC_OMEGA = 21,
  6205. PSYS_SRC_ANGLE_BEGIN = 22,
  6206. PSYS_SRC_ANGLE_END = 23
  6207. }
  6208. internal Primitive.ParticleSystem.ParticleDataFlags ConvertUINTtoFlags(uint flags)
  6209. {
  6210. const Primitive.ParticleSystem.ParticleDataFlags returnval = Primitive.ParticleSystem.ParticleDataFlags.None;
  6211. return returnval;
  6212. }
  6213. protected Primitive.ParticleSystem getNewParticleSystemWithSLDefaultValues()
  6214. {
  6215. Primitive.ParticleSystem ps = new Primitive.ParticleSystem
  6216. {
  6217. PartStartColor = new Color4(1.0f, 1.0f, 1.0f, 1.0f),
  6218. PartEndColor = new Color4(1.0f, 1.0f, 1.0f, 1.0f),
  6219. PartStartScaleX = 1.0f,
  6220. PartStartScaleY = 1.0f,
  6221. PartEndScaleX = 1.0f,
  6222. PartEndScaleY = 1.0f,
  6223. BurstSpeedMin = 1.0f,
  6224. BurstSpeedMax = 1.0f,
  6225. BurstRate = 0.1f,
  6226. PartMaxAge = 10.0f,
  6227. BurstPartCount = 10
  6228. };
  6229. // TODO find out about the other defaults and add them here
  6230. return ps;
  6231. }
  6232. public void llLinkParticleSystem(int linknumber, LSL_List rules)
  6233. {
  6234. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  6235. List<ISceneChildEntity> parts = GetLinkParts(linknumber);
  6236. foreach (var part in parts)
  6237. {
  6238. SetParticleSystem(part, rules);
  6239. }
  6240. }
  6241. public void llParticleSystem(LSL_List rules)
  6242. {
  6243. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  6244. SetParticleSystem(m_host, rules);
  6245. }
  6246. private void SetParticleSystem(ISceneChildEntity part, LSL_List rules)
  6247. {
  6248. if (rules.Length == 0)
  6249. {
  6250. part.RemoveParticleSystem();
  6251. }
  6252. else
  6253. {
  6254. Primitive.ParticleSystem prules = getNewParticleSystemWithSLDefaultValues();
  6255. LSL_Vector tempv = new LSL_Vector();
  6256. for (int i = 0; i < rules.Length; i += 2)
  6257. {
  6258. LSL_Integer rule = rules.GetLSLIntegerItem(i);
  6259. if (rule == (int) ScriptBaseClass.PSYS_PART_FLAGS)
  6260. {
  6261. prules.PartDataFlags =
  6262. (Primitive.ParticleSystem.ParticleDataFlags) (uint) rules.GetLSLIntegerItem(i + 1);
  6263. }
  6264. else if (rule == (int) ScriptBaseClass.PSYS_PART_START_COLOR)
  6265. {
  6266. tempv = rules.GetVector3Item(i + 1);
  6267. prules.PartStartColor.R = (float) tempv.x;
  6268. prules.PartStartColor.G = (float) tempv.y;
  6269. prules.PartStartColor.B = (float) tempv.z;
  6270. }
  6271. else
  6272. {
  6273. float tempf = 0;
  6274. if (rule == (int) ScriptBaseClass.PSYS_PART_START_ALPHA)
  6275. {
  6276. tempf = (float) rules.GetLSLFloatItem(i + 1);
  6277. prules.PartStartColor.A = tempf;
  6278. }
  6279. else if (rule == (int) ScriptBaseClass.PSYS_PART_END_COLOR)
  6280. {
  6281. tempv = rules.GetVector3Item(i + 1);
  6282. prules.PartEndColor.R = (float) tempv.x;
  6283. prules.PartEndColor.G = (float) tempv.y;
  6284. prules.PartEndColor.B = (float) tempv.z;
  6285. }
  6286. else if (rule == (int) ScriptBaseClass.PSYS_PART_END_ALPHA)
  6287. {
  6288. tempf = (float) rules.GetLSLFloatItem(i + 1);
  6289. prules.PartEndColor.A = tempf;
  6290. }
  6291. else if (rule == (int) ScriptBaseClass.PSYS_PART_START_SCALE)
  6292. {
  6293. tempv = rules.GetVector3Item(i + 1);
  6294. prules.PartStartScaleX = (float) tempv.x;
  6295. prules.PartStartScaleY = (float) tempv.y;
  6296. }
  6297. else if (rule == (int) ScriptBaseClass.PSYS_PART_END_SCALE)
  6298. {
  6299. tempv = rules.GetVector3Item(i + 1);
  6300. prules.PartEndScaleX = (float) tempv.x;
  6301. prules.PartEndScaleY = (float) tempv.y;
  6302. }
  6303. else if (rule == (int) ScriptBaseClass.PSYS_PART_MAX_AGE)
  6304. {
  6305. tempf = (float) rules.GetLSLFloatItem(i + 1);
  6306. prules.PartMaxAge = tempf;
  6307. }
  6308. else if (rule == (int) ScriptBaseClass.PSYS_SRC_ACCEL)
  6309. {
  6310. tempv = rules.GetVector3Item(i + 1);
  6311. prules.PartAcceleration.X = (float) tempv.x;
  6312. prules.PartAcceleration.Y = (float) tempv.y;
  6313. prules.PartAcceleration.Z = (float) tempv.z;
  6314. }
  6315. else if (rule == (int) ScriptBaseClass.PSYS_SRC_PATTERN)
  6316. {
  6317. int tmpi = rules.GetLSLIntegerItem(i + 1);
  6318. prules.Pattern = (Primitive.ParticleSystem.SourcePattern) tmpi;
  6319. }
  6320. // PSYS_SRC_INNERANGLE and PSYS_SRC_ANGLE_BEGIN use the same variables. The
  6321. // PSYS_SRC_OUTERANGLE and PSYS_SRC_ANGLE_END also use the same variable. The
  6322. // client tells the difference between the two by looking at the 0x02 bit in
  6323. // the PartFlags variable.
  6324. else if (rule == (int) ScriptBaseClass.PSYS_SRC_INNERANGLE)
  6325. {
  6326. tempf = (float) rules.GetLSLFloatItem(i + 1);
  6327. prules.InnerAngle = tempf;
  6328. prules.PartFlags &= 0xFFFFFFFD; // Make sure new angle format is off.
  6329. }
  6330. else if (rule == (int) ScriptBaseClass.PSYS_SRC_OUTERANGLE)
  6331. {
  6332. tempf = (float) rules.GetLSLFloatItem(i + 1);
  6333. prules.OuterAngle = tempf;
  6334. prules.PartFlags &= 0xFFFFFFFD; // Make sure new angle format is off.
  6335. }
  6336. else if (rule == (int) ScriptBaseClass.PSYS_SRC_TEXTURE)
  6337. {
  6338. prules.Texture = KeyOrName(rules.GetLSLStringItem(i + 1), false);
  6339. }
  6340. else if (rule == (int) ScriptBaseClass.PSYS_SRC_BURST_RATE)
  6341. {
  6342. tempf = (float) rules.GetLSLFloatItem(i + 1);
  6343. prules.BurstRate = tempf;
  6344. }
  6345. else if (rule == (int) ScriptBaseClass.PSYS_SRC_BURST_PART_COUNT)
  6346. {
  6347. prules.BurstPartCount = (byte) (int) rules.GetLSLIntegerItem(i + 1);
  6348. }
  6349. else if (rule == (int) ScriptBaseClass.PSYS_SRC_BURST_RADIUS)
  6350. {
  6351. tempf = (float) rules.GetLSLFloatItem(i + 1);
  6352. prules.BurstRadius = tempf;
  6353. }
  6354. else if (rule == (int) ScriptBaseClass.PSYS_SRC_BURST_SPEED_MIN)
  6355. {
  6356. tempf = (float) rules.GetLSLFloatItem(i + 1);
  6357. prules.BurstSpeedMin = tempf;
  6358. }
  6359. else if (rule == (int) ScriptBaseClass.PSYS_SRC_BURST_SPEED_MAX)
  6360. {
  6361. tempf = (float) rules.GetLSLFloatItem(i + 1);
  6362. prules.BurstSpeedMax = tempf;
  6363. }
  6364. else if (rule == (int) ScriptBaseClass.PSYS_SRC_MAX_AGE)
  6365. {
  6366. tempf = (float) rules.GetLSLFloatItem(i + 1);
  6367. prules.MaxAge = tempf;
  6368. }
  6369. else if (rule == (int) ScriptBaseClass.PSYS_SRC_TARGET_KEY)
  6370. {
  6371. UUID key = UUID.Zero;
  6372. prules.Target = UUID.TryParse(rules.Data[i + 1].ToString(), out key) ? key : part.UUID;
  6373. }
  6374. else if (rule == (int) ScriptBaseClass.PSYS_SRC_OMEGA)
  6375. {
  6376. // AL: This is an assumption, since it is the only thing that would match.
  6377. tempv = rules.GetVector3Item(i + 1);
  6378. prules.AngularVelocity.X = (float) tempv.x;
  6379. prules.AngularVelocity.Y = (float) tempv.y;
  6380. prules.AngularVelocity.Z = (float) tempv.z;
  6381. }
  6382. else if (rule == (int) ScriptBaseClass.PSYS_SRC_ANGLE_BEGIN)
  6383. {
  6384. tempf = (float) rules.GetLSLFloatItem(i + 1);
  6385. prules.InnerAngle = tempf;
  6386. prules.PartFlags |= 0x02; // Set new angle format.
  6387. }
  6388. else if (rule == (int) ScriptBaseClass.PSYS_SRC_ANGLE_END)
  6389. {
  6390. tempf = (float) rules.GetLSLFloatItem(i + 1);
  6391. prules.OuterAngle = tempf;
  6392. prules.PartFlags |= 0x02; // Set new angle format.
  6393. }
  6394. }
  6395. }
  6396. prules.CRC = 1;
  6397. part.AddNewParticleSystem(prules);
  6398. }
  6399. part.ScheduleUpdate(PrimUpdateFlags.Particles);
  6400. }
  6401. public void llGroundRepel(double height, int water, double tau)
  6402. {
  6403. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  6404. if (m_host.PhysActor != null)
  6405. {
  6406. float ground = (float) llGround(new LSL_Types.Vector3(0, 0, 0));
  6407. float waterLevel = (float) llWater(new LSL_Types.Vector3(0, 0, 0));
  6408. PIDHoverType hoverType = PIDHoverType.Ground;
  6409. if (water != 0)
  6410. {
  6411. hoverType = PIDHoverType.GroundAndWater;
  6412. if (ground < waterLevel)
  6413. height += waterLevel;
  6414. else
  6415. height += ground;
  6416. }
  6417. else
  6418. {
  6419. height += ground;
  6420. }
  6421. m_host.SetHoverHeight((float) height, hoverType, (float) tau);
  6422. }
  6423. }
  6424. protected UUID GetTaskInventoryItem(string name)
  6425. {
  6426. lock (m_host.TaskInventory)
  6427. {
  6428. foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
  6429. {
  6430. if (inv.Value.Name == name)
  6431. return inv.Key;
  6432. }
  6433. }
  6434. return UUID.Zero;
  6435. }
  6436. public void llGiveInventoryList(string destination, string category, LSL_List inventory)
  6437. {
  6438. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  6439. UUID destID;
  6440. if (!UUID.TryParse(destination, out destID))
  6441. return;
  6442. List<UUID> itemList = new List<UUID>();
  6443. foreach (Object item in inventory.Data)
  6444. {
  6445. UUID itemID;
  6446. if (UUID.TryParse(item.ToString(), out itemID))
  6447. {
  6448. itemList.Add(itemID);
  6449. }
  6450. else
  6451. {
  6452. itemID = GetTaskInventoryItem(item.ToString());
  6453. if (itemID != UUID.Zero)
  6454. itemList.Add(itemID);
  6455. }
  6456. }
  6457. if (itemList.Count == 0)
  6458. return;
  6459. UUID folderID = UUID.Zero;
  6460. ILLClientInventory inventoryModule = World.RequestModuleInterface<ILLClientInventory>();
  6461. if (inventoryModule != null)
  6462. folderID = inventoryModule.MoveTaskInventoryItemsToUserInventory(destID, category, m_host, itemList);
  6463. if (folderID == UUID.Zero)
  6464. return;
  6465. byte[] bucket = new byte[17];
  6466. bucket[0] = (byte) AssetType.Folder;
  6467. byte[] objBytes = folderID.GetBytes();
  6468. Array.Copy(objBytes, 0, bucket, 1, 16);
  6469. GridInstantMessage msg = new GridInstantMessage(World,
  6470. m_host.UUID, m_host.Name + ", an object owned by " +
  6471. resolveName(m_host.OwnerID) + ",", destID,
  6472. (byte) InstantMessageDialog.InventoryOffered,
  6473. false, category + "\n" + m_host.Name + " is located at " +
  6474. World.RegionInfo.RegionName + " " +
  6475. m_host.AbsolutePosition.ToString(),
  6476. folderID, true, m_host.AbsolutePosition,
  6477. bucket);
  6478. if (m_TransferModule != null)
  6479. m_TransferModule.SendInstantMessage(msg);
  6480. }
  6481. public void llSetVehicleType(int type)
  6482. {
  6483. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  6484. if (m_host.ParentEntity != null)
  6485. {
  6486. if (!m_host.ParentEntity.IsDeleted)
  6487. {
  6488. m_host.ParentEntity.RootChild.SetVehicleType(type);
  6489. }
  6490. }
  6491. }
  6492. //CFK 9/28: Most, but not all of the underlying plumbing between here and the physics modules is in
  6493. //CFK 9/28: so these are not complete yet.
  6494. public void llSetVehicleFloatParam(int param, LSL_Float value)
  6495. {
  6496. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  6497. if (m_host.ParentEntity != null)
  6498. {
  6499. if (!m_host.ParentEntity.IsDeleted)
  6500. {
  6501. m_host.ParentEntity.RootChild.SetVehicleFloatParam(param, (float) value);
  6502. }
  6503. }
  6504. }
  6505. //CFK 9/28: Most, but not all of the underlying plumbing between here and the physics modules is in
  6506. //CFK 9/28: so these are not complete yet.
  6507. public void llSetVehicleVectorParam(int param, LSL_Vector vec)
  6508. {
  6509. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  6510. if (m_host.ParentEntity != null)
  6511. {
  6512. if (!m_host.ParentEntity.IsDeleted)
  6513. {
  6514. m_host.ParentEntity.RootChild.SetVehicleVectorParam(param,
  6515. new Vector3((float) vec.x, (float) vec.y,
  6516. (float) vec.z));
  6517. }
  6518. }
  6519. }
  6520. //CFK 9/28: Most, but not all of the underlying plumbing between here and the physics modules is in
  6521. //CFK 9/28: so these are not complete yet.
  6522. public void llSetVehicleRotationParam(int param, LSL_Rotation rot)
  6523. {
  6524. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  6525. if (m_host.ParentEntity != null)
  6526. {
  6527. if (!m_host.ParentEntity.IsDeleted)
  6528. {
  6529. m_host.ParentEntity.RootChild.SetVehicleRotationParam(param,
  6530. Rot2Quaternion(rot));
  6531. }
  6532. }
  6533. }
  6534. public void llSetVehicleFlags(int flags)
  6535. {
  6536. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  6537. if (m_host.ParentEntity != null)
  6538. {
  6539. if (!m_host.ParentEntity.IsDeleted)
  6540. {
  6541. m_host.ParentEntity.RootChild.SetVehicleFlags(flags, false);
  6542. }
  6543. }
  6544. }
  6545. public void llRemoveVehicleFlags(int flags)
  6546. {
  6547. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  6548. if (m_host.ParentEntity != null)
  6549. {
  6550. if (!m_host.ParentEntity.IsDeleted)
  6551. {
  6552. m_host.ParentEntity.RootChild.SetVehicleFlags(flags, true);
  6553. }
  6554. }
  6555. }
  6556. public void llSitTarget(LSL_Vector offset, LSL_Rotation rot)
  6557. {
  6558. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  6559. // LSL quaternions can normalize to 0, normal Quaternions can't.
  6560. if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0)
  6561. rot.z = 1; // ZERO_ROTATION = 0,0,0,1
  6562. m_host.SitTargetPosition = new Vector3((float) offset.x, (float) offset.y, (float) offset.z);
  6563. m_host.SitTargetOrientation = Rot2Quaternion(rot);
  6564. }
  6565. public void llLinkSitTarget(LSL_Integer link, LSL_Vector offset, LSL_Rotation rot)
  6566. {
  6567. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  6568. // LSL quaternions can normalize to 0, normal Quaternions can't.
  6569. if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0)
  6570. rot.z = 1; // ZERO_ROTATION = 0,0,0,1
  6571. List<ISceneChildEntity> entities = GetLinkParts(link);
  6572. if (entities.Count == 0)
  6573. return;
  6574. entities[0].SitTargetPosition = new Vector3((float) offset.x, (float) offset.y, (float) offset.z);
  6575. entities[0].SitTargetOrientation = Rot2Quaternion(rot);
  6576. }
  6577. public LSL_String llAvatarOnSitTarget()
  6578. {
  6579. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  6580. return m_host.SitTargetAvatar.Count > 0
  6581. ? new LSL_String(m_host.SitTargetAvatar[0].ToString())
  6582. : ScriptBaseClass.NULL_KEY;
  6583. }
  6584. public LSL_Key llAvatarOnLinkSitTarget()
  6585. {
  6586. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  6587. return new LSL_Key();
  6588. return m_host.SitTargetAvatar.Count > 0
  6589. ? new LSL_String(m_host.SitTargetAvatar[0].ToString())
  6590. : ScriptBaseClass.NULL_KEY;
  6591. }
  6592. public DateTime llAddToLandPassList(string avatar, double hours)
  6593. {
  6594. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  6595. return DateTime.Now;
  6596. IParcelManagementModule parcelManagement = World.RequestModuleInterface<IParcelManagementModule>();
  6597. if (parcelManagement != null)
  6598. {
  6599. LandData land =
  6600. parcelManagement.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).LandData;
  6601. if (land.OwnerID == m_host.OwnerID)
  6602. {
  6603. ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
  6604. UUID key;
  6605. if (UUID.TryParse(avatar, out key))
  6606. {
  6607. entry.AgentID = key;
  6608. entry.Flags = AccessList.Access;
  6609. entry.Time = DateTime.Now.AddHours(hours);
  6610. land.ParcelAccessList.Add(entry);
  6611. }
  6612. }
  6613. }
  6614. return PScriptSleep(100);
  6615. }
  6616. public void llSetTouchText(string text)
  6617. {
  6618. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  6619. m_host.TouchName = text;
  6620. }
  6621. public void llSetSitText(string text)
  6622. {
  6623. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  6624. m_host.SitName = text;
  6625. }
  6626. public void llSetLinkCamera(LSL_Integer link, LSL_Vector eye, LSL_Vector at)
  6627. {
  6628. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  6629. List<ISceneChildEntity> entities = GetLinkParts(link);
  6630. if (entities.Count > 0)
  6631. {
  6632. entities[0].CameraEyeOffset = new Vector3((float) eye.x, (float) eye.y, (float) eye.z);
  6633. entities[0].CameraAtOffset = new Vector3((float) at.x, (float) at.y, (float) at.z);
  6634. }
  6635. }
  6636. public void llSetCameraEyeOffset(LSL_Vector offset)
  6637. {
  6638. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  6639. m_host.CameraEyeOffset = new Vector3((float) offset.x, (float) offset.y, (float) offset.z);
  6640. }
  6641. public void llSetCameraAtOffset(LSL_Vector offset)
  6642. {
  6643. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  6644. m_host.CameraAtOffset = new Vector3((float) offset.x, (float) offset.y, (float) offset.z);
  6645. }
  6646. public LSL_String llDumpList2String(LSL_List src, string seperator)
  6647. {
  6648. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  6649. if (src.Length == 0)
  6650. {
  6651. return String.Empty;
  6652. }
  6653. #if (!ISWIN)
  6654. string ret = "";
  6655. foreach (object o in src.Data)
  6656. ret += o.ToString() + seperator;
  6657. #else
  6658. string ret = src.Data.Aggregate("", (current, o) => current + (o.ToString() + seperator));
  6659. #endif
  6660. ret = ret.Substring(0, ret.Length - seperator.Length);
  6661. return ret;
  6662. }
  6663. public LSL_Integer llScriptDanger(LSL_Vector pos)
  6664. {
  6665. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  6666. bool result = m_ScriptEngine.PipeEventsForScript(m_host,
  6667. new Vector3((float) pos.x, (float) pos.y, (float) pos.z));
  6668. if (result)
  6669. {
  6670. return 1;
  6671. }
  6672. return 0;
  6673. }
  6674. public DateTime llDialog(string avatar, string message, LSL_List buttons, int chat_channel)
  6675. {
  6676. IDialogModule dm = World.RequestModuleInterface<IDialogModule>();
  6677. if (dm == null)
  6678. return DateTime.Now;
  6679. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  6680. return DateTime.Now;
  6681. UUID av = new UUID();
  6682. if (!UUID.TryParse(avatar, out av))
  6683. {
  6684. //Silently accepted in in SL NOTE: it does sleep though!
  6685. //LSLError("First parameter to llDialog needs to be a key");
  6686. return PScriptSleep(1000);
  6687. }
  6688. if (buttons.Length > 12)
  6689. {
  6690. LSLError("No more than 12 buttons can be shown");
  6691. return DateTime.Now;
  6692. }
  6693. string[] buts = new string[buttons.Length];
  6694. for (int i = 0; i < buttons.Length; i++)
  6695. {
  6696. if (buttons.Data[i].ToString() == String.Empty)
  6697. {
  6698. LSLError("button label cannot be blank");
  6699. return DateTime.Now;
  6700. }
  6701. if (buttons.Data[i].ToString().Length > 24)
  6702. {
  6703. LSLError("button label cannot be longer than 24 characters");
  6704. return DateTime.Now;
  6705. }
  6706. buts[i] = buttons.Data[i].ToString();
  6707. }
  6708. if (buts.Length == 0)
  6709. buts = new[] {"OK"};
  6710. dm.SendDialogToUser(
  6711. av, m_host.Name, m_host.UUID, m_host.OwnerID,
  6712. message, new UUID("00000000-0000-2222-3333-100000001000"), chat_channel, buts);
  6713. return PScriptSleep(1000);
  6714. }
  6715. public void llVolumeDetect(int detect)
  6716. {
  6717. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  6718. if (m_host.ParentEntity != null)
  6719. {
  6720. if (!m_host.ParentEntity.IsDeleted)
  6721. {
  6722. m_host.ParentEntity.RootChild.ScriptSetVolumeDetect(detect != 0);
  6723. }
  6724. }
  6725. }
  6726. /// <summary>
  6727. /// This is a depecated function so this just replicates the result of
  6728. /// invoking it in SL
  6729. /// </summary>
  6730. public DateTime llRemoteLoadScript(string target, string name, int running, int start_param)
  6731. {
  6732. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  6733. return DateTime.Now;
  6734. // Report an error as it does in SL
  6735. ShoutError("Deprecated. Please use llRemoteLoadScriptPin instead.");
  6736. return PScriptSleep(3000);
  6737. }
  6738. public void llSetRemoteScriptAccessPin(int pin)
  6739. {
  6740. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  6741. m_host.ScriptAccessPin = pin;
  6742. }
  6743. public DateTime llRemoteLoadScriptPin(string target, string name, int pin, int running, int start_param)
  6744. {
  6745. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  6746. return DateTime.Now;
  6747. bool found = false;
  6748. UUID destId = UUID.Zero;
  6749. UUID srcId = UUID.Zero;
  6750. if (!UUID.TryParse(target, out destId))
  6751. {
  6752. llSay(0, "Could not parse key " + target);
  6753. return DateTime.Now;
  6754. }
  6755. // target must be a different prim than the one containing the script
  6756. if (m_host.UUID == destId)
  6757. {
  6758. return DateTime.Now;
  6759. }
  6760. // copy the first script found with this inventory name
  6761. lock (m_host.TaskInventory)
  6762. {
  6763. foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
  6764. {
  6765. if (inv.Value.Name == name)
  6766. {
  6767. // make sure the object is a script
  6768. if (10 == inv.Value.Type)
  6769. {
  6770. found = true;
  6771. srcId = inv.Key;
  6772. break;
  6773. }
  6774. }
  6775. }
  6776. }
  6777. if (!found)
  6778. {
  6779. llSay(0, "Could not find script " + name);
  6780. return DateTime.Now;
  6781. }
  6782. // the rest of the permission checks are done in RezScript, so check the pin there as well
  6783. ILLClientInventory inventoryModule = World.RequestModuleInterface<ILLClientInventory>();
  6784. if (inventoryModule != null)
  6785. inventoryModule.RezScript(srcId, m_host, destId, pin, running, start_param);
  6786. // this will cause the delay even if the script pin or permissions were wrong - seems ok
  6787. return PScriptSleep(3000);
  6788. }
  6789. public DateTime llOpenRemoteDataChannel()
  6790. {
  6791. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  6792. return DateTime.Now;
  6793. IXMLRPC xmlrpcMod = World.RequestModuleInterface<IXMLRPC>();
  6794. if (xmlrpcMod.IsEnabled())
  6795. {
  6796. UUID channelID = xmlrpcMod.OpenXMLRPCChannel(m_host.UUID, m_itemID, UUID.Zero);
  6797. IXmlRpcRouter xmlRpcRouter = World.RequestModuleInterface<IXmlRpcRouter>();
  6798. if (xmlRpcRouter != null)
  6799. {
  6800. string ExternalHostName = MainServer.Instance.HostName;
  6801. xmlRpcRouter.RegisterNewReceiver(m_ScriptEngine.ScriptModule, channelID, m_host.UUID,
  6802. m_itemID, String.Format("http://{0}:{1}/", ExternalHostName,
  6803. xmlrpcMod.Port.ToString()));
  6804. }
  6805. object[] resobj = new object[]
  6806. {
  6807. new LSL_Integer(1),
  6808. new LSL_String(channelID.ToString()),
  6809. new LSL_String(UUID.Zero.ToString()),
  6810. new LSL_String(String.Empty),
  6811. new LSL_Integer(0),
  6812. new LSL_String(String.Empty)
  6813. };
  6814. m_ScriptEngine.PostScriptEvent(m_itemID, m_host.UUID, new EventParams("remote_data", resobj,
  6815. new DetectParams[0]),
  6816. EventPriority.FirstStart);
  6817. }
  6818. return PScriptSleep(1000);
  6819. }
  6820. public LSL_Key llSendRemoteData(string channel, string dest, int idata, string sdata)
  6821. {
  6822. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  6823. IXMLRPC xmlrpcMod = World.RequestModuleInterface<IXMLRPC>();
  6824. ScriptSleep(3000);
  6825. return (xmlrpcMod.SendRemoteData(m_host.UUID, m_itemID, channel, dest, idata, sdata)).ToString();
  6826. }
  6827. public DateTime llRemoteDataReply(string channel, string message_id, string sdata, int idata)
  6828. {
  6829. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  6830. return DateTime.Now;
  6831. IXMLRPC xmlrpcMod = World.RequestModuleInterface<IXMLRPC>();
  6832. xmlrpcMod.RemoteDataReply(channel, message_id, sdata, idata);
  6833. return PScriptSleep(100);
  6834. }
  6835. public DateTime llCloseRemoteDataChannel(object _channel)
  6836. {
  6837. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  6838. return DateTime.Now;
  6839. IXMLRPC xmlrpcMod = World.RequestModuleInterface<IXMLRPC>();
  6840. xmlrpcMod.CloseXMLRPCChannel(UUID.Parse(_channel.ToString()));
  6841. return PScriptSleep(100);
  6842. }
  6843. public LSL_String llMD5String(string src, int nonce)
  6844. {
  6845. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  6846. return new LSL_String();
  6847. return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString()));
  6848. }
  6849. public LSL_String llSHA1String(string src)
  6850. {
  6851. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  6852. return Util.SHA1Hash(src).ToLower();
  6853. }
  6854. protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(ISceneChildEntity part, int holeshape,
  6855. LSL_Vector cut, float hollow,
  6856. LSL_Vector twist)
  6857. {
  6858. ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
  6859. if (holeshape != (int) ScriptBaseClass.PRIM_HOLE_DEFAULT &&
  6860. holeshape != (int) ScriptBaseClass.PRIM_HOLE_CIRCLE &&
  6861. holeshape != (int) ScriptBaseClass.PRIM_HOLE_SQUARE &&
  6862. holeshape != (int) ScriptBaseClass.PRIM_HOLE_TRIANGLE)
  6863. {
  6864. holeshape = ScriptBaseClass.PRIM_HOLE_DEFAULT;
  6865. }
  6866. shapeBlock.ProfileCurve = (byte) holeshape;
  6867. if (cut.x < 0f)
  6868. {
  6869. cut.x = 0f;
  6870. }
  6871. if (cut.x > 1f)
  6872. {
  6873. cut.x = 1f;
  6874. }
  6875. if (cut.y < 0f)
  6876. {
  6877. cut.y = 0f;
  6878. }
  6879. if (cut.y > 1f)
  6880. {
  6881. cut.y = 1f;
  6882. }
  6883. if (cut.y - cut.x < 0.05f)
  6884. {
  6885. cut.x = cut.y - 0.05f;
  6886. if (cut.x < 0.0f)
  6887. {
  6888. cut.x = 0.0f;
  6889. cut.y = 0.05f;
  6890. }
  6891. }
  6892. shapeBlock.ProfileBegin = (ushort) (50000*cut.x);
  6893. shapeBlock.ProfileEnd = (ushort) (50000*(1 - cut.y));
  6894. if (hollow < 0f)
  6895. {
  6896. hollow = 0f;
  6897. }
  6898. if (hollow > 0.95)
  6899. {
  6900. hollow = 0.95f;
  6901. }
  6902. shapeBlock.ProfileHollow = (ushort) (50000*hollow);
  6903. if (twist.x < -1.0f)
  6904. {
  6905. twist.x = -1.0f;
  6906. }
  6907. if (twist.x > 1.0f)
  6908. {
  6909. twist.x = 1.0f;
  6910. }
  6911. if (twist.y < -1.0f)
  6912. {
  6913. twist.y = -1.0f;
  6914. }
  6915. if (twist.y > 1.0f)
  6916. {
  6917. twist.y = 1.0f;
  6918. }
  6919. // A fairly large precision error occurs for some calculations,
  6920. // if a float or double is directly cast to a byte or sbyte
  6921. // variable, in both .Net and Mono. In .Net, coding
  6922. // "(sbyte)(float)(some expression)" corrects the precision
  6923. // errors. But this does not work for Mono. This longer coding
  6924. // form of creating a tempoary float variable from the
  6925. // expression first, then casting that variable to a byte or
  6926. // sbyte, works for both .Net and Mono. These types of
  6927. // assignments occur in SetPrimtiveBlockShapeParams and
  6928. // SetPrimitiveShapeParams in support of llSetPrimitiveParams.
  6929. float tempFloat = (float) (100.0d*twist.x);
  6930. shapeBlock.PathTwistBegin = (sbyte) tempFloat;
  6931. tempFloat = (float) (100.0d*twist.y);
  6932. shapeBlock.PathTwist = (sbyte) tempFloat;
  6933. shapeBlock.ObjectLocalID = part.LocalId;
  6934. // retain pathcurve
  6935. shapeBlock.PathCurve = part.Shape.PathCurve;
  6936. part.Shape.SculptEntry = false;
  6937. return shapeBlock;
  6938. }
  6939. protected void SetPrimitiveShapeParams(ISceneChildEntity part, int holeshape, LSL_Vector cut, float hollow,
  6940. LSL_Vector twist, LSL_Vector taper_b, LSL_Vector topshear, byte fudge)
  6941. {
  6942. ObjectShapePacket.ObjectDataBlock shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow,
  6943. twist);
  6944. shapeBlock.ProfileCurve += fudge;
  6945. if (taper_b.x < 0f)
  6946. {
  6947. taper_b.x = 0f;
  6948. }
  6949. if (taper_b.x > 2f)
  6950. {
  6951. taper_b.x = 2f;
  6952. }
  6953. if (taper_b.y < 0f)
  6954. {
  6955. taper_b.y = 0f;
  6956. }
  6957. if (taper_b.y > 2f)
  6958. {
  6959. taper_b.y = 2f;
  6960. }
  6961. float tempFloat = (float) (100.0d*(2.0d - taper_b.x));
  6962. shapeBlock.PathScaleX = (byte) tempFloat;
  6963. tempFloat = (float) (100.0d*(2.0d - taper_b.y));
  6964. shapeBlock.PathScaleY = (byte) tempFloat;
  6965. if (topshear.x < -0.5f)
  6966. {
  6967. topshear.x = -0.5f;
  6968. }
  6969. if (topshear.x > 0.5f)
  6970. {
  6971. topshear.x = 0.5f;
  6972. }
  6973. if (topshear.y < -0.5f)
  6974. {
  6975. topshear.y = -0.5f;
  6976. }
  6977. if (topshear.y > 0.5f)
  6978. {
  6979. topshear.y = 0.5f;
  6980. }
  6981. tempFloat = (float) (100.0d*topshear.x);
  6982. shapeBlock.PathShearX = (byte) tempFloat;
  6983. tempFloat = (float) (100.0d*topshear.y);
  6984. shapeBlock.PathShearY = (byte) tempFloat;
  6985. part.Shape.SculptEntry = false;
  6986. part.UpdateShape(shapeBlock);
  6987. }
  6988. protected void SetPrimitiveShapeParams(ISceneChildEntity part, int holeshape, LSL_Vector cut, float hollow,
  6989. LSL_Vector twist, LSL_Vector dimple, byte fudge)
  6990. {
  6991. ObjectShapePacket.ObjectDataBlock shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow,
  6992. twist);
  6993. // profile/path swapped for a sphere
  6994. shapeBlock.PathBegin = shapeBlock.ProfileBegin;
  6995. shapeBlock.PathEnd = shapeBlock.ProfileEnd;
  6996. shapeBlock.ProfileCurve += fudge;
  6997. shapeBlock.PathScaleX = 100;
  6998. shapeBlock.PathScaleY = 100;
  6999. if (dimple.x < 0f)
  7000. {
  7001. dimple.x = 0f;
  7002. }
  7003. if (dimple.x > 1f)
  7004. {
  7005. dimple.x = 1f;
  7006. }
  7007. if (dimple.y < 0f)
  7008. {
  7009. dimple.y = 0f;
  7010. }
  7011. if (dimple.y > 1f)
  7012. {
  7013. dimple.y = 1f;
  7014. }
  7015. if (dimple.y - cut.x < 0.05f)
  7016. {
  7017. dimple.x = cut.y - 0.05f;
  7018. }
  7019. shapeBlock.ProfileBegin = (ushort) (50000*dimple.x);
  7020. shapeBlock.ProfileEnd = (ushort) (50000*(1 - dimple.y));
  7021. part.Shape.SculptEntry = false;
  7022. part.UpdateShape(shapeBlock);
  7023. }
  7024. protected void SetPrimitiveShapeParams(ISceneChildEntity part, int holeshape, LSL_Vector cut, float hollow,
  7025. LSL_Vector twist, LSL_Vector holesize, LSL_Vector topshear,
  7026. LSL_Vector profilecut, LSL_Vector taper_a, float revolutions,
  7027. float radiusoffset, float skew, byte fudge)
  7028. {
  7029. ObjectShapePacket.ObjectDataBlock shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow,
  7030. twist);
  7031. shapeBlock.ProfileCurve += fudge;
  7032. // profile/path swapped for a torrus, tube, ring
  7033. shapeBlock.PathBegin = shapeBlock.ProfileBegin;
  7034. shapeBlock.PathEnd = shapeBlock.ProfileEnd;
  7035. if (holesize.x < 0.05f)
  7036. {
  7037. holesize.x = 0.05f;
  7038. }
  7039. if (holesize.x > 1f)
  7040. {
  7041. holesize.x = 1f;
  7042. }
  7043. if (holesize.y < 0.05f)
  7044. {
  7045. holesize.y = 0.05f;
  7046. }
  7047. if (holesize.y > 0.5f)
  7048. {
  7049. holesize.y = 0.5f;
  7050. }
  7051. float tempFloat = (float) (100.0d*(2.0d - holesize.x));
  7052. shapeBlock.PathScaleX = (byte) tempFloat;
  7053. tempFloat = (float) (100.0d*(2.0d - holesize.y));
  7054. shapeBlock.PathScaleY = (byte) tempFloat;
  7055. if (topshear.x < -0.5f)
  7056. {
  7057. topshear.x = -0.5f;
  7058. }
  7059. if (topshear.x > 0.5f)
  7060. {
  7061. topshear.x = 0.5f;
  7062. }
  7063. if (topshear.y < -0.5f)
  7064. {
  7065. topshear.y = -0.5f;
  7066. }
  7067. if (topshear.y > 0.5f)
  7068. {
  7069. topshear.y = 0.5f;
  7070. }
  7071. tempFloat = (float) (100.0d*topshear.x);
  7072. shapeBlock.PathShearX = (byte) tempFloat;
  7073. tempFloat = (float) (100.0d*topshear.y);
  7074. shapeBlock.PathShearY = (byte) tempFloat;
  7075. if (profilecut.x < 0f)
  7076. {
  7077. profilecut.x = 0f;
  7078. }
  7079. if (profilecut.x > 1f)
  7080. {
  7081. profilecut.x = 1f;
  7082. }
  7083. if (profilecut.y < 0f)
  7084. {
  7085. profilecut.y = 0f;
  7086. }
  7087. if (profilecut.y > 1f)
  7088. {
  7089. profilecut.y = 1f;
  7090. }
  7091. if (profilecut.y - profilecut.x < 0.05f)
  7092. {
  7093. profilecut.x = profilecut.y - 0.05f;
  7094. if (profilecut.x < 0.0f)
  7095. {
  7096. profilecut.x = 0.0f;
  7097. profilecut.y = 0.05f;
  7098. }
  7099. }
  7100. shapeBlock.ProfileBegin = (ushort) (50000*profilecut.x);
  7101. shapeBlock.ProfileEnd = (ushort) (50000*(1 - profilecut.y));
  7102. if (taper_a.x < -1f)
  7103. {
  7104. taper_a.x = -1f;
  7105. }
  7106. if (taper_a.x > 1f)
  7107. {
  7108. taper_a.x = 1f;
  7109. }
  7110. if (taper_a.y < -1f)
  7111. {
  7112. taper_a.y = -1f;
  7113. }
  7114. if (taper_a.y > 1f)
  7115. {
  7116. taper_a.y = 1f;
  7117. }
  7118. tempFloat = (float) (100.0d*taper_a.x);
  7119. shapeBlock.PathTaperX = (sbyte) tempFloat;
  7120. tempFloat = (float) (100.0d*taper_a.y);
  7121. shapeBlock.PathTaperY = (sbyte) tempFloat;
  7122. if (revolutions < 1f)
  7123. {
  7124. revolutions = 1f;
  7125. }
  7126. if (revolutions > 4f)
  7127. {
  7128. revolutions = 4f;
  7129. }
  7130. tempFloat = 66.66667f*(revolutions - 1.0f);
  7131. shapeBlock.PathRevolutions = (byte) tempFloat;
  7132. // limits on radiusoffset depend on revolutions and hole size (how?) seems like the maximum range is 0 to 1
  7133. if (radiusoffset < 0f)
  7134. {
  7135. radiusoffset = 0f;
  7136. }
  7137. if (radiusoffset > 1f)
  7138. {
  7139. radiusoffset = 1f;
  7140. }
  7141. tempFloat = 100.0f*radiusoffset;
  7142. shapeBlock.PathRadiusOffset = (sbyte) tempFloat;
  7143. if (skew < -0.95f)
  7144. {
  7145. skew = -0.95f;
  7146. }
  7147. if (skew > 0.95f)
  7148. {
  7149. skew = 0.95f;
  7150. }
  7151. tempFloat = 100.0f*skew;
  7152. shapeBlock.PathSkew = (sbyte) tempFloat;
  7153. part.Shape.SculptEntry = false;
  7154. part.UpdateShape(shapeBlock);
  7155. }
  7156. protected void SetPrimitiveShapeParams(ISceneChildEntity part, string map, int type)
  7157. {
  7158. ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
  7159. UUID sculptId;
  7160. if (!UUID.TryParse(map, out sculptId))
  7161. {
  7162. sculptId = InventoryKey(map, (int) AssetType.Texture);
  7163. }
  7164. if (sculptId == UUID.Zero)
  7165. return;
  7166. shapeBlock.ObjectLocalID = part.LocalId;
  7167. shapeBlock.PathScaleX = 100;
  7168. shapeBlock.PathScaleY = 150;
  7169. int onlytype = (type & (ScriptBaseClass.PRIM_SCULPT_FLAG_INVERT | ScriptBaseClass.PRIM_SCULPT_FLAG_MIRROR));
  7170. //Removes the sculpt flags according to libOMV
  7171. if (onlytype != (int) ScriptBaseClass.PRIM_SCULPT_TYPE_CYLINDER &&
  7172. onlytype != (int) ScriptBaseClass.PRIM_SCULPT_TYPE_PLANE &&
  7173. onlytype != (int) ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE &&
  7174. onlytype != (int) ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS &&
  7175. onlytype != (int) ScriptBaseClass.PRIM_SCULPT_TYPE_MESH)
  7176. {
  7177. // default
  7178. type |= ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE;
  7179. }
  7180. // retain pathcurve
  7181. shapeBlock.PathCurve = part.Shape.PathCurve;
  7182. bool changedTextureID = part.Shape.SculptTexture != sculptId;
  7183. part.Shape.SetSculptProperties((byte) type, sculptId);
  7184. part.Shape.SculptEntry = true;
  7185. part.UpdateShape(shapeBlock, changedTextureID);
  7186. }
  7187. public void llSetPrimitiveParams(LSL_List rules)
  7188. {
  7189. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  7190. SetPrimParams(m_host, rules);
  7191. }
  7192. public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules)
  7193. {
  7194. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  7195. List<IEntity> parts = GetLinkPartsAndEntities(linknumber);
  7196. foreach (IEntity part in parts)
  7197. SetPrimParams(part, rules);
  7198. }
  7199. public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules)
  7200. {
  7201. List<ISceneChildEntity> parts = GetLinkParts(linknumber);
  7202. foreach (ISceneChildEntity part in parts)
  7203. SetPrimParams(part, rules);
  7204. }
  7205. public LSL_Integer llGetLinkNumberOfSides(int LinkNum)
  7206. {
  7207. List<ISceneChildEntity> Parts = GetLinkParts(LinkNum);
  7208. #if (!ISWIN)
  7209. int faces = 0;
  7210. foreach (ISceneChildEntity part in Parts)
  7211. faces += GetNumberOfSides(part);
  7212. #else
  7213. int faces = Parts.Sum(part => GetNumberOfSides(part));
  7214. #endif
  7215. return new LSL_Integer(faces);
  7216. }
  7217. protected void SetPrimParams(IEntity part, LSL_List rules)
  7218. {
  7219. int idx = 0;
  7220. while (idx < rules.Length)
  7221. {
  7222. int code = rules.GetLSLIntegerItem(idx++);
  7223. int remain = rules.Length - idx;
  7224. int face;
  7225. LSL_Vector v;
  7226. if (code == (int) ScriptBaseClass.PRIM_NAME)
  7227. {
  7228. if (remain < 1)
  7229. return;
  7230. string name = rules.Data[idx++].ToString();
  7231. if (part is ISceneChildEntity)
  7232. (part as ISceneChildEntity).Name = name;
  7233. }
  7234. else if (code == (int) ScriptBaseClass.PRIM_DESC)
  7235. {
  7236. if (remain < 1)
  7237. return;
  7238. string desc = rules.Data[idx++].ToString();
  7239. if (part is ISceneChildEntity)
  7240. (part as ISceneChildEntity).Description = desc;
  7241. }
  7242. else if (code == (int) ScriptBaseClass.PRIM_ROT_LOCAL)
  7243. {
  7244. if (remain < 1)
  7245. return;
  7246. LSL_Rotation lr = rules.GetQuaternionItem(idx++);
  7247. if (part is ISceneChildEntity)
  7248. SetRot((part as ISceneChildEntity), Rot2Quaternion(lr));
  7249. }
  7250. else if (code == (int) ScriptBaseClass.PRIM_POSITION)
  7251. {
  7252. if (remain < 1)
  7253. return;
  7254. v = rules.GetVector3Item(idx++);
  7255. if (part is ISceneChildEntity)
  7256. SetPos(part as ISceneChildEntity, v, true);
  7257. else if (part is IScenePresence)
  7258. {
  7259. (part as IScenePresence).OffsetPosition = new Vector3((float) v.x, (float) v.y, (float) v.z);
  7260. (part as IScenePresence).SendTerseUpdateToAllClients();
  7261. }
  7262. }
  7263. else if (code == (int) ScriptBaseClass.PRIM_POS_LOCAL)
  7264. {
  7265. if (remain < 1)
  7266. return;
  7267. v = rules.GetVector3Item(idx++);
  7268. if (part is ISceneChildEntity)
  7269. {
  7270. if (((ISceneChildEntity) part).ParentID != 0)
  7271. ((ISceneChildEntity) part).OffsetPosition = new Vector3((float) v.x, (float) v.y,
  7272. (float) v.z);
  7273. else
  7274. part.AbsolutePosition = new Vector3((float) v.x, (float) v.y, (float) v.z);
  7275. }
  7276. else if (part is IScenePresence)
  7277. {
  7278. (part as IScenePresence).OffsetPosition = new Vector3((float) v.x, (float) v.y, (float) v.z);
  7279. (part as IScenePresence).SendTerseUpdateToAllClients();
  7280. }
  7281. }
  7282. else if (code == (int) ScriptBaseClass.PRIM_SIZE)
  7283. {
  7284. if (remain < 1)
  7285. return;
  7286. v = rules.GetVector3Item(idx++);
  7287. if (part is ISceneChildEntity)
  7288. SetScale(part as ISceneChildEntity, v);
  7289. }
  7290. else if (code == (int) ScriptBaseClass.PRIM_ROTATION)
  7291. {
  7292. if (remain < 1)
  7293. return;
  7294. LSL_Rotation q = rules.GetQuaternionItem(idx++);
  7295. if (part is ISceneChildEntity)
  7296. {
  7297. // try to let this work as in SL...
  7298. if ((part as ISceneChildEntity).ParentID == 0)
  7299. {
  7300. // special case: If we are root, rotate complete SOG to new rotation
  7301. SetRot(part as ISceneChildEntity, Rot2Quaternion(q));
  7302. }
  7303. else
  7304. {
  7305. // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask.
  7306. ISceneEntity group = (part as ISceneChildEntity).ParentEntity;
  7307. if (group != null) // a bit paranoid, maybe
  7308. {
  7309. ISceneChildEntity rootPart = group.RootChild;
  7310. if (rootPart != null) // again, better safe than sorry
  7311. {
  7312. SetRot((part as ISceneChildEntity), rootPart.GetRotationOffset()*Rot2Quaternion(q));
  7313. }
  7314. }
  7315. }
  7316. }
  7317. else if (part is IScenePresence)
  7318. {
  7319. IScenePresence sp = (IScenePresence) part;
  7320. ISceneChildEntity childObj = sp.Scene.GetSceneObjectPart(sp.SittingOnUUID);
  7321. if (childObj != null)
  7322. {
  7323. sp.Rotation = childObj.ParentEntity.GroupRotation*Rot2Quaternion(q);
  7324. sp.SendTerseUpdateToAllClients();
  7325. }
  7326. }
  7327. }
  7328. else if (code == (int) ScriptBaseClass.PRIM_TYPE)
  7329. {
  7330. if (remain < 3)
  7331. return;
  7332. if (part is ISceneChildEntity)
  7333. {
  7334. }
  7335. else
  7336. return;
  7337. code = rules.GetLSLIntegerItem(idx++);
  7338. remain = rules.Length - idx;
  7339. float hollow;
  7340. LSL_Vector twist;
  7341. LSL_Vector taper_b;
  7342. LSL_Vector topshear;
  7343. float revolutions;
  7344. float radiusoffset;
  7345. float skew;
  7346. LSL_Vector holesize;
  7347. LSL_Vector profilecut;
  7348. if (code == (int) ScriptBaseClass.PRIM_TYPE_BOX)
  7349. {
  7350. if (remain < 6)
  7351. return;
  7352. face = rules.GetLSLIntegerItem(idx++);
  7353. v = rules.GetVector3Item(idx++); // cut
  7354. hollow = (float) rules.GetLSLFloatItem(idx++);
  7355. twist = rules.GetVector3Item(idx++);
  7356. taper_b = rules.GetVector3Item(idx++);
  7357. topshear = rules.GetVector3Item(idx++);
  7358. (part as ISceneChildEntity).Shape.PathCurve = (byte) Extrusion.Straight;
  7359. SetPrimitiveShapeParams((part as ISceneChildEntity), face, v, hollow, twist, taper_b, topshear,
  7360. 1);
  7361. }
  7362. else if (code == (int) ScriptBaseClass.PRIM_TYPE_CYLINDER)
  7363. {
  7364. if (remain < 6)
  7365. return;
  7366. face = rules.GetLSLIntegerItem(idx++); // holeshape
  7367. v = rules.GetVector3Item(idx++); // cut
  7368. hollow = (float) rules.GetLSLFloatItem(idx++);
  7369. twist = rules.GetVector3Item(idx++);
  7370. taper_b = rules.GetVector3Item(idx++);
  7371. topshear = rules.GetVector3Item(idx++);
  7372. (part as ISceneChildEntity).Shape.ProfileShape = ProfileShape.Circle;
  7373. (part as ISceneChildEntity).Shape.PathCurve = (byte) Extrusion.Straight;
  7374. SetPrimitiveShapeParams((part as ISceneChildEntity), face, v, hollow, twist, taper_b, topshear,
  7375. 0);
  7376. }
  7377. else if (code == (int) ScriptBaseClass.PRIM_TYPE_PRISM)
  7378. {
  7379. if (remain < 6)
  7380. return;
  7381. face = rules.GetLSLIntegerItem(idx++); // holeshape
  7382. v = rules.GetVector3Item(idx++); //cut
  7383. hollow = (float) rules.GetLSLFloatItem(idx++);
  7384. twist = rules.GetVector3Item(idx++);
  7385. taper_b = rules.GetVector3Item(idx++);
  7386. topshear = rules.GetVector3Item(idx++);
  7387. (part as ISceneChildEntity).Shape.PathCurve = (byte) Extrusion.Straight;
  7388. SetPrimitiveShapeParams((part as ISceneChildEntity), face, v, hollow, twist, taper_b, topshear,
  7389. 3);
  7390. }
  7391. else if (code == (int) ScriptBaseClass.PRIM_TYPE_SPHERE)
  7392. {
  7393. if (remain < 5)
  7394. return;
  7395. face = rules.GetLSLIntegerItem(idx++); // holeshape
  7396. v = rules.GetVector3Item(idx++); // cut
  7397. hollow = (float) rules.GetLSLFloatItem(idx++);
  7398. twist = rules.GetVector3Item(idx++);
  7399. taper_b = rules.GetVector3Item(idx++); // dimple
  7400. (part as ISceneChildEntity).Shape.PathCurve = (byte) Extrusion.Curve1;
  7401. SetPrimitiveShapeParams((part as ISceneChildEntity), face, v, hollow, twist, taper_b, 5);
  7402. }
  7403. else if (code == (int) ScriptBaseClass.PRIM_TYPE_TORUS)
  7404. {
  7405. if (remain < 11)
  7406. return;
  7407. face = rules.GetLSLIntegerItem(idx++); // holeshape
  7408. v = rules.GetVector3Item(idx++); //cut
  7409. hollow = (float) rules.GetLSLFloatItem(idx++);
  7410. twist = rules.GetVector3Item(idx++);
  7411. holesize = rules.GetVector3Item(idx++);
  7412. topshear = rules.GetVector3Item(idx++);
  7413. profilecut = rules.GetVector3Item(idx++);
  7414. taper_b = rules.GetVector3Item(idx++); // taper_a
  7415. revolutions = (float) rules.GetLSLFloatItem(idx++);
  7416. radiusoffset = (float) rules.GetLSLFloatItem(idx++);
  7417. skew = (float) rules.GetLSLFloatItem(idx++);
  7418. (part as ISceneChildEntity).Shape.PathCurve = (byte) Extrusion.Curve1;
  7419. SetPrimitiveShapeParams((part as ISceneChildEntity), face, v, hollow, twist, holesize, topshear,
  7420. profilecut, taper_b,
  7421. revolutions, radiusoffset, skew, 0);
  7422. }
  7423. else if (code == (int) ScriptBaseClass.PRIM_TYPE_TUBE)
  7424. {
  7425. if (remain < 11)
  7426. return;
  7427. face = rules.GetLSLIntegerItem(idx++); // holeshape
  7428. v = rules.GetVector3Item(idx++); //cut
  7429. hollow = (float) rules.GetLSLFloatItem(idx++);
  7430. twist = rules.GetVector3Item(idx++);
  7431. holesize = rules.GetVector3Item(idx++);
  7432. topshear = rules.GetVector3Item(idx++);
  7433. profilecut = rules.GetVector3Item(idx++);
  7434. taper_b = rules.GetVector3Item(idx++); // taper_a
  7435. revolutions = (float) rules.GetLSLFloatItem(idx++);
  7436. radiusoffset = (float) rules.GetLSLFloatItem(idx++);
  7437. skew = (float) rules.GetLSLFloatItem(idx++);
  7438. (part as ISceneChildEntity).Shape.PathCurve = (byte) Extrusion.Curve1;
  7439. SetPrimitiveShapeParams((part as ISceneChildEntity), face, v, hollow, twist, holesize, topshear,
  7440. profilecut, taper_b,
  7441. revolutions, radiusoffset, skew, 1);
  7442. }
  7443. else if (code == (int) ScriptBaseClass.PRIM_TYPE_RING)
  7444. {
  7445. if (remain < 11)
  7446. return;
  7447. face = rules.GetLSLIntegerItem(idx++); // holeshape
  7448. v = rules.GetVector3Item(idx++); //cut
  7449. hollow = (float) rules.GetLSLFloatItem(idx++);
  7450. twist = rules.GetVector3Item(idx++);
  7451. holesize = rules.GetVector3Item(idx++);
  7452. topshear = rules.GetVector3Item(idx++);
  7453. profilecut = rules.GetVector3Item(idx++);
  7454. taper_b = rules.GetVector3Item(idx++); // taper_a
  7455. revolutions = (float) rules.GetLSLFloatItem(idx++);
  7456. radiusoffset = (float) rules.GetLSLFloatItem(idx++);
  7457. skew = (float) rules.GetLSLFloatItem(idx++);
  7458. (part as ISceneChildEntity).Shape.PathCurve = (byte) Extrusion.Curve1;
  7459. SetPrimitiveShapeParams((part as ISceneChildEntity), face, v, hollow, twist, holesize, topshear,
  7460. profilecut, taper_b,
  7461. revolutions, radiusoffset, skew, 3);
  7462. }
  7463. else if (code == (int) ScriptBaseClass.PRIM_TYPE_SCULPT)
  7464. {
  7465. if (remain < 2)
  7466. return;
  7467. string map = rules.Data[idx++].ToString();
  7468. face = rules.GetLSLIntegerItem(idx++); // type
  7469. (part as ISceneChildEntity).Shape.PathCurve = (byte) Extrusion.Curve1;
  7470. SetPrimitiveShapeParams((part as ISceneChildEntity), map, face);
  7471. }
  7472. }
  7473. else if (code == (int) ScriptBaseClass.PRIM_TEXTURE)
  7474. {
  7475. if (remain < 5)
  7476. return;
  7477. if (part is ISceneChildEntity)
  7478. {
  7479. }
  7480. else
  7481. return;
  7482. face = rules.GetLSLIntegerItem(idx++);
  7483. string tex = rules.Data[idx++].ToString();
  7484. LSL_Vector repeats = rules.GetVector3Item(idx++);
  7485. LSL_Vector offsets = rules.GetVector3Item(idx++);
  7486. double rotation = rules.GetLSLFloatItem(idx++);
  7487. SetTexture((part as ISceneChildEntity), tex, face);
  7488. ScaleTexture((part as ISceneChildEntity), repeats.x, repeats.y, face);
  7489. OffsetTexture((part as ISceneChildEntity), offsets.x, offsets.y, face);
  7490. RotateTexture((part as ISceneChildEntity), rotation, face);
  7491. }
  7492. else if (code == (int) ScriptBaseClass.PRIM_COLOR)
  7493. {
  7494. if (remain < 3)
  7495. return;
  7496. if (part is ISceneChildEntity)
  7497. {
  7498. }
  7499. else
  7500. return;
  7501. face = rules.GetLSLIntegerItem(idx++);
  7502. LSL_Vector color = rules.GetVector3Item(idx++);
  7503. double alpha = rules.GetLSLFloatItem(idx++);
  7504. (part as ISceneChildEntity).SetFaceColor(
  7505. new Vector3((float) color.x, (float) color.y, (float) color.z), face);
  7506. SetAlpha((part as ISceneChildEntity), alpha, face);
  7507. }
  7508. else if (code == (int) ScriptBaseClass.PRIM_FLEXIBLE)
  7509. {
  7510. if (remain < 7)
  7511. return;
  7512. if (!(part is ISceneChildEntity))
  7513. return;
  7514. bool flexi = rules.GetLSLIntegerItem(idx++);
  7515. int softness = rules.GetLSLIntegerItem(idx++);
  7516. float gravity = (float) rules.GetLSLFloatItem(idx++);
  7517. float friction = (float) rules.GetLSLFloatItem(idx++);
  7518. float wind = (float) rules.GetLSLFloatItem(idx++);
  7519. float tension = (float) rules.GetLSLFloatItem(idx++);
  7520. LSL_Vector force = rules.GetVector3Item(idx++);
  7521. SetFlexi((part as ISceneChildEntity), flexi, softness, gravity, friction, wind, tension, force);
  7522. }
  7523. else if (code == (int) ScriptBaseClass.PRIM_POINT_LIGHT)
  7524. {
  7525. if (remain < 5)
  7526. return;
  7527. if (!(part is ISceneChildEntity))
  7528. return;
  7529. bool light = rules.GetLSLIntegerItem(idx++);
  7530. LSL_Vector lightcolor = rules.GetVector3Item(idx++);
  7531. float intensity = (float) rules.GetLSLFloatItem(idx++);
  7532. float radius = (float) rules.GetLSLFloatItem(idx++);
  7533. float falloff = (float) rules.GetLSLFloatItem(idx++);
  7534. SetPointLight((part as ISceneChildEntity), light, lightcolor, intensity, radius, falloff);
  7535. }
  7536. else if (code == (int) ScriptBaseClass.PRIM_GLOW)
  7537. {
  7538. if (remain < 2)
  7539. return;
  7540. if (!(part is ISceneChildEntity))
  7541. return;
  7542. face = rules.GetLSLIntegerItem(idx++);
  7543. float glow = (float) rules.GetLSLFloatItem(idx++);
  7544. SetGlow((part as ISceneChildEntity), face, glow);
  7545. }
  7546. else if (code == (int) ScriptBaseClass.PRIM_BUMP_SHINY)
  7547. {
  7548. if (remain < 3)
  7549. return;
  7550. if (!(part is ISceneChildEntity))
  7551. return;
  7552. face = rules.GetLSLIntegerItem(idx++);
  7553. int shiny = rules.GetLSLIntegerItem(idx++);
  7554. Bumpiness bump = (Bumpiness) Convert.ToByte((int) rules.GetLSLIntegerItem(idx++));
  7555. SetShiny(part as ISceneChildEntity, face, shiny, bump);
  7556. }
  7557. else if (code == (int) ScriptBaseClass.PRIM_FULLBRIGHT)
  7558. {
  7559. if (remain < 2)
  7560. return;
  7561. if (!(part is ISceneChildEntity))
  7562. return;
  7563. face = rules.GetLSLIntegerItem(idx++);
  7564. bool st = rules.GetLSLIntegerItem(idx++);
  7565. SetFullBright(part as ISceneChildEntity, face, st);
  7566. }
  7567. else if (code == (int) ScriptBaseClass.PRIM_MATERIAL)
  7568. {
  7569. if (remain < 1)
  7570. return;
  7571. if (!(part is ISceneChildEntity))
  7572. return;
  7573. int mat = rules.GetLSLIntegerItem(idx++);
  7574. if (mat < 0 || mat > 7)
  7575. return;
  7576. (part as ISceneChildEntity).UpdateMaterial(mat);
  7577. }
  7578. else if (code == (int) ScriptBaseClass.PRIM_PHANTOM)
  7579. {
  7580. if (remain < 1)
  7581. return;
  7582. if (!(part is ISceneChildEntity))
  7583. return;
  7584. string ph = rules.Data[idx++].ToString();
  7585. bool phantom = ph.Equals("1");
  7586. (part as ISceneChildEntity).ScriptSetPhantomStatus(phantom);
  7587. }
  7588. else if (code == (int) ScriptBaseClass.PRIM_PHYSICS)
  7589. {
  7590. if (remain < 1)
  7591. return;
  7592. if (!(part is ISceneChildEntity))
  7593. return;
  7594. string phy = rules.Data[idx++].ToString();
  7595. m_host.ParentEntity.ScriptSetPhysicsStatus(phy.Equals("1"));
  7596. }
  7597. else if (code == (int) ScriptBaseClass.PRIM_TEMP_ON_REZ)
  7598. {
  7599. if (remain < 1)
  7600. return;
  7601. if (!(part is ISceneChildEntity))
  7602. return;
  7603. string temp = rules.Data[idx++].ToString();
  7604. bool tempOnRez = temp.Equals("1");
  7605. (part as ISceneChildEntity).ScriptSetTemporaryStatus(tempOnRez);
  7606. }
  7607. else if (code == (int) ScriptBaseClass.PRIM_TEXGEN)
  7608. {
  7609. if (remain < 2)
  7610. return;
  7611. if (!(part is ISceneChildEntity))
  7612. return;
  7613. //face,type
  7614. face = rules.GetLSLIntegerItem(idx++);
  7615. int style = rules.GetLSLIntegerItem(idx++);
  7616. SetTexGen((part as ISceneChildEntity), face, style);
  7617. }
  7618. else if (code == (int) ScriptBaseClass.PRIM_TEXT)
  7619. {
  7620. if (remain < 3)
  7621. return;
  7622. if (!(part is ISceneChildEntity))
  7623. return;
  7624. string primText = rules.GetLSLStringItem(idx++);
  7625. LSL_Vector primTextColor = rules.GetVector3Item(idx++);
  7626. LSL_Float primTextAlpha = rules.GetLSLFloatItem(idx++);
  7627. Vector3 av3 = new Vector3(Util.Clip((float) primTextColor.x, 0.0f, 1.0f),
  7628. Util.Clip((float) primTextColor.y, 0.0f, 1.0f),
  7629. Util.Clip((float) primTextColor.z, 0.0f, 1.0f));
  7630. (part as ISceneChildEntity).SetText(primText, av3, Util.Clip((float) primTextAlpha, 0.0f, 1.0f));
  7631. }
  7632. else if (code == (int) ScriptBaseClass.PRIM_OMEGA)
  7633. {
  7634. if (remain < 3)
  7635. return;
  7636. LSL_Vector direction = rules.GetVector3Item(idx++);
  7637. LSL_Float spinrate = rules.GetLSLFloatItem(idx++);
  7638. LSL_Float gain = rules.GetLSLFloatItem(idx++);
  7639. if (part is ISceneChildEntity)
  7640. llTargetOmega(direction, spinrate, gain);
  7641. }
  7642. else if (code == (int) ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE)
  7643. {
  7644. bool UsePhysics = ((m_host.Flags & PrimFlags.Physics) != 0);
  7645. bool IsTemporary = ((m_host.Flags & PrimFlags.TemporaryOnRez) != 0);
  7646. bool IsPhantom = ((m_host.Flags & PrimFlags.Phantom) != 0);
  7647. bool IsVolumeDetect = m_host.VolumeDetectActive;
  7648. ObjectFlagUpdatePacket.ExtraPhysicsBlock[] blocks = new ObjectFlagUpdatePacket.ExtraPhysicsBlock[1];
  7649. blocks[0] = new ObjectFlagUpdatePacket.ExtraPhysicsBlock
  7650. {
  7651. Density = m_host.Density,
  7652. Friction = m_host.Friction,
  7653. GravityMultiplier = m_host.GravityMultiplier
  7654. };
  7655. LSL_Integer shapeType = rules.GetLSLIntegerItem(idx++);
  7656. if (shapeType == ScriptBaseClass.PRIM_PHYSICS_SHAPE_PRIM)
  7657. blocks[0].PhysicsShapeType = (byte) shapeType.value;
  7658. else if (shapeType == ScriptBaseClass.PRIM_PHYSICS_SHAPE_NONE)
  7659. blocks[0].PhysicsShapeType = (byte) shapeType.value;
  7660. else //if(shapeType == ScriptBaseClass.PRIM_PHYSICS_SHAPE_CONVEX)
  7661. blocks[0].PhysicsShapeType = (byte) shapeType.value;
  7662. blocks[0].Restitution = m_host.Restitution;
  7663. if (part is ISceneChildEntity)
  7664. if ((part as ISceneChildEntity).UpdatePrimFlags(UsePhysics,
  7665. IsTemporary, IsPhantom, IsVolumeDetect, blocks))
  7666. (part as ISceneChildEntity).ParentEntity.RebuildPhysicalRepresentation(true);
  7667. }
  7668. else if (code == (int) ScriptBaseClass.PRIM_LINK_TARGET)
  7669. {
  7670. if (remain < 1)
  7671. return;
  7672. LSL_Integer nextLink = rules.GetLSLIntegerItem(idx++);
  7673. List<IEntity> entities = GetLinkPartsAndEntities(nextLink);
  7674. if (entities.Count > 0)
  7675. part = entities[0];
  7676. }
  7677. }
  7678. }
  7679. public LSL_String llStringToBase64(string str)
  7680. {
  7681. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  7682. try
  7683. {
  7684. byte[] encData_byte = new byte[str.Length];
  7685. encData_byte = Util.UTF8.GetBytes(str);
  7686. string encodedData = Convert.ToBase64String(encData_byte);
  7687. return encodedData;
  7688. }
  7689. catch (Exception e)
  7690. {
  7691. throw new Exception("Error in base64Encode" + e);
  7692. }
  7693. }
  7694. public LSL_String llBase64ToString(string str)
  7695. {
  7696. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  7697. try
  7698. {
  7699. return Util.Base64ToString(str);
  7700. }
  7701. catch (Exception e)
  7702. {
  7703. throw new Exception("Error in base64Decode" + e);
  7704. }
  7705. }
  7706. public LSL_String llXorBase64Strings(string str1, string str2)
  7707. {
  7708. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  7709. Deprecated("llXorBase64Strings");
  7710. ScriptSleep(300);
  7711. return String.Empty;
  7712. }
  7713. public void llRemoteDataSetRegion()
  7714. {
  7715. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  7716. Deprecated("llRemoteDataSetRegion");
  7717. }
  7718. public LSL_Float llLog10(double val)
  7719. {
  7720. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  7721. return new LSL_Float();
  7722. return Math.Log10(val);
  7723. }
  7724. public LSL_Float llLog(double val)
  7725. {
  7726. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  7727. return new LSL_Float();
  7728. return Math.Log(val);
  7729. }
  7730. public LSL_List llGetAnimationList(string id)
  7731. {
  7732. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  7733. return new LSL_List();
  7734. LSL_List l = new LSL_List();
  7735. IScenePresence av = World.GetScenePresence((UUID) id);
  7736. if (av == null || av.IsChildAgent) // only if in the region
  7737. return l;
  7738. UUID[] anims = av.Animator.GetAnimationArray();
  7739. foreach (UUID foo in anims)
  7740. l.Add(new LSL_Key(foo.ToString()));
  7741. return l;
  7742. }
  7743. public DateTime llSetParcelMusicURL(string url)
  7744. {
  7745. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  7746. return DateTime.Now;
  7747. IParcelManagementModule parcelManagement = World.RequestModuleInterface<IParcelManagementModule>();
  7748. if (parcelManagement != null)
  7749. {
  7750. ILandObject land = parcelManagement.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y);
  7751. if (land == null)
  7752. return DateTime.Now;
  7753. if (!World.Permissions.CanEditParcel(m_host.OwnerID, land))
  7754. return DateTime.Now;
  7755. land.SetMusicUrl(url);
  7756. }
  7757. return PScriptSleep(2000);
  7758. }
  7759. public LSL_Vector llGetRootPosition()
  7760. {
  7761. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  7762. return new LSL_Vector();
  7763. return new LSL_Vector(m_host.ParentEntity.AbsolutePosition.X, m_host.ParentEntity.AbsolutePosition.Y,
  7764. m_host.ParentEntity.AbsolutePosition.Z);
  7765. }
  7766. /// <summary>
  7767. /// http://lslwiki.net/lslwiki/wakka.php?wakka=llGetRot
  7768. /// http://lslwiki.net/lslwiki/wakka.php?wakka=ChildRotation
  7769. /// Also tested in sl in regards to the behaviour in attachments/mouselook
  7770. /// In the root prim:-
  7771. /// Returns the object rotation if not attached
  7772. /// Returns the avatars rotation if attached
  7773. /// Returns the camera rotation if attached and the avatar is in mouselook
  7774. /// </summary>
  7775. public LSL_Rotation llGetRootRotation()
  7776. {
  7777. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  7778. return new LSL_Rotation();
  7779. Quaternion q;
  7780. if (m_host.ParentEntity.RootChild.AttachmentPoint != 0)
  7781. {
  7782. IScenePresence avatar = World.GetScenePresence(m_host.AttachedAvatar);
  7783. if (avatar != null)
  7784. q = (avatar.AgentControlFlags & (uint) AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0
  7785. ? avatar.CameraRotation
  7786. : avatar.Rotation;
  7787. else
  7788. q = m_host.ParentEntity.GroupRotation; // Likely never get here but just in case
  7789. }
  7790. else
  7791. q = m_host.ParentEntity.GroupRotation; // just the group rotation
  7792. return new LSL_Rotation(q.X, q.Y, q.Z, q.W);
  7793. }
  7794. public LSL_String llGetObjectDesc()
  7795. {
  7796. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  7797. return m_host.Description ?? String.Empty;
  7798. }
  7799. public void llSetObjectDesc(string desc)
  7800. {
  7801. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  7802. m_host.Description = desc ?? String.Empty;
  7803. }
  7804. public LSL_String llGetCreator()
  7805. {
  7806. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  7807. return m_host.CreatorID.ToString();
  7808. }
  7809. public LSL_String llGetTimestamp()
  7810. {
  7811. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  7812. return DateTime.Now.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ");
  7813. }
  7814. public LSL_Integer llGetNumberOfPrims()
  7815. {
  7816. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  7817. int avatarCount = m_host.ParentEntity.SitTargetAvatar.Count;
  7818. return m_host.ParentEntity.PrimCount + avatarCount;
  7819. }
  7820. /// <summary>
  7821. /// A partial implementation.
  7822. /// http://lslwiki.net/lslwiki/wakka.php?wakka=llGetBoundingBox
  7823. /// So far only valid for standing/flying/ground sitting avatars and single prim objects.
  7824. /// If the object has multiple prims and/or a sitting avatar then the bounding
  7825. /// box is for the root prim only.
  7826. /// </summary>
  7827. public LSL_List llGetBoundingBox(string obj)
  7828. {
  7829. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  7830. return new LSL_List();
  7831. UUID objID = UUID.Zero;
  7832. LSL_List result = new LSL_List();
  7833. if (!UUID.TryParse(obj, out objID))
  7834. {
  7835. result.Add(new LSL_Vector());
  7836. result.Add(new LSL_Vector());
  7837. return result;
  7838. }
  7839. IScenePresence presence = World.GetScenePresence(objID);
  7840. if (presence != null)
  7841. {
  7842. if (presence.ParentID == UUID.Zero) // not sat on an object
  7843. {
  7844. LSL_Vector lower = new LSL_Vector();
  7845. LSL_Vector upper = new LSL_Vector();
  7846. if (presence.Animator.Animations.ImplicitDefaultAnimation.AnimID
  7847. == AnimationSet.Animations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
  7848. {
  7849. // This is for ground sitting avatars
  7850. IAvatarAppearanceModule appearance = presence.RequestModuleInterface<IAvatarAppearanceModule>();
  7851. if (appearance != null)
  7852. {
  7853. float height = appearance.Appearance.AvatarHeight/2.66666667f;
  7854. lower = new LSL_Vector(-0.3375f, -0.45f, height*-1.0f);
  7855. upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
  7856. }
  7857. }
  7858. else
  7859. {
  7860. // This is for standing/flying avatars
  7861. IAvatarAppearanceModule appearance = presence.RequestModuleInterface<IAvatarAppearanceModule>();
  7862. if (appearance != null)
  7863. {
  7864. float height = appearance.Appearance.AvatarHeight/2.0f;
  7865. lower = new LSL_Vector(-0.225f, -0.3f, height*-1.0f);
  7866. upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
  7867. }
  7868. }
  7869. result.Add(lower);
  7870. result.Add(upper);
  7871. return result;
  7872. }
  7873. // sitting on an object so we need the bounding box of that
  7874. // which should include the avatar so set the UUID to the
  7875. // UUID of the object the avatar is sat on and allow it to fall through
  7876. // to processing an object
  7877. ISceneChildEntity p = World.GetSceneObjectPart(presence.ParentID);
  7878. objID = p.UUID;
  7879. }
  7880. ISceneChildEntity part = World.GetSceneObjectPart(objID);
  7881. // Currently only works for single prims without a sitting avatar
  7882. if (part != null)
  7883. {
  7884. Vector3 halfSize = part.Scale*0.5f;
  7885. LSL_Vector lower = new LSL_Vector(halfSize.X*-1.0f, halfSize.Y*-1.0f, halfSize.Z*-1.0f);
  7886. LSL_Vector upper = new LSL_Vector(halfSize.X, halfSize.Y, halfSize.Z);
  7887. result.Add(lower);
  7888. result.Add(upper);
  7889. return result;
  7890. }
  7891. // Not found so return empty values
  7892. result.Add(new LSL_Vector());
  7893. result.Add(new LSL_Vector());
  7894. return result;
  7895. }
  7896. public LSL_Vector llGetGeometricCenter()
  7897. {
  7898. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  7899. return new LSL_Vector();
  7900. Vector3 MinPos = new Vector3(100000, 100000, 100000);
  7901. Vector3 MaxPos = new Vector3(-100000, -100000, -100000);
  7902. foreach (ISceneChildEntity child in m_host.ParentEntity.ChildrenEntities())
  7903. {
  7904. Vector3 tmp = child.AbsolutePosition;
  7905. if (tmp.X < MinPos.X)
  7906. MinPos.X = tmp.X;
  7907. if (tmp.Y < MinPos.Y)
  7908. MinPos.Y = tmp.Y;
  7909. if (tmp.Z < MinPos.Z)
  7910. MinPos.Z = tmp.Z;
  7911. if (tmp.X > MaxPos.X)
  7912. MaxPos.X = tmp.X;
  7913. if (tmp.Y > MaxPos.Y)
  7914. MaxPos.Y = tmp.Y;
  7915. if (tmp.Z > MaxPos.Z)
  7916. MaxPos.Z = tmp.Z;
  7917. }
  7918. Vector3 GroupAvg = ((MaxPos + MinPos)/2);
  7919. return new LSL_Vector(GroupAvg.X, GroupAvg.Y, GroupAvg.Z);
  7920. //Just plain wrong!
  7921. //return new LSL_Vector(m_host.GetGeometricCenter().X, m_host.GetGeometricCenter().Y, m_host.GetGeometricCenter().Z);
  7922. }
  7923. public LSL_List llGetPrimitiveParams(LSL_List rules)
  7924. {
  7925. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  7926. return new LSL_List();
  7927. return GetLinkPrimitiveParams(m_host, rules);
  7928. }
  7929. public LSL_List llGetLinkPrimitiveParams(int linknumber, LSL_List rules)
  7930. {
  7931. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  7932. return new LSL_List();
  7933. List<ISceneChildEntity> parts = GetLinkParts(linknumber);
  7934. LSL_List res = new LSL_List();
  7935. #if (!ISWIN)
  7936. LSL_List result = res;
  7937. foreach (ISceneChildEntity part in parts)
  7938. {
  7939. LSL_List list = GetLinkPrimitiveParams(part, rules);
  7940. result = result + list;
  7941. }
  7942. return result;
  7943. #else
  7944. return parts.Select(part => GetLinkPrimitiveParams(part, rules))
  7945. .Aggregate(res, (current, partRes) => current + partRes);
  7946. #endif
  7947. }
  7948. public LSL_List GetLinkPrimitiveParams(ISceneChildEntity part, LSL_List rules)
  7949. {
  7950. LSL_List res = new LSL_List();
  7951. int idx = 0;
  7952. while (idx < rules.Length)
  7953. {
  7954. int code = rules.GetLSLIntegerItem(idx++);
  7955. int remain = rules.Length - idx;
  7956. Primitive.TextureEntry tex = part.Shape.Textures;
  7957. int face = 0;
  7958. if (code == (int) ScriptBaseClass.PRIM_NAME)
  7959. {
  7960. res.Add(new LSL_String(part.Name));
  7961. }
  7962. else if (code == (int) ScriptBaseClass.PRIM_DESC)
  7963. {
  7964. res.Add(new LSL_String(part.Description));
  7965. }
  7966. else if (code == (int) ScriptBaseClass.PRIM_MATERIAL)
  7967. {
  7968. res.Add(new LSL_Integer(part.Material));
  7969. }
  7970. else if (code == (int) ScriptBaseClass.PRIM_PHYSICS)
  7971. {
  7972. res.Add((part.GetEffectiveObjectFlags() & (uint) PrimFlags.Physics) != 0
  7973. ? new LSL_Integer(1)
  7974. : new LSL_Integer(0));
  7975. }
  7976. else if (code == (int) ScriptBaseClass.PRIM_TEMP_ON_REZ)
  7977. {
  7978. res.Add((part.GetEffectiveObjectFlags() & (uint) PrimFlags.TemporaryOnRez) != 0
  7979. ? new LSL_Integer(1)
  7980. : new LSL_Integer(0));
  7981. }
  7982. else if (code == (int) ScriptBaseClass.PRIM_PHANTOM)
  7983. {
  7984. res.Add((part.GetEffectiveObjectFlags() & (uint) PrimFlags.Phantom) != 0
  7985. ? new LSL_Integer(1)
  7986. : new LSL_Integer(0));
  7987. }
  7988. else if (code == (int) ScriptBaseClass.PRIM_POSITION)
  7989. {
  7990. Vector3 tmp = part.AbsolutePosition;
  7991. LSL_Vector v = new LSL_Vector(tmp.X,
  7992. tmp.Y,
  7993. tmp.Z);
  7994. // For some reason, the part.AbsolutePosition.* values do not change if the
  7995. // linkset is rotated; they always reflect the child prim's world position
  7996. // as though the linkset is unrotated. This is incompatible behavior with SL's
  7997. // implementation, so will break scripts imported from there (not to mention it
  7998. // makes it more difficult to determine a child prim's actual inworld position).
  7999. if (part.ParentID != 0)
  8000. {
  8001. LSL_Rotation rtmp = llGetRootRotation();
  8002. LSL_Vector rpos = llGetRootPosition();
  8003. v = ((v - rpos)*rtmp) + rpos;
  8004. }
  8005. res.Add(v);
  8006. }
  8007. else if (code == (int) ScriptBaseClass.PRIM_POS_LOCAL)
  8008. {
  8009. res.Add(GetLocalPos(part));
  8010. }
  8011. else if (code == (int) ScriptBaseClass.PRIM_SIZE)
  8012. {
  8013. Vector3 tmp = part.Scale;
  8014. res.Add(new LSL_Vector(tmp.X,
  8015. tmp.Y,
  8016. tmp.Z));
  8017. }
  8018. else if (code == (int) ScriptBaseClass.PRIM_ROTATION)
  8019. {
  8020. res.Add(GetPartRot(part));
  8021. }
  8022. else if (code == (int) ScriptBaseClass.PRIM_TYPE)
  8023. {
  8024. // implementing box
  8025. PrimitiveBaseShape Shape = part.Shape;
  8026. int primType = (int) part.GetPrimType();
  8027. res.Add(new LSL_Integer(primType));
  8028. double topshearx = (sbyte) Shape.PathShearX/100.0; // Fix negative values for PathShearX
  8029. double topsheary = (sbyte) Shape.PathShearY/100.0; // and PathShearY.
  8030. if (primType == ScriptBaseClass.PRIM_TYPE_BOX ||
  8031. primType == ScriptBaseClass.PRIM_TYPE_CYLINDER ||
  8032. primType == ScriptBaseClass.PRIM_TYPE_PRISM)
  8033. {
  8034. res.Add(new LSL_Integer(Shape.ProfileCurve));
  8035. res.Add(new LSL_Vector(Shape.ProfileBegin/50000.0, 1 - Shape.ProfileEnd/50000.0, 0));
  8036. res.Add(new LSL_Float(Shape.ProfileHollow/50000.0));
  8037. res.Add(new LSL_Vector(Shape.PathTwistBegin/100.0, Shape.PathTwist/100.0, 0));
  8038. res.Add(new LSL_Vector(1 - (Shape.PathScaleX/100.0 - 1), 1 - (Shape.PathScaleY/100.0 - 1), 0));
  8039. res.Add(new LSL_Vector(topshearx, topsheary, 0));
  8040. }
  8041. if (primType == ScriptBaseClass.PRIM_TYPE_SPHERE)
  8042. {
  8043. res.Add(new LSL_Integer(Shape.ProfileCurve));
  8044. res.Add(new LSL_Vector(Shape.PathBegin/50000.0, 1 - Shape.PathEnd/50000.0, 0));
  8045. res.Add(new LSL_Float(Shape.ProfileHollow/50000.0));
  8046. res.Add(new LSL_Vector(Shape.PathTwistBegin/100.0, Shape.PathTwist/100.0, 0));
  8047. res.Add(new LSL_Vector(Shape.ProfileBegin/50000.0, 1 - Shape.ProfileEnd/50000.0, 0));
  8048. }
  8049. if (primType == ScriptBaseClass.PRIM_TYPE_SCULPT)
  8050. {
  8051. res.Add(Shape.SculptTexture.ToString());
  8052. res.Add(new LSL_Integer(Shape.SculptType));
  8053. }
  8054. if (primType == ScriptBaseClass.PRIM_TYPE_RING ||
  8055. primType == ScriptBaseClass.PRIM_TYPE_TUBE ||
  8056. primType == ScriptBaseClass.PRIM_TYPE_TORUS)
  8057. {
  8058. // holeshape
  8059. res.Add(new LSL_Integer(Shape.ProfileCurve));
  8060. // cut
  8061. res.Add(new LSL_Vector(Shape.PathBegin/50000.0, 1 - Shape.PathEnd/50000.0, 0));
  8062. // hollow
  8063. res.Add(new LSL_Float(Shape.ProfileHollow/50000.0));
  8064. // twist
  8065. res.Add(new LSL_Vector(Shape.PathTwistBegin/100.0, Shape.PathTwist/100.0, 0));
  8066. // vector holesize
  8067. res.Add(new LSL_Vector(1 - (Shape.PathScaleX/100.0 - 1), 1 - (Shape.PathScaleY/100.0 - 1), 0));
  8068. // vector topshear
  8069. res.Add(new LSL_Vector(topshearx, topsheary, 0));
  8070. // vector profilecut
  8071. res.Add(new LSL_Vector(Shape.ProfileBegin/50000.0, 1 - Shape.ProfileEnd/50000.0, 0));
  8072. // vector tapera
  8073. res.Add(new LSL_Vector(Shape.PathTaperX/100.0, Shape.PathTaperY/100.0, 0));
  8074. // float revolutions
  8075. res.Add(
  8076. new LSL_Float(Math.Round(Shape.PathRevolutions*0.015d, 2, MidpointRounding.AwayFromZero)) +
  8077. 1.0d);
  8078. // Slightly inaccurate, because an unsigned byte is being used to represent
  8079. // the entire range of floating-point values from 1.0 through 4.0 (which is how
  8080. // SL does it).
  8081. //
  8082. // Using these formulas to store and retrieve PathRevolutions, it is not
  8083. // possible to use all values between 1.00 and 4.00. For instance, you can't
  8084. // represent 1.10. You can represent 1.09 and 1.11, but not 1.10. So, if you
  8085. // use llSetPrimitiveParams to set revolutions to 1.10 and then retreive them
  8086. // with llGetPrimitiveParams, you'll retrieve 1.09. You can also see a similar
  8087. // behavior in the viewer as you cannot set 1.10. The viewer jumps to 1.11.
  8088. // In SL, llSetPrimitveParams and llGetPrimitiveParams can set and get a value
  8089. // such as 1.10. So, SL must store and retreive the actual user input rather
  8090. // than only storing the encoded value.
  8091. // float radiusoffset
  8092. res.Add(new LSL_Float(Shape.PathRadiusOffset/100.0));
  8093. // float skew
  8094. res.Add(new LSL_Float(Shape.PathSkew/100.0));
  8095. }
  8096. }
  8097. else if (code == (int) ScriptBaseClass.PRIM_TEXTURE)
  8098. {
  8099. if (remain < 1)
  8100. return res;
  8101. face = rules.GetLSLIntegerItem(idx++);
  8102. if (face == ScriptBaseClass.ALL_SIDES)
  8103. {
  8104. for (face = 0; face < GetNumberOfSides(part); face++)
  8105. {
  8106. Primitive.TextureEntryFace texface = tex.GetFace((uint) face);
  8107. res.Add(new LSL_String(texface.TextureID.ToString()));
  8108. res.Add(new LSL_Vector(texface.RepeatU,
  8109. texface.RepeatV,
  8110. 0));
  8111. res.Add(new LSL_Vector(texface.OffsetU,
  8112. texface.OffsetV,
  8113. 0));
  8114. res.Add(new LSL_Float(texface.Rotation));
  8115. }
  8116. }
  8117. else
  8118. {
  8119. if (face >= 0 && face < GetNumberOfSides(part))
  8120. {
  8121. Primitive.TextureEntryFace texface = tex.GetFace((uint) face);
  8122. res.Add(new LSL_String(texface.TextureID.ToString()));
  8123. res.Add(new LSL_Vector(texface.RepeatU,
  8124. texface.RepeatV,
  8125. 0));
  8126. res.Add(new LSL_Vector(texface.OffsetU,
  8127. texface.OffsetV,
  8128. 0));
  8129. res.Add(new LSL_Float(texface.Rotation));
  8130. }
  8131. }
  8132. }
  8133. else if (code == (int) ScriptBaseClass.PRIM_COLOR)
  8134. {
  8135. if (remain < 1)
  8136. return res;
  8137. face = rules.GetLSLIntegerItem(idx++);
  8138. tex = part.Shape.Textures;
  8139. Color4 texcolor;
  8140. if (face == ScriptBaseClass.ALL_SIDES)
  8141. {
  8142. for (face = 0; face < GetNumberOfSides(part); face++)
  8143. {
  8144. texcolor = tex.GetFace((uint) face).RGBA;
  8145. res.Add(new LSL_Vector(texcolor.R,
  8146. texcolor.G,
  8147. texcolor.B));
  8148. res.Add(new LSL_Float(texcolor.A));
  8149. }
  8150. }
  8151. else
  8152. {
  8153. texcolor = tex.GetFace((uint) face).RGBA;
  8154. res.Add(new LSL_Vector(texcolor.R,
  8155. texcolor.G,
  8156. texcolor.B));
  8157. res.Add(new LSL_Float(texcolor.A));
  8158. }
  8159. }
  8160. else if (code == (int) ScriptBaseClass.PRIM_BUMP_SHINY)
  8161. {
  8162. if (remain < 1)
  8163. return res;
  8164. face = rules.GetLSLIntegerItem(idx++);
  8165. if (face == ScriptBaseClass.ALL_SIDES)
  8166. {
  8167. for (face = 0; face < GetNumberOfSides(part); face++)
  8168. {
  8169. Primitive.TextureEntryFace texface = tex.GetFace((uint) face);
  8170. // Convert Shininess to PRIM_SHINY_*
  8171. res.Add(new LSL_Integer((uint) texface.Shiny >> 6));
  8172. // PRIM_BUMP_*
  8173. res.Add(new LSL_Integer((int) texface.Bump));
  8174. }
  8175. }
  8176. else
  8177. {
  8178. if (face >= 0 && face < GetNumberOfSides(part))
  8179. {
  8180. Primitive.TextureEntryFace texface = tex.GetFace((uint) face);
  8181. // Convert Shininess to PRIM_SHINY_*
  8182. res.Add(new LSL_Integer((uint) texface.Shiny >> 6));
  8183. // PRIM_BUMP_*
  8184. res.Add(new LSL_Integer((int) texface.Bump));
  8185. }
  8186. }
  8187. }
  8188. else if (code == (int) ScriptBaseClass.PRIM_FULLBRIGHT)
  8189. {
  8190. if (remain < 1)
  8191. return res;
  8192. face = rules.GetLSLIntegerItem(idx++);
  8193. tex = part.Shape.Textures;
  8194. if (face == ScriptBaseClass.ALL_SIDES)
  8195. {
  8196. for (face = 0; face < GetNumberOfSides(part); face++)
  8197. {
  8198. Primitive.TextureEntryFace texface = tex.GetFace((uint) face);
  8199. res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0));
  8200. }
  8201. }
  8202. else
  8203. {
  8204. if (face >= 0 && face < GetNumberOfSides(part))
  8205. {
  8206. Primitive.TextureEntryFace texface = tex.GetFace((uint) face);
  8207. res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0));
  8208. }
  8209. }
  8210. }
  8211. else if (code == (int) ScriptBaseClass.PRIM_FLEXIBLE)
  8212. {
  8213. PrimitiveBaseShape shape = part.Shape;
  8214. res.Add(shape.FlexiEntry ? new LSL_Integer(1) : new LSL_Integer(0));
  8215. res.Add(new LSL_Integer(shape.FlexiSoftness)); // softness
  8216. res.Add(new LSL_Float(shape.FlexiGravity)); // gravity
  8217. res.Add(new LSL_Float(shape.FlexiDrag)); // friction
  8218. res.Add(new LSL_Float(shape.FlexiWind)); // wind
  8219. res.Add(new LSL_Float(shape.FlexiTension)); // tension
  8220. res.Add(new LSL_Vector(shape.FlexiForceX, // force
  8221. shape.FlexiForceY,
  8222. shape.FlexiForceZ));
  8223. }
  8224. else if (code == (int) ScriptBaseClass.PRIM_TEXGEN)
  8225. {
  8226. if (remain < 1)
  8227. return res;
  8228. face = rules.GetLSLIntegerItem(idx++);
  8229. if (face == ScriptBaseClass.ALL_SIDES)
  8230. {
  8231. for (face = 0; face < GetNumberOfSides(part); face++)
  8232. {
  8233. MappingType texgen = tex.GetFace((uint) face).TexMapType;
  8234. // Convert MappingType to PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR etc.
  8235. res.Add(new LSL_Integer((uint) texgen >> 1));
  8236. }
  8237. }
  8238. else
  8239. {
  8240. if (face >= 0 && face < GetNumberOfSides(part))
  8241. {
  8242. MappingType texgen = tex.GetFace((uint) face).TexMapType;
  8243. res.Add(new LSL_Integer((uint) texgen >> 1));
  8244. }
  8245. }
  8246. }
  8247. else if (code == (int) ScriptBaseClass.PRIM_POINT_LIGHT)
  8248. {
  8249. PrimitiveBaseShape shape = part.Shape;
  8250. res.Add(shape.LightEntry ? new LSL_Integer(1) : new LSL_Integer(0));
  8251. res.Add(new LSL_Vector(shape.LightColorR, // color
  8252. shape.LightColorG,
  8253. shape.LightColorB));
  8254. res.Add(new LSL_Float(shape.LightIntensity)); // intensity
  8255. res.Add(new LSL_Float(shape.LightRadius)); // radius
  8256. res.Add(new LSL_Float(shape.LightFalloff)); // falloff
  8257. }
  8258. else if (code == (int) ScriptBaseClass.PRIM_GLOW)
  8259. {
  8260. if (remain < 1)
  8261. return res;
  8262. face = rules.GetLSLIntegerItem(idx++);
  8263. if (face == ScriptBaseClass.ALL_SIDES)
  8264. {
  8265. for (face = 0; face < GetNumberOfSides(part); face++)
  8266. {
  8267. Primitive.TextureEntryFace texface = tex.GetFace((uint) face);
  8268. res.Add(new LSL_Float(texface.Glow));
  8269. }
  8270. }
  8271. else
  8272. {
  8273. if (face >= 0 && face < GetNumberOfSides(part))
  8274. {
  8275. Primitive.TextureEntryFace texface = tex.GetFace((uint) face);
  8276. res.Add(new LSL_Float(texface.Glow));
  8277. }
  8278. }
  8279. }
  8280. else if (code == (int) ScriptBaseClass.PRIM_TEXT)
  8281. {
  8282. Color4 textColor = part.GetTextColor();
  8283. res.Add(new LSL_String(part.Text));
  8284. res.Add(new LSL_Vector(textColor.R,
  8285. textColor.G,
  8286. textColor.B));
  8287. res.Add(new LSL_Float(textColor.A));
  8288. }
  8289. else if (code == (int) ScriptBaseClass.PRIM_ROT_LOCAL)
  8290. {
  8291. Quaternion rtmp = part.GetRotationOffset();
  8292. res.Add(new LSL_Rotation(rtmp.X, rtmp.Y, rtmp.Z, rtmp.W));
  8293. }
  8294. else if (code == (int) ScriptBaseClass.PRIM_OMEGA)
  8295. {
  8296. Vector3 axis = part.OmegaAxis;
  8297. LSL_Float spinRate = part.OmegaSpinRate;
  8298. LSL_Float gain = part.OmegaGain;
  8299. res.Add(axis);
  8300. res.Add(spinRate);
  8301. res.Add(gain);
  8302. }
  8303. else if (code == (int) ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE)
  8304. {
  8305. res.Add(new LSL_Integer(part.PhysicsType));
  8306. }
  8307. else if (code == (int) ScriptBaseClass.PRIM_LINK_TARGET)
  8308. {
  8309. if (remain < 1)
  8310. continue;
  8311. LSL_Integer nextLink = rules.GetLSLIntegerItem(idx++);
  8312. List<ISceneChildEntity> entities = GetLinkParts(nextLink);
  8313. if (entities.Count > 0)
  8314. part = entities[0];
  8315. }
  8316. }
  8317. return res;
  8318. }
  8319. public LSL_List llGetPhysicsMaterial()
  8320. {
  8321. return new LSL_List(m_host.GravityMultiplier, m_host.Restitution, m_host.Friction, m_host.Density);
  8322. }
  8323. public void llSetPhysicsMaterial(LSL_Integer bits, LSL_Float density, LSL_Float friction, LSL_Float restitution,
  8324. LSL_Float gravityMultiplier)
  8325. {
  8326. ObjectFlagUpdatePacket.ExtraPhysicsBlock[] blocks = new ObjectFlagUpdatePacket.ExtraPhysicsBlock[1];
  8327. blocks[0] = new ObjectFlagUpdatePacket.ExtraPhysicsBlock();
  8328. if ((bits & ScriptBaseClass.DENSITY) == ScriptBaseClass.DENSITY)
  8329. m_host.Density = (float) density;
  8330. else
  8331. blocks[0].Density = m_host.Density;
  8332. if ((bits & ScriptBaseClass.FRICTION) == ScriptBaseClass.FRICTION)
  8333. m_host.Friction = (float) friction;
  8334. else
  8335. blocks[0].Friction = m_host.Friction;
  8336. if ((bits & ScriptBaseClass.RESTITUTION) == ScriptBaseClass.RESTITUTION)
  8337. m_host.Restitution = (float) restitution;
  8338. else
  8339. blocks[0].Restitution = m_host.Restitution;
  8340. if ((bits & ScriptBaseClass.GRAVITY_MULTIPLIER) == ScriptBaseClass.GRAVITY_MULTIPLIER)
  8341. m_host.GravityMultiplier = (float) gravityMultiplier;
  8342. else
  8343. blocks[0].GravityMultiplier = m_host.GravityMultiplier;
  8344. bool UsePhysics = ((m_host.Flags & PrimFlags.Physics) != 0);
  8345. bool IsTemporary = ((m_host.Flags & PrimFlags.TemporaryOnRez) != 0);
  8346. bool IsPhantom = ((m_host.Flags & PrimFlags.Phantom) != 0);
  8347. bool IsVolumeDetect = m_host.VolumeDetectActive;
  8348. blocks[0].PhysicsShapeType = m_host.PhysicsType;
  8349. if (m_host.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect, blocks))
  8350. m_host.ParentEntity.RebuildPhysicalRepresentation(true);
  8351. }
  8352. // <remarks>
  8353. // <para>
  8354. // The .NET definition of base 64 is:
  8355. // <list>
  8356. // <item>
  8357. // Significant: A-Z a-z 0-9 + -
  8358. // </item>
  8359. // <item>
  8360. // Whitespace: \t \n \r ' '
  8361. // </item>
  8362. // <item>
  8363. // Valueless: =
  8364. // </item>
  8365. // <item>
  8366. // End-of-string: \0 or '=='
  8367. // </item>
  8368. // </list>
  8369. // </para>
  8370. // <para>
  8371. // Each point in a base-64 string represents
  8372. // a 6 bit value. A 32-bit integer can be
  8373. // represented using 6 characters (with some
  8374. // redundancy).
  8375. // </para>
  8376. // <para>
  8377. // LSL requires a base64 string to be 8
  8378. // characters in length. LSL also uses '/'
  8379. // rather than '-' (MIME compliant).
  8380. // </para>
  8381. // <para>
  8382. // RFC 1341 used as a reference (as specified
  8383. // by the SecondLife Wiki).
  8384. // </para>
  8385. // <para>
  8386. // SL do not record any kind of exception for
  8387. // these functions, so the string to integer
  8388. // conversion returns '0' if an invalid
  8389. // character is encountered during conversion.
  8390. // </para>
  8391. // <para>
  8392. // References
  8393. // <list>
  8394. // <item>
  8395. // http://lslwiki.net/lslwiki/wakka.php?wakka=Base64
  8396. // </item>
  8397. // <item>
  8398. // </item>
  8399. // </list>
  8400. // </para>
  8401. // </remarks>
  8402. // <summary>
  8403. // Table for converting 6-bit integers into
  8404. // base-64 characters
  8405. // </summary>
  8406. protected static readonly char[] i2ctable =
  8407. {
  8408. 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
  8409. 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
  8410. 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
  8411. 'Y', 'Z',
  8412. 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
  8413. 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
  8414. 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
  8415. 'y', 'z',
  8416. '0', '1', '2', '3', '4', '5', '6', '7',
  8417. '8', '9',
  8418. '+', '/'
  8419. };
  8420. // <summary>
  8421. // Table for converting base-64 characters
  8422. // into 6-bit integers.
  8423. // </summary>
  8424. protected static readonly int[] c2itable =
  8425. {
  8426. -1, -1, -1, -1, -1, -1, -1, -1, // 0x
  8427. -1, -1, -1, -1, -1, -1, -1, -1,
  8428. -1, -1, -1, -1, -1, -1, -1, -1, // 1x
  8429. -1, -1, -1, -1, -1, -1, -1, -1,
  8430. -1, -1, -1, -1, -1, -1, -1, -1, // 2x
  8431. -1, -1, -1, 63, -1, -1, -1, 64,
  8432. 53, 54, 55, 56, 57, 58, 59, 60, // 3x
  8433. 61, 62, -1, -1, -1, 0, -1, -1,
  8434. -1, 1, 2, 3, 4, 5, 6, 7, // 4x
  8435. 8, 9, 10, 11, 12, 13, 14, 15,
  8436. 16, 17, 18, 19, 20, 21, 22, 23, // 5x
  8437. 24, 25, 26, -1, -1, -1, -1, -1,
  8438. -1, 27, 28, 29, 30, 31, 32, 33, // 6x
  8439. 34, 35, 36, 37, 38, 39, 40, 41,
  8440. 42, 43, 44, 45, 46, 47, 48, 49, // 7x
  8441. 50, 51, 52, -1, -1, -1, -1, -1,
  8442. -1, -1, -1, -1, -1, -1, -1, -1, // 8x
  8443. -1, -1, -1, -1, -1, -1, -1, -1,
  8444. -1, -1, -1, -1, -1, -1, -1, -1, // 9x
  8445. -1, -1, -1, -1, -1, -1, -1, -1,
  8446. -1, -1, -1, -1, -1, -1, -1, -1, // Ax
  8447. -1, -1, -1, -1, -1, -1, -1, -1,
  8448. -1, -1, -1, -1, -1, -1, -1, -1, // Bx
  8449. -1, -1, -1, -1, -1, -1, -1, -1,
  8450. -1, -1, -1, -1, -1, -1, -1, -1, // Cx
  8451. -1, -1, -1, -1, -1, -1, -1, -1,
  8452. -1, -1, -1, -1, -1, -1, -1, -1, // Dx
  8453. -1, -1, -1, -1, -1, -1, -1, -1,
  8454. -1, -1, -1, -1, -1, -1, -1, -1, // Ex
  8455. -1, -1, -1, -1, -1, -1, -1, -1,
  8456. -1, -1, -1, -1, -1, -1, -1, -1, // Fx
  8457. -1, -1, -1, -1, -1, -1, -1, -1
  8458. };
  8459. // <summary>
  8460. // Converts a 32-bit integer into a Base64
  8461. // character string. Base64 character strings
  8462. // are always 8 characters long. All iinteger
  8463. // values are acceptable.
  8464. // </summary>
  8465. // <param name="number">
  8466. // 32-bit integer to be converted.
  8467. // </param>
  8468. // <returns>
  8469. // 8 character string. The 1st six characters
  8470. // contain the encoded number, the last two
  8471. // characters are padded with "=".
  8472. // </returns>
  8473. public LSL_String llIntegerToBase64(int number)
  8474. {
  8475. // uninitialized string
  8476. char[] imdt = new char[8];
  8477. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  8478. // Manually unroll the loop
  8479. imdt[7] = '=';
  8480. imdt[6] = '=';
  8481. imdt[5] = i2ctable[number << 4 & 0x3F];
  8482. imdt[4] = i2ctable[number >> 2 & 0x3F];
  8483. imdt[3] = i2ctable[number >> 8 & 0x3F];
  8484. imdt[2] = i2ctable[number >> 14 & 0x3F];
  8485. imdt[1] = i2ctable[number >> 20 & 0x3F];
  8486. imdt[0] = i2ctable[number >> 26 & 0x3F];
  8487. return new string(imdt);
  8488. }
  8489. // <summary>
  8490. // Converts an eight character base-64 string
  8491. // into a 32-bit integer.
  8492. // </summary>
  8493. // <param name="str">
  8494. // 8 characters string to be converted. Other
  8495. // length strings return zero.
  8496. // </param>
  8497. // <returns>
  8498. // Returns an integer representing the
  8499. // encoded value providedint he 1st 6
  8500. // characters of the string.
  8501. // </returns>
  8502. // <remarks>
  8503. // This is coded to behave like LSL's
  8504. // implementation (I think), based upon the
  8505. // information available at the Wiki.
  8506. // If more than 8 characters are supplied,
  8507. // zero is returned.
  8508. // If a NULL string is supplied, zero will
  8509. // be returned.
  8510. // If fewer than 6 characters are supplied, then
  8511. // the answer will reflect a partial
  8512. // accumulation.
  8513. // <para>
  8514. // The 6-bit segments are
  8515. // extracted left-to-right in big-endian mode,
  8516. // which means that segment 6 only contains the
  8517. // two low-order bits of the 32 bit integer as
  8518. // its high order 2 bits. A short string therefore
  8519. // means loss of low-order information. E.g.
  8520. //
  8521. // |<---------------------- 32-bit integer ----------------------->|<-Pad->|
  8522. // |<--Byte 0----->|<--Byte 1----->|<--Byte 2----->|<--Byte 3----->|<-Pad->|
  8523. // |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|
  8524. // |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|
  8525. // | str[0] | str[1] | str[2] | str[3] | str[4] | str[6] |
  8526. //
  8527. // </para>
  8528. // </remarks>
  8529. public LSL_Integer llBase64ToInteger(string str)
  8530. {
  8531. int number = 0;
  8532. int digit;
  8533. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  8534. // Require a well-fromed base64 string
  8535. if (str.Length > 8)
  8536. return 0;
  8537. // The loop is unrolled in the interests
  8538. // of performance and simple necessity.
  8539. //
  8540. // MUST find 6 digits to be well formed
  8541. // -1 == invalid
  8542. // 0 == padding
  8543. if ((digit = c2itable[str[0]]) <= 0)
  8544. {
  8545. return digit < 0 ? 0 : number;
  8546. }
  8547. number += --digit << 26;
  8548. if ((digit = c2itable[str[1]]) <= 0)
  8549. {
  8550. return digit < 0 ? 0 : number;
  8551. }
  8552. number += --digit << 20;
  8553. if ((digit = c2itable[str[2]]) <= 0)
  8554. {
  8555. return digit < 0 ? 0 : number;
  8556. }
  8557. number += --digit << 14;
  8558. if ((digit = c2itable[str[3]]) <= 0)
  8559. {
  8560. return digit < 0 ? 0 : number;
  8561. }
  8562. number += --digit << 8;
  8563. if ((digit = c2itable[str[4]]) <= 0)
  8564. {
  8565. return digit < 0 ? 0 : number;
  8566. }
  8567. number += --digit << 2;
  8568. if ((digit = c2itable[str[5]]) <= 0)
  8569. {
  8570. return digit < 0 ? 0 : number;
  8571. }
  8572. number += --digit >> 4;
  8573. // ignore trailing padding
  8574. return number;
  8575. }
  8576. public LSL_Float llGetGMTclock()
  8577. {
  8578. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  8579. return new LSL_Float();
  8580. return DateTime.UtcNow.TimeOfDay.TotalSeconds;
  8581. }
  8582. public LSL_String llGetHTTPHeader(LSL_Key request_id, string header)
  8583. {
  8584. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  8585. if (m_UrlModule != null)
  8586. return m_UrlModule.GetHttpHeader(request_id, header);
  8587. return String.Empty;
  8588. }
  8589. public LSL_String llGetSimulatorHostname()
  8590. {
  8591. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  8592. IUrlModule UrlModule = World.RequestModuleInterface<IUrlModule>();
  8593. return UrlModule.ExternalHostNameForLSL;
  8594. }
  8595. // <summary>
  8596. // Scan the string supplied in 'src' and
  8597. // tokenize it based upon two sets of
  8598. // tokenizers provided in two lists,
  8599. // separators and spacers.
  8600. // </summary>
  8601. //
  8602. // <remarks>
  8603. // Separators demarcate tokens and are
  8604. // elided as they are encountered. Spacers
  8605. // also demarcate tokens, but are themselves
  8606. // retained as tokens.
  8607. //
  8608. // Both separators and spacers may be arbitrarily
  8609. // long strings. i.e. ":::".
  8610. //
  8611. // The function returns an ordered list
  8612. // representing the tokens found in the supplied
  8613. // sources string. If two successive tokenizers
  8614. // are encountered, then a NULL entry is added
  8615. // to the list.
  8616. //
  8617. // It is a precondition that the source and
  8618. // toekizer lisst are non-null. If they are null,
  8619. // then a null pointer exception will be thrown
  8620. // while their lengths are being determined.
  8621. //
  8622. // A small amount of working memoryis required
  8623. // of approximately 8*#tokenizers.
  8624. //
  8625. // There are many ways in which this function
  8626. // can be implemented, this implementation is
  8627. // fairly naive and assumes that when the
  8628. // function is invooked with a short source
  8629. // string and/or short lists of tokenizers, then
  8630. // performance will not be an issue.
  8631. //
  8632. // In order to minimize the perofrmance
  8633. // effects of long strings, or large numbers
  8634. // of tokeizers, the function skips as far as
  8635. // possible whenever a toekenizer is found,
  8636. // and eliminates redundant tokenizers as soon
  8637. // as is possible.
  8638. //
  8639. // The implementation tries to avoid any copying
  8640. // of arrays or other objects.
  8641. // </remarks>
  8642. private LSL_List ParseString(string src, LSL_List separators, LSL_List spacers, bool keepNulls)
  8643. {
  8644. int beginning = 0;
  8645. int srclen = src.Length;
  8646. int seplen = separators.Length;
  8647. object[] separray = separators.Data;
  8648. int spclen = spacers.Length;
  8649. object[] spcarray = spacers.Data;
  8650. int mlen = seplen + spclen;
  8651. int[] offset = new int[mlen + 1];
  8652. bool[] active = new bool[mlen];
  8653. // Initial capacity reduces resize cost
  8654. LSL_List tokens = new LSL_List();
  8655. // All entries are initially valid
  8656. for (int i = 0; i < mlen; i++)
  8657. active[i] = true;
  8658. offset[mlen] = srclen;
  8659. while (beginning < srclen)
  8660. {
  8661. int best = mlen;
  8662. // Scan for separators
  8663. int j;
  8664. for (j = 0; j < seplen; j++)
  8665. {
  8666. if (separray[j].ToString() == String.Empty)
  8667. active[j] = false;
  8668. if (active[j])
  8669. {
  8670. // scan all of the markers
  8671. if ((offset[j] = src.IndexOf(separray[j].ToString(), beginning)) == -1)
  8672. {
  8673. // not present at all
  8674. active[j] = false;
  8675. }
  8676. else
  8677. {
  8678. // present and correct
  8679. if (offset[j] < offset[best])
  8680. {
  8681. // closest so far
  8682. best = j;
  8683. if (offset[best] == beginning)
  8684. break;
  8685. }
  8686. }
  8687. }
  8688. }
  8689. // Scan for spacers
  8690. if (offset[best] != beginning)
  8691. {
  8692. for (j = seplen; (j < mlen) && (offset[best] > beginning); j++)
  8693. {
  8694. if (spcarray[j - seplen].ToString() == String.Empty)
  8695. active[j] = false;
  8696. if (active[j])
  8697. {
  8698. // scan all of the markers
  8699. if ((offset[j] = src.IndexOf(spcarray[j - seplen].ToString(), beginning)) == -1)
  8700. {
  8701. // not present at all
  8702. active[j] = false;
  8703. }
  8704. else
  8705. {
  8706. // present and correct
  8707. if (offset[j] < offset[best])
  8708. {
  8709. // closest so far
  8710. best = j;
  8711. }
  8712. }
  8713. }
  8714. }
  8715. }
  8716. // This is the normal exit from the scanning loop
  8717. if (best == mlen)
  8718. {
  8719. // no markers were found on this pass
  8720. // so we're pretty much done
  8721. if ((keepNulls) || ((srclen - beginning) > 0))
  8722. tokens.Add(new LSL_String(src.Substring(beginning, srclen - beginning)));
  8723. break;
  8724. }
  8725. // Otherwise we just add the newly delimited token
  8726. // and recalculate where the search should continue.
  8727. if ((keepNulls) || ((offset[best] - beginning) > 0))
  8728. tokens.Add(new LSL_String(src.Substring(beginning, offset[best] - beginning)));
  8729. if (best < seplen)
  8730. {
  8731. beginning = offset[best] + (separray[best].ToString()).Length;
  8732. }
  8733. else
  8734. {
  8735. beginning = offset[best] + (spcarray[best - seplen].ToString()).Length;
  8736. string str = spcarray[best - seplen].ToString();
  8737. if ((keepNulls) || ((str.Length > 0)))
  8738. tokens.Add(new LSL_String(str));
  8739. }
  8740. }
  8741. // This an awkward an not very intuitive boundary case. If the
  8742. // last substring is a tokenizer, then there is an implied trailing
  8743. // null list entry. Hopefully the single comparison will not be too
  8744. // arduous. Alternatively the 'break' could be replced with a return
  8745. // but that's shabby programming.
  8746. if ((beginning == srclen) && (keepNulls))
  8747. {
  8748. if (srclen != 0)
  8749. tokens.Add(new LSL_String(""));
  8750. }
  8751. return tokens;
  8752. }
  8753. public LSL_List llParseString2List(string src, LSL_List separators, LSL_List spacers)
  8754. {
  8755. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "llParseString2List", m_host, "LSL", m_itemID))
  8756. return new LSL_List();
  8757. return ParseString(src, separators, spacers, false);
  8758. }
  8759. public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
  8760. {
  8761. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "llParseStringKeepNulls", m_host, "LSL", m_itemID))
  8762. return new LSL_List();
  8763. return ParseString(src, separators, spacers, true);
  8764. }
  8765. public LSL_Integer llGetObjectPermMask(int mask)
  8766. {
  8767. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  8768. return new LSL_Integer();
  8769. int permmask = 0;
  8770. if (mask == ScriptBaseClass.MASK_BASE) //0
  8771. {
  8772. permmask = (int) m_host.BaseMask;
  8773. }
  8774. else if (mask == ScriptBaseClass.MASK_OWNER) //1
  8775. {
  8776. permmask = (int) m_host.OwnerMask;
  8777. }
  8778. else if (mask == ScriptBaseClass.MASK_GROUP) //2
  8779. {
  8780. permmask = (int) m_host.GroupMask;
  8781. }
  8782. else if (mask == ScriptBaseClass.MASK_EVERYONE) //3
  8783. {
  8784. permmask = (int) m_host.EveryoneMask;
  8785. }
  8786. else if (mask == ScriptBaseClass.MASK_NEXT) //4
  8787. {
  8788. permmask = (int) m_host.NextOwnerMask;
  8789. }
  8790. return permmask;
  8791. }
  8792. public void llSetObjectPermMask(int mask, int value)
  8793. {
  8794. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  8795. if (m_ScriptEngine.Config.GetBoolean("AllowGodFunctions", false))
  8796. {
  8797. if (World.Permissions.CanRunConsoleCommand(m_host.OwnerID))
  8798. {
  8799. if (mask == ScriptBaseClass.MASK_BASE) //0
  8800. {
  8801. m_host.BaseMask = (uint) value;
  8802. }
  8803. else if (mask == ScriptBaseClass.MASK_OWNER) //1
  8804. {
  8805. m_host.OwnerMask = (uint) value;
  8806. }
  8807. else if (mask == ScriptBaseClass.MASK_GROUP) //2
  8808. {
  8809. m_host.GroupMask = (uint) value;
  8810. }
  8811. else if (mask == ScriptBaseClass.MASK_EVERYONE) //3
  8812. {
  8813. m_host.EveryoneMask = (uint) value;
  8814. }
  8815. else if (mask == ScriptBaseClass.MASK_NEXT) //4
  8816. {
  8817. m_host.NextOwnerMask = (uint) value;
  8818. }
  8819. }
  8820. }
  8821. }
  8822. public LSL_Integer llGetInventoryPermMask(string item, int mask)
  8823. {
  8824. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  8825. lock (m_host.TaskInventory)
  8826. {
  8827. foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
  8828. {
  8829. if (inv.Value.Name == item)
  8830. {
  8831. switch (mask)
  8832. {
  8833. case 0:
  8834. return (int) inv.Value.BasePermissions;
  8835. case 1:
  8836. return (int) inv.Value.CurrentPermissions;
  8837. case 2:
  8838. return (int) inv.Value.GroupPermissions;
  8839. case 3:
  8840. return (int) inv.Value.EveryonePermissions;
  8841. case 4:
  8842. return (int) inv.Value.NextPermissions;
  8843. }
  8844. }
  8845. }
  8846. }
  8847. return -1;
  8848. }
  8849. public void llSetInventoryPermMask(string item, int mask, int value)
  8850. {
  8851. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  8852. if (m_ScriptEngine.Config.GetBoolean("AllowGodFunctions", false))
  8853. {
  8854. if (World.Permissions.CanRunConsoleCommand(m_host.OwnerID))
  8855. {
  8856. lock (m_host.TaskInventory)
  8857. {
  8858. foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
  8859. {
  8860. if (inv.Value.Name == item)
  8861. {
  8862. switch (mask)
  8863. {
  8864. case 0:
  8865. inv.Value.BasePermissions = (uint) value;
  8866. break;
  8867. case 1:
  8868. inv.Value.CurrentPermissions = (uint) value;
  8869. break;
  8870. case 2:
  8871. inv.Value.GroupPermissions = (uint) value;
  8872. break;
  8873. case 3:
  8874. inv.Value.EveryonePermissions = (uint) value;
  8875. break;
  8876. case 4:
  8877. inv.Value.NextPermissions = (uint) value;
  8878. break;
  8879. }
  8880. }
  8881. }
  8882. }
  8883. }
  8884. }
  8885. }
  8886. public LSL_String llGetInventoryCreator(string item)
  8887. {
  8888. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  8889. lock (m_host.TaskInventory)
  8890. {
  8891. foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
  8892. {
  8893. if (inv.Value.Name == item)
  8894. {
  8895. return inv.Value.CreatorID.ToString();
  8896. }
  8897. }
  8898. }
  8899. llSay(0, "No item name '" + item + "'");
  8900. return String.Empty;
  8901. }
  8902. public void llOwnerSay(string msg)
  8903. {
  8904. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  8905. IChatModule chatModule = World.RequestModuleInterface<IChatModule>();
  8906. if (chatModule != null)
  8907. chatModule.SimChatBroadcast(msg, ChatTypeEnum.Owner, 0,
  8908. m_host.AbsolutePosition, m_host.Name, m_host.UUID, false, UUID.Zero, World);
  8909. }
  8910. public LSL_String llRequestSecureURL()
  8911. {
  8912. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  8913. if (m_UrlModule != null)
  8914. return m_UrlModule.RequestSecureURL(m_ScriptEngine.ScriptModule, m_host, m_itemID).ToString();
  8915. return UUID.Zero.ToString();
  8916. }
  8917. public LSL_String llGetEnv(LSL_String name)
  8918. {
  8919. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  8920. if (name == "sim_channel")
  8921. return "Aurora-Sim Server";
  8922. if (name == "sim_version")
  8923. return World.RequestModuleInterface<ISimulationBase>().Version;
  8924. return "";
  8925. }
  8926. public void llTeleportAgent(LSL_Key avatar, LSL_String landmark, LSL_Vector position, LSL_Vector look_at)
  8927. {
  8928. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  8929. UUID invItemID = InventorySelf();
  8930. if (invItemID == UUID.Zero)
  8931. return;
  8932. lock (m_host.TaskInventory)
  8933. {
  8934. if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero)
  8935. {
  8936. ShoutError("No permissions to teleport the agent");
  8937. return;
  8938. }
  8939. if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TELEPORT) == 0)
  8940. {
  8941. ShoutError("No permissions to teleport the agent");
  8942. return;
  8943. }
  8944. }
  8945. TaskInventoryItem item = null;
  8946. lock (m_host.TaskInventory)
  8947. {
  8948. foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
  8949. {
  8950. if (inv.Value.Name == landmark)
  8951. item = inv.Value;
  8952. }
  8953. }
  8954. if (item == null && landmark != "")
  8955. return;
  8956. IScenePresence presence = World.GetScenePresence(m_host.OwnerID);
  8957. if (presence != null)
  8958. {
  8959. IEntityTransferModule module = World.RequestModuleInterface<IEntityTransferModule>();
  8960. if (module != null)
  8961. {
  8962. if (landmark == "")
  8963. module.Teleport(presence, World.RegionInfo.RegionHandle,
  8964. position.ToVector3(), look_at.ToVector3(), (uint) TeleportFlags.ViaLocation);
  8965. else
  8966. {
  8967. AssetLandmark lm = new AssetLandmark(
  8968. World.AssetService.Get(item.AssetID.ToString()));
  8969. module.Teleport(presence, lm.RegionHandle, lm.Position,
  8970. look_at.ToVector3(), (uint) TeleportFlags.ViaLocation);
  8971. }
  8972. }
  8973. }
  8974. }
  8975. public void llTeleportAgentGlobalCoords(LSL_Key agent, LSL_Vector global_coordinates,
  8976. LSL_Vector region_coordinates, LSL_Vector look_at)
  8977. {
  8978. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  8979. UUID invItemID = InventorySelf();
  8980. if (invItemID == UUID.Zero)
  8981. return;
  8982. lock (m_host.TaskInventory)
  8983. {
  8984. if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero)
  8985. {
  8986. ShoutError("No permissions to teleport the agent");
  8987. return;
  8988. }
  8989. if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TELEPORT) == 0)
  8990. {
  8991. ShoutError("No permissions to teleport the agent");
  8992. return;
  8993. }
  8994. }
  8995. IScenePresence presence = World.GetScenePresence(m_host.OwnerID);
  8996. if (presence != null)
  8997. {
  8998. IEntityTransferModule module = World.RequestModuleInterface<IEntityTransferModule>();
  8999. if (module != null)
  9000. {
  9001. module.Teleport(presence,
  9002. Utils.UIntsToLong((uint) global_coordinates.x, (uint) global_coordinates.y),
  9003. region_coordinates.ToVector3(), look_at.ToVector3(),
  9004. (uint) TeleportFlags.ViaLocation);
  9005. }
  9006. }
  9007. }
  9008. public LSL_Key llRequestSimulatorData(string simulator, int data)
  9009. {
  9010. UUID tid = UUID.Zero;
  9011. try
  9012. {
  9013. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  9014. string reply = String.Empty;
  9015. GridRegion info = World.RegionInfo.RegionName == simulator
  9016. ? new GridRegion(World.RegionInfo)
  9017. : World.GridService.GetRegionByName(World.RegionInfo.AllScopeIDs, simulator);
  9018. switch (data)
  9019. {
  9020. case 5: // DATA_SIM_POS
  9021. if (info == null)
  9022. break;
  9023. reply = new LSL_Vector(
  9024. info.RegionLocX,
  9025. info.RegionLocY,
  9026. 0).ToString();
  9027. break;
  9028. case 6: // DATA_SIM_STATUS
  9029. if (info != null)
  9030. {
  9031. reply = (info.Flags & (int) RegionFlags.RegionOnline) != 0 ? "up" : "down";
  9032. }
  9033. //if() starting
  9034. //if() stopping
  9035. //if() crashed
  9036. else
  9037. reply = "unknown";
  9038. break;
  9039. case 7: // DATA_SIM_RATING
  9040. if (info == null)
  9041. break;
  9042. uint access = Util.ConvertAccessLevelToMaturity(info.Access);
  9043. if (access == 0)
  9044. reply = "PG";
  9045. else if (access == 1)
  9046. reply = "MATURE";
  9047. else if (access == 2)
  9048. reply = "ADULT";
  9049. else
  9050. reply = "UNKNOWN";
  9051. break;
  9052. case 128:
  9053. try
  9054. {
  9055. if (
  9056. !ScriptProtection.CheckThreatLevel(ThreatLevel.High, "llRequestSimulatorData", m_host,
  9057. "LSL", m_itemID)) return "";
  9058. reply = "Aurora";
  9059. }
  9060. catch
  9061. {
  9062. reply = "";
  9063. }
  9064. break;
  9065. }
  9066. if (reply != "")
  9067. {
  9068. UUID rq = UUID.Random();
  9069. DataserverPlugin dataserverPlugin = (DataserverPlugin) m_ScriptEngine.GetScriptPlugin("Dataserver");
  9070. tid = dataserverPlugin.RegisterRequest(m_host.UUID, m_itemID, rq.ToString());
  9071. dataserverPlugin.AddReply(rq.ToString(), reply, 1000);
  9072. }
  9073. }
  9074. catch
  9075. {
  9076. }
  9077. ScriptSleep(1000);
  9078. return (LSL_Key) tid.ToString();
  9079. }
  9080. public LSL_String llRequestURL()
  9081. {
  9082. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  9083. if (m_UrlModule != null)
  9084. return m_UrlModule.RequestURL(m_ScriptEngine.ScriptModule, m_host, m_itemID).ToString();
  9085. return UUID.Zero.ToString();
  9086. }
  9087. public void llForceMouselook(int mouselook)
  9088. {
  9089. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  9090. m_host.ForceMouselook = (mouselook != 0);
  9091. }
  9092. /// <summary>
  9093. /// illListReplaceList removes the sub-list defined by the inclusive indices
  9094. /// start and end and inserts the src list in its place. The inclusive
  9095. /// nature of the indices means that at least one element must be deleted
  9096. /// if the indices are within the bounds of the existing list. I.e. 2,2
  9097. /// will remove the element at index 2 and replace it with the source
  9098. /// list. Both indices may be negative, with the usual interpretation. An
  9099. /// interesting case is where end is lower than start. As these indices
  9100. /// bound the list to be removed, then 0->end, and start->lim are removed
  9101. /// and the source list is added as a suffix.
  9102. /// </summary>
  9103. public LSL_List llListReplaceList(LSL_List dest, LSL_List src, int start, int end)
  9104. {
  9105. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  9106. return new LSL_List();
  9107. // Note that although we have normalized, both
  9108. // indices could still be negative.
  9109. if (start < 0)
  9110. {
  9111. start = start + dest.Length;
  9112. }
  9113. if (end < 0)
  9114. {
  9115. end = end + dest.Length;
  9116. }
  9117. // The comventional case, remove a sequence starting with
  9118. // start and ending with end. And then insert the source
  9119. // list.
  9120. if (start <= end)
  9121. {
  9122. // If greater than zero, then there is going to be a
  9123. // surviving prefix. Otherwise the inclusive nature
  9124. // of the indices mean that we're going to add the
  9125. // source list as a prefix.
  9126. if (start > 0)
  9127. {
  9128. LSL_List pref = dest.GetSublist(0, start - 1);
  9129. // Only add a suffix if there is something
  9130. // beyond the end index (it's inclusive too).
  9131. if (end + 1 < dest.Length)
  9132. {
  9133. return pref + src + dest.GetSublist(end + 1, -1);
  9134. }
  9135. return pref + src;
  9136. }
  9137. // If start is less than or equal to zero, then
  9138. // the new list is simply a prefix. We still need to
  9139. // figure out any necessary surgery to the destination
  9140. // based upon end. Note that if end exceeds the upper
  9141. // bound in this case, the entire destination list
  9142. // is removed.
  9143. if (end + 1 < dest.Length)
  9144. {
  9145. return src + dest.GetSublist(end + 1, -1);
  9146. }
  9147. return src;
  9148. }
  9149. // Finally, if start > end, we strip away a prefix and
  9150. // a suffix, to leave the list that sits <between> ens
  9151. // and start, and then tag on the src list. AT least
  9152. // that's my interpretation. We can get sublist to do
  9153. // this for us. Note that one, or both of the indices
  9154. // might have been negative.
  9155. return dest.GetSublist(end + 1, start - 1) + src;
  9156. }
  9157. public DateTime llLoadURL(string avatar_id, string message, string url)
  9158. {
  9159. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  9160. return DateTime.Now;
  9161. IDialogModule dm = World.RequestModuleInterface<IDialogModule>();
  9162. if (null != dm)
  9163. dm.SendUrlToUser(
  9164. new UUID(avatar_id), m_host.Name, m_host.UUID, m_host.OwnerID, false, message, url);
  9165. return PScriptSleep(10000);
  9166. }
  9167. public DateTime llParcelMediaCommandList(LSL_List commandList)
  9168. {
  9169. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  9170. return DateTime.Now;
  9171. // according to the docs, this command only works if script owner and land owner are the same
  9172. // lets add estate owners and gods, too, and use the generic permission check.
  9173. IParcelManagementModule parcelManagement = World.RequestModuleInterface<IParcelManagementModule>();
  9174. if (parcelManagement != null)
  9175. {
  9176. ILandObject landObject = parcelManagement.GetLandObject(m_host.AbsolutePosition.X,
  9177. m_host.AbsolutePosition.Y);
  9178. if (landObject == null)
  9179. return DateTime.Now;
  9180. if (!World.Permissions.CanEditParcel(m_host.OwnerID, landObject))
  9181. return DateTime.Now;
  9182. bool update = false; // send a ParcelMediaUpdate (and possibly change the land's media URL)?
  9183. byte loop = 0;
  9184. LandData landData = landObject.LandData;
  9185. string url = landData.MediaURL;
  9186. string texture = landData.MediaID.ToString();
  9187. bool autoAlign = landData.MediaAutoScale != 0;
  9188. string mediaType = landData.MediaType;
  9189. string description = landData.MediaDescription;
  9190. int width = landData.MediaWidth;
  9191. int height = landData.MediaHeight;
  9192. float mediaLoopSet = landData.MediaLoopSet;
  9193. ParcelMediaCommandEnum? commandToSend = null;
  9194. float time = 0.0f; // default is from start
  9195. IScenePresence presence = null;
  9196. for (int i = 0; i < commandList.Data.Length; i++)
  9197. {
  9198. int tmp = ((LSL_Integer) commandList.Data[i]).value;
  9199. ParcelMediaCommandEnum command = (ParcelMediaCommandEnum) tmp;
  9200. switch (command)
  9201. {
  9202. case ParcelMediaCommandEnum.Agent:
  9203. // we send only to one agent
  9204. if ((i + 1) < commandList.Length)
  9205. {
  9206. if (commandList.Data[i + 1] is LSL_String)
  9207. {
  9208. UUID agentID;
  9209. if (UUID.TryParse((LSL_String) commandList.Data[i + 1], out agentID))
  9210. {
  9211. presence = World.GetScenePresence(agentID);
  9212. }
  9213. }
  9214. else ShoutError("The argument of PARCEL_MEDIA_COMMAND_AGENT must be a key");
  9215. ++i;
  9216. }
  9217. break;
  9218. case ParcelMediaCommandEnum.Loop:
  9219. loop = 1;
  9220. commandToSend = command;
  9221. update = true; //need to send the media update packet to set looping
  9222. break;
  9223. case ParcelMediaCommandEnum.LoopSet:
  9224. if ((i + 1) < commandList.Length)
  9225. {
  9226. if (commandList.Data[i + 1] is LSL_Float)
  9227. {
  9228. mediaLoopSet = (float) ((LSL_Float) commandList.Data[i + 1]).value;
  9229. }
  9230. else ShoutError("The argument of PARCEL_MEDIA_COMMAND_LOOP_SET must be a float");
  9231. ++i;
  9232. }
  9233. commandToSend = command;
  9234. break;
  9235. case ParcelMediaCommandEnum.Play:
  9236. loop = 0;
  9237. commandToSend = command;
  9238. update = true; //need to send the media update packet to make sure it doesn't loop
  9239. break;
  9240. case ParcelMediaCommandEnum.Pause:
  9241. case ParcelMediaCommandEnum.Stop:
  9242. case ParcelMediaCommandEnum.Unload:
  9243. commandToSend = command;
  9244. break;
  9245. case ParcelMediaCommandEnum.Url:
  9246. if ((i + 1) < commandList.Length)
  9247. {
  9248. if (commandList.Data[i + 1] is LSL_String)
  9249. {
  9250. url = (LSL_String) commandList.Data[i + 1];
  9251. update = true;
  9252. }
  9253. else ShoutError("The argument of PARCEL_MEDIA_COMMAND_URL must be a string.");
  9254. ++i;
  9255. }
  9256. break;
  9257. case ParcelMediaCommandEnum.Texture:
  9258. if ((i + 1) < commandList.Length)
  9259. {
  9260. if (commandList.Data[i + 1] is LSL_String)
  9261. {
  9262. texture = (LSL_String) commandList.Data[i + 1];
  9263. update = true;
  9264. }
  9265. else
  9266. ShoutError("The argument of PARCEL_MEDIA_COMMAND_TEXTURE must be a string or key.");
  9267. ++i;
  9268. }
  9269. break;
  9270. case ParcelMediaCommandEnum.Time:
  9271. if ((i + 1) < commandList.Length)
  9272. {
  9273. if (commandList.Data[i + 1] is LSL_Float)
  9274. {
  9275. time = (float) (LSL_Float) commandList.Data[i + 1];
  9276. }
  9277. else ShoutError("The argument of PARCEL_MEDIA_COMMAND_TIME must be a float.");
  9278. ++i;
  9279. }
  9280. commandToSend = command;
  9281. break;
  9282. case ParcelMediaCommandEnum.AutoAlign:
  9283. if ((i + 1) < commandList.Length)
  9284. {
  9285. if (commandList.Data[i + 1] is LSL_Integer)
  9286. {
  9287. autoAlign = (LSL_Integer) commandList.Data[i + 1];
  9288. update = true;
  9289. }
  9290. else ShoutError("The argument of PARCEL_MEDIA_COMMAND_AUTO_ALIGN must be an integer.");
  9291. ++i;
  9292. }
  9293. break;
  9294. case ParcelMediaCommandEnum.Type:
  9295. if ((i + 1) < commandList.Length)
  9296. {
  9297. if (commandList.Data[i + 1] is LSL_String)
  9298. {
  9299. mediaType = (LSL_String) commandList.Data[i + 1];
  9300. update = true;
  9301. }
  9302. else ShoutError("The argument of PARCEL_MEDIA_COMMAND_TYPE must be a string.");
  9303. ++i;
  9304. }
  9305. break;
  9306. case ParcelMediaCommandEnum.Desc:
  9307. if ((i + 1) < commandList.Length)
  9308. {
  9309. if (commandList.Data[i + 1] is LSL_String)
  9310. {
  9311. description = (LSL_String) commandList.Data[i + 1];
  9312. update = true;
  9313. }
  9314. else ShoutError("The argument of PARCEL_MEDIA_COMMAND_DESC must be a string.");
  9315. ++i;
  9316. }
  9317. break;
  9318. case ParcelMediaCommandEnum.Size:
  9319. if ((i + 2) < commandList.Length)
  9320. {
  9321. if (commandList.Data[i + 1] is LSL_Integer)
  9322. {
  9323. if (commandList.Data[i + 2] is LSL_Integer)
  9324. {
  9325. width = (LSL_Integer) commandList.Data[i + 1];
  9326. height = (LSL_Integer) commandList.Data[i + 2];
  9327. update = true;
  9328. }
  9329. else
  9330. ShoutError(
  9331. "The second argument of PARCEL_MEDIA_COMMAND_SIZE must be an integer.");
  9332. }
  9333. else ShoutError("The first argument of PARCEL_MEDIA_COMMAND_SIZE must be an integer.");
  9334. i += 2;
  9335. }
  9336. break;
  9337. default:
  9338. NotImplemented("llParcelMediaCommandList parameter not supported yet: " +
  9339. Enum.Parse(typeof (ParcelMediaCommandEnum), commandList.Data[i].ToString()));
  9340. break;
  9341. } //end switch
  9342. } //end for
  9343. // if we didn't get a presence, we send to all and change the url
  9344. // if we did get a presence, we only send to the agent specified, and *don't change the land settings*!
  9345. // did something important change or do we only start/stop/pause?
  9346. if (update)
  9347. {
  9348. if (presence == null)
  9349. {
  9350. // we send to all
  9351. landData.MediaID = new UUID(texture);
  9352. landData.MediaAutoScale = autoAlign ? (byte) 1 : (byte) 0;
  9353. landData.MediaWidth = width;
  9354. landData.MediaHeight = height;
  9355. landData.MediaType = mediaType;
  9356. landData.MediaDescription = description;
  9357. landData.MediaLoop = loop == 1;
  9358. landData.MediaLoopSet = mediaLoopSet;
  9359. // do that one last, it will cause a ParcelPropertiesUpdate
  9360. landObject.SetMediaUrl(url);
  9361. // now send to all (non-child) agents
  9362. World.ForEachScenePresence(delegate(IScenePresence sp)
  9363. {
  9364. if (!sp.IsChildAgent &&
  9365. (sp.CurrentParcelUUID == landData.GlobalID))
  9366. {
  9367. sp.ControllingClient.SendParcelMediaUpdate(
  9368. landData.MediaURL,
  9369. landData.MediaID,
  9370. landData.MediaAutoScale,
  9371. mediaType,
  9372. description,
  9373. width, height,
  9374. loop);
  9375. }
  9376. });
  9377. }
  9378. else if (!presence.IsChildAgent)
  9379. {
  9380. // we only send to one (root) agent
  9381. presence.ControllingClient.SendParcelMediaUpdate(url,
  9382. new UUID(texture),
  9383. autoAlign ? (byte) 1 : (byte) 0,
  9384. mediaType,
  9385. description,
  9386. width, height,
  9387. loop);
  9388. }
  9389. }
  9390. if (commandToSend != null)
  9391. {
  9392. float ParamToSend = time;
  9393. if ((ParcelMediaCommandEnum) commandToSend == ParcelMediaCommandEnum.LoopSet)
  9394. ParamToSend = mediaLoopSet;
  9395. // the commandList contained a start/stop/... command, too
  9396. if (presence == null)
  9397. {
  9398. // send to all (non-child) agents
  9399. World.ForEachScenePresence(delegate(IScenePresence sp)
  9400. {
  9401. if (!sp.IsChildAgent)
  9402. {
  9403. sp.ControllingClient.SendParcelMediaCommand(
  9404. landData.Flags,
  9405. (ParcelMediaCommandEnum) commandToSend,
  9406. ParamToSend);
  9407. }
  9408. });
  9409. }
  9410. else if (!presence.IsChildAgent)
  9411. {
  9412. presence.ControllingClient.SendParcelMediaCommand(landData.Flags,
  9413. (ParcelMediaCommandEnum) commandToSend,
  9414. ParamToSend);
  9415. }
  9416. }
  9417. }
  9418. return PScriptSleep(2000);
  9419. }
  9420. public LSL_List llParcelMediaQuery(LSL_List aList)
  9421. {
  9422. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  9423. return new LSL_List();
  9424. LSL_List list = new LSL_List();
  9425. foreach (object t in aList.Data)
  9426. {
  9427. if (t != null)
  9428. {
  9429. IParcelManagementModule parcelManagement = World.RequestModuleInterface<IParcelManagementModule>();
  9430. if (parcelManagement != null)
  9431. {
  9432. LSL_Integer tmp = (LSL_Integer) t;
  9433. switch ((ParcelMediaCommandEnum) tmp.value)
  9434. {
  9435. case ParcelMediaCommandEnum.Url:
  9436. list.Add(
  9437. new LSL_String(
  9438. parcelManagement.GetLandObject(m_host.AbsolutePosition.X,
  9439. m_host.AbsolutePosition.Y).LandData.MediaURL));
  9440. break;
  9441. case ParcelMediaCommandEnum.Desc:
  9442. list.Add(
  9443. new LSL_String(
  9444. parcelManagement.GetLandObject(m_host.AbsolutePosition.X,
  9445. m_host.AbsolutePosition.Y)
  9446. .LandData.MediaDescription));
  9447. break;
  9448. case ParcelMediaCommandEnum.Texture:
  9449. list.Add(
  9450. new LSL_String(
  9451. parcelManagement.GetLandObject(m_host.AbsolutePosition.X,
  9452. m_host.AbsolutePosition.Y)
  9453. .LandData.MediaID.ToString()));
  9454. break;
  9455. case ParcelMediaCommandEnum.Type:
  9456. list.Add(
  9457. new LSL_String(
  9458. parcelManagement.GetLandObject(m_host.AbsolutePosition.X,
  9459. m_host.AbsolutePosition.Y).LandData.MediaType));
  9460. break;
  9461. case ParcelMediaCommandEnum.Loop:
  9462. list.Add(
  9463. new LSL_Integer(
  9464. parcelManagement.GetLandObject(m_host.AbsolutePosition.X,
  9465. m_host.AbsolutePosition.Y).LandData.MediaLoop
  9466. ? 1
  9467. : 0));
  9468. break;
  9469. case ParcelMediaCommandEnum.LoopSet:
  9470. list.Add(
  9471. new LSL_Integer(
  9472. parcelManagement.GetLandObject(m_host.AbsolutePosition.X,
  9473. m_host.AbsolutePosition.Y).LandData.MediaLoopSet));
  9474. break;
  9475. case ParcelMediaCommandEnum.Size:
  9476. list.Add(
  9477. new LSL_String(
  9478. parcelManagement.GetLandObject(m_host.AbsolutePosition.X,
  9479. m_host.AbsolutePosition.Y).LandData.MediaHeight));
  9480. list.Add(
  9481. new LSL_String(
  9482. parcelManagement.GetLandObject(m_host.AbsolutePosition.X,
  9483. m_host.AbsolutePosition.Y).LandData.MediaWidth));
  9484. break;
  9485. default:
  9486. const ParcelMediaCommandEnum mediaCommandEnum = ParcelMediaCommandEnum.Url;
  9487. NotImplemented("llParcelMediaQuery parameter do not supported yet: " +
  9488. Enum.Parse(mediaCommandEnum.GetType(), t.ToString()));
  9489. break;
  9490. }
  9491. }
  9492. }
  9493. }
  9494. ScriptSleep(2000);
  9495. return list;
  9496. }
  9497. public LSL_List llGetPrimMediaParams(LSL_Integer face, LSL_List rules)
  9498. {
  9499. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  9500. return new LSL_List();
  9501. ScriptSleep(1000);
  9502. // LSL Spec http://wiki.secondlife.com/wiki/LlGetPrimMediaParams says to fail silently if face is invalid
  9503. // TODO: Need to correctly handle case where a face has no media (which gives back an empty list).
  9504. // Assuming silently fail means give back an empty list. Ideally, need to check this.
  9505. if (face < 0 || face > m_host.GetNumberOfSides() - 1)
  9506. return new LSL_List();
  9507. return GetPrimMediaParams(m_host, face, rules);
  9508. }
  9509. public LSL_List llGetLinkMedia(LSL_Integer link, LSL_Integer face, LSL_List rules)
  9510. {
  9511. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  9512. return new LSL_List();
  9513. List<ISceneChildEntity> entities = GetLinkParts(link);
  9514. if (entities.Count == 0 || face < 0 || face > entities[0].GetNumberOfSides() - 1)
  9515. return new LSL_List();
  9516. LSL_List res = new LSL_List();
  9517. #if (!ISWIN)
  9518. LSL_List result = res;
  9519. foreach (ISceneChildEntity part in entities)
  9520. {
  9521. LSL_List list = GetPrimMediaParams(part, face, rules);
  9522. result = result + list;
  9523. }
  9524. return result;
  9525. #else
  9526. return entities.Select(part => GetPrimMediaParams(part, face, rules)).Aggregate(res,
  9527. (current, partRes) =>
  9528. current + partRes);
  9529. #endif
  9530. }
  9531. private LSL_List GetPrimMediaParams(ISceneChildEntity obj, int face, LSL_List rules)
  9532. {
  9533. IMoapModule module = World.RequestModuleInterface<IMoapModule>();
  9534. if (null == module)
  9535. throw new Exception("Media on a prim functions not available");
  9536. MediaEntry me = module.GetMediaEntry(obj, face);
  9537. // As per http://wiki.secondlife.com/wiki/LlGetPrimMediaParams
  9538. if (null == me)
  9539. return new LSL_List();
  9540. LSL_List res = new LSL_List();
  9541. for (int i = 0; i < rules.Length; i++)
  9542. {
  9543. int code = (int) rules.GetLSLIntegerItem(i);
  9544. if (code == ScriptBaseClass.PRIM_MEDIA_ALT_IMAGE_ENABLE)
  9545. {
  9546. // Not implemented
  9547. res.Add(new LSL_Integer(0));
  9548. }
  9549. else if (code == ScriptBaseClass.PRIM_MEDIA_CONTROLS)
  9550. {
  9551. res.Add(me.Controls == MediaControls.Standard
  9552. ? new LSL_Integer(ScriptBaseClass.PRIM_MEDIA_CONTROLS_STANDARD)
  9553. : new LSL_Integer(ScriptBaseClass.PRIM_MEDIA_CONTROLS_MINI));
  9554. }
  9555. else if (code == ScriptBaseClass.PRIM_MEDIA_CURRENT_URL)
  9556. {
  9557. res.Add(new LSL_String(me.CurrentURL));
  9558. }
  9559. else if (code == ScriptBaseClass.PRIM_MEDIA_HOME_URL)
  9560. {
  9561. res.Add(new LSL_String(me.HomeURL));
  9562. }
  9563. else if (code == ScriptBaseClass.PRIM_MEDIA_AUTO_LOOP)
  9564. {
  9565. res.Add(me.AutoLoop ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE);
  9566. }
  9567. else if (code == ScriptBaseClass.PRIM_MEDIA_AUTO_PLAY)
  9568. {
  9569. res.Add(me.AutoPlay ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE);
  9570. }
  9571. else if (code == ScriptBaseClass.PRIM_MEDIA_AUTO_SCALE)
  9572. {
  9573. res.Add(me.AutoScale ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE);
  9574. }
  9575. else if (code == ScriptBaseClass.PRIM_MEDIA_AUTO_ZOOM)
  9576. {
  9577. res.Add(me.AutoZoom ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE);
  9578. }
  9579. else if (code == ScriptBaseClass.PRIM_MEDIA_FIRST_CLICK_INTERACT)
  9580. {
  9581. res.Add(me.InteractOnFirstClick ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE);
  9582. }
  9583. else if (code == ScriptBaseClass.PRIM_MEDIA_WIDTH_PIXELS)
  9584. {
  9585. res.Add(new LSL_Integer(me.Width));
  9586. }
  9587. else if (code == ScriptBaseClass.PRIM_MEDIA_HEIGHT_PIXELS)
  9588. {
  9589. res.Add(new LSL_Integer(me.Height));
  9590. }
  9591. else if (code == ScriptBaseClass.PRIM_MEDIA_WHITELIST_ENABLE)
  9592. {
  9593. res.Add(me.EnableWhiteList ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE);
  9594. }
  9595. else if (code == ScriptBaseClass.PRIM_MEDIA_WHITELIST)
  9596. {
  9597. string[] urls = (string[]) me.WhiteList.Clone();
  9598. for (int j = 0; j < urls.Length; j++)
  9599. urls[j] = Uri.EscapeDataString(urls[j]);
  9600. res.Add(new LSL_String(string.Join(", ", urls)));
  9601. }
  9602. else if (code == ScriptBaseClass.PRIM_MEDIA_PERMS_INTERACT)
  9603. {
  9604. res.Add(new LSL_Integer((int) me.InteractPermissions));
  9605. }
  9606. else if (code == ScriptBaseClass.PRIM_MEDIA_PERMS_CONTROL)
  9607. {
  9608. res.Add(new LSL_Integer((int) me.ControlPermissions));
  9609. }
  9610. }
  9611. return res;
  9612. }
  9613. public LSL_Integer llClearPrimMedia(LSL_Integer face)
  9614. {
  9615. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  9616. ScriptSleep(1000);
  9617. ClearPrimMedia(m_host, face);
  9618. return ScriptBaseClass.LSL_STATUS_OK;
  9619. }
  9620. public LSL_Integer llClearLinkMedia(LSL_Integer link, LSL_Integer face)
  9621. {
  9622. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  9623. ScriptSleep(1000);
  9624. List<ISceneChildEntity> entities = GetLinkParts(link);
  9625. if (entities.Count == 0 || face < 0 || face > entities[0].GetNumberOfSides() - 1)
  9626. return ScriptBaseClass.LSL_STATUS_OK;
  9627. foreach (ISceneChildEntity child in entities)
  9628. ClearPrimMedia(child, face);
  9629. return ScriptBaseClass.LSL_STATUS_OK;
  9630. }
  9631. private void ClearPrimMedia(ISceneChildEntity entity, LSL_Integer face)
  9632. {
  9633. // LSL Spec http://wiki.secondlife.com/wiki/LlClearPrimMedia says to fail silently if face is invalid
  9634. // Assuming silently fail means sending back LSL_STATUS_OK. Ideally, need to check this.
  9635. // FIXME: Don't perform the media check directly
  9636. if (face < 0 || face > entity.GetNumberOfSides() - 1)
  9637. return;
  9638. IMoapModule module = World.RequestModuleInterface<IMoapModule>();
  9639. if (null == module)
  9640. throw new Exception("Media on a prim functions not available");
  9641. module.ClearMediaEntry(entity, face);
  9642. }
  9643. public LSL_Integer llSetPrimMediaParams(LSL_Integer face, LSL_List rules)
  9644. {
  9645. ScriptSleep(1000);
  9646. // LSL Spec http://wiki.secondlife.com/wiki/LlSetPrimMediaParams says to fail silently if face is invalid
  9647. // Assuming silently fail means sending back LSL_STATUS_OK. Ideally, need to check this.
  9648. // Don't perform the media check directly
  9649. if (face < 0 || face > m_host.GetNumberOfSides() - 1)
  9650. return ScriptBaseClass.LSL_STATUS_OK;
  9651. return SetPrimMediaParams(m_host, face, rules);
  9652. }
  9653. public LSL_Integer llSetLinkMedia(LSL_Integer link, LSL_Integer face, LSL_List rules)
  9654. {
  9655. ScriptSleep(1000);
  9656. // LSL Spec http://wiki.secondlife.com/wiki/LlSetPrimMediaParams says to fail silently if face is invalid
  9657. // Assuming silently fail means sending back LSL_STATUS_OK. Ideally, need to check this.
  9658. // Don't perform the media check directly
  9659. List<ISceneChildEntity> entities = GetLinkParts(link);
  9660. if (entities.Count == 0 || face < 0 || face > entities[0].GetNumberOfSides() - 1)
  9661. return ScriptBaseClass.LSL_STATUS_OK;
  9662. foreach (ISceneChildEntity child in entities)
  9663. SetPrimMediaParams(child, face, rules);
  9664. return ScriptBaseClass.LSL_STATUS_OK;
  9665. }
  9666. public LSL_Integer SetPrimMediaParams(ISceneChildEntity obj, int face, LSL_List rules)
  9667. {
  9668. IMoapModule module = World.RequestModuleInterface<IMoapModule>();
  9669. if (null == module)
  9670. throw new Exception("Media on a prim functions not available");
  9671. MediaEntry me = module.GetMediaEntry(obj, face) ?? new MediaEntry();
  9672. int i = 0;
  9673. while (i < rules.Length - 1)
  9674. {
  9675. int code = rules.GetLSLIntegerItem(i++);
  9676. if (code == ScriptBaseClass.PRIM_MEDIA_ALT_IMAGE_ENABLE)
  9677. {
  9678. me.EnableAlterntiveImage = (rules.GetLSLIntegerItem(i++) != 0);
  9679. }
  9680. else if (code == ScriptBaseClass.PRIM_MEDIA_CONTROLS)
  9681. {
  9682. int v = rules.GetLSLIntegerItem(i++);
  9683. me.Controls = ScriptBaseClass.PRIM_MEDIA_CONTROLS_STANDARD == v
  9684. ? MediaControls.Standard
  9685. : MediaControls.Mini;
  9686. }
  9687. else if (code == ScriptBaseClass.PRIM_MEDIA_CURRENT_URL)
  9688. {
  9689. me.CurrentURL = rules.GetLSLStringItem(i++);
  9690. }
  9691. else if (code == ScriptBaseClass.PRIM_MEDIA_HOME_URL)
  9692. {
  9693. me.HomeURL = rules.GetLSLStringItem(i++);
  9694. }
  9695. else if (code == ScriptBaseClass.PRIM_MEDIA_AUTO_LOOP)
  9696. {
  9697. me.AutoLoop = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++));
  9698. }
  9699. else if (code == ScriptBaseClass.PRIM_MEDIA_AUTO_PLAY)
  9700. {
  9701. me.AutoPlay = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++));
  9702. }
  9703. else if (code == ScriptBaseClass.PRIM_MEDIA_AUTO_SCALE)
  9704. {
  9705. me.AutoScale = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++));
  9706. }
  9707. else if (code == ScriptBaseClass.PRIM_MEDIA_AUTO_ZOOM)
  9708. {
  9709. me.AutoZoom = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++));
  9710. }
  9711. else if (code == ScriptBaseClass.PRIM_MEDIA_FIRST_CLICK_INTERACT)
  9712. {
  9713. me.InteractOnFirstClick = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++));
  9714. }
  9715. else if (code == ScriptBaseClass.PRIM_MEDIA_WIDTH_PIXELS)
  9716. {
  9717. me.Width = rules.GetLSLIntegerItem(i++);
  9718. }
  9719. else if (code == ScriptBaseClass.PRIM_MEDIA_HEIGHT_PIXELS)
  9720. {
  9721. me.Height = rules.GetLSLIntegerItem(i++);
  9722. }
  9723. else if (code == ScriptBaseClass.PRIM_MEDIA_WHITELIST_ENABLE)
  9724. {
  9725. me.EnableWhiteList = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++));
  9726. }
  9727. else if (code == ScriptBaseClass.PRIM_MEDIA_WHITELIST)
  9728. {
  9729. string[] rawWhiteListUrls = rules.GetLSLStringItem(i++).ToString().Split(new[] {','});
  9730. List<string> whiteListUrls = new List<string>();
  9731. #if (!ISWIN)
  9732. Array.ForEach(
  9733. rawWhiteListUrls, delegate(string rawUrl) { whiteListUrls.Add(rawUrl.Trim()); });
  9734. #else
  9735. Array.ForEach(
  9736. rawWhiteListUrls, rawUrl => whiteListUrls.Add(rawUrl.Trim()));
  9737. #endif
  9738. me.WhiteList = whiteListUrls.ToArray();
  9739. }
  9740. else if (code == ScriptBaseClass.PRIM_MEDIA_PERMS_INTERACT)
  9741. {
  9742. me.InteractPermissions = (MediaPermission) (byte) (int) rules.GetLSLIntegerItem(i++);
  9743. }
  9744. else if (code == ScriptBaseClass.PRIM_MEDIA_PERMS_CONTROL)
  9745. {
  9746. me.ControlPermissions = (MediaPermission) (byte) (int) rules.GetLSLIntegerItem(i++);
  9747. }
  9748. }
  9749. module.SetMediaEntry(obj, face, me);
  9750. return ScriptBaseClass.LSL_STATUS_OK;
  9751. }
  9752. public LSL_Integer llModPow(int a, int b, int c)
  9753. {
  9754. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  9755. Int64 tmp = 0;
  9756. Math.DivRem(Convert.ToInt64(Math.Pow(a, b)), c, out tmp);
  9757. ScriptSleep(100);
  9758. return Convert.ToInt32(tmp);
  9759. }
  9760. public LSL_Integer llGetInventoryType(string name)
  9761. {
  9762. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;
  9763. lock (m_host.TaskInventory)
  9764. {
  9765. foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
  9766. {
  9767. if (inv.Value.Name == name)
  9768. {
  9769. return inv.Value.Type;
  9770. }
  9771. }
  9772. }
  9773. return -1;
  9774. }
  9775. public void llSetPayPrice(int price, LSL_List quick_pay_buttons)
  9776. {
  9777. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  9778. m_host.ParentEntity.RootChild.PayPrice[0] = price;
  9779. if (quick_pay_buttons.Data.Length > 0)
  9780. m_host.ParentEntity.RootChild.PayPrice[1] = (LSL_Integer) quick_pay_buttons.Data[0];
  9781. else
  9782. m_host.ParentEntity.RootChild.PayPrice[1] = (LSL_Integer) (-2);
  9783. if (quick_pay_buttons.Data.Length > 1)
  9784. m_host.ParentEntity.RootChild.PayPrice[2] = (LSL_Integer) quick_pay_buttons.Data[1];
  9785. else
  9786. m_host.ParentEntity.RootChild.PayPrice[2] = (LSL_Integer) (-2);
  9787. if (quick_pay_buttons.Data.Length > 2)
  9788. m_host.ParentEntity.RootChild.PayPrice[3] = (LSL_Integer) quick_pay_buttons.Data[2];
  9789. else
  9790. m_host.ParentEntity.RootChild.PayPrice[3] = (LSL_Integer) (-2);
  9791. if (quick_pay_buttons.Data.Length > 3)
  9792. m_host.ParentEntity.RootChild.PayPrice[4] = (LSL_Integer) quick_pay_buttons.Data[3];
  9793. else
  9794. m_host.ParentEntity.RootChild.PayPrice[4] = (LSL_Integer) (-2);
  9795. }
  9796. public LSL_Vector llGetCameraPos()
  9797. {
  9798. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  9799. return new LSL_Vector();
  9800. UUID invItemID = InventorySelf();
  9801. if (invItemID == UUID.Zero)
  9802. return new LSL_Vector();
  9803. lock (m_host.TaskInventory)
  9804. {
  9805. if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero)
  9806. return new LSL_Vector();
  9807. if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0)
  9808. {
  9809. ShoutError("No permissions to track the camera");
  9810. return new LSL_Vector();
  9811. }
  9812. }
  9813. IScenePresence presence = World.GetScenePresence(m_host.OwnerID);
  9814. if (presence != null)
  9815. {
  9816. LSL_Vector pos = new LSL_Vector(presence.CameraPosition.X, presence.CameraPosition.Y,
  9817. presence.CameraPosition.Z);
  9818. return pos;
  9819. }
  9820. return new LSL_Vector();
  9821. }
  9822. public LSL_Rotation llGetCameraRot()
  9823. {
  9824. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  9825. return new LSL_Rotation();
  9826. UUID invItemID = InventorySelf();
  9827. if (invItemID == UUID.Zero)
  9828. return new LSL_Rotation();
  9829. lock (m_host.TaskInventory)
  9830. {
  9831. if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero)
  9832. return new LSL_Rotation();
  9833. if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0)
  9834. {
  9835. ShoutError("No permissions to track the camera");
  9836. return new LSL_Rotation();
  9837. }
  9838. }
  9839. IScenePresence presence = World.GetScenePresence(m_host.OwnerID);
  9840. if (presence != null)
  9841. {
  9842. return new LSL_Rotation(presence.CameraRotation.X, presence.CameraRotation.Y, presence.CameraRotation.Z,
  9843. presence.CameraRotation.W);
  9844. }
  9845. return new LSL_Rotation();
  9846. }
  9847. /// <summary>
  9848. /// The SL implementation does nothing, it is deprecated
  9849. /// This duplicates SL
  9850. /// </summary>
  9851. public DateTime llSetPrimURL(string url)
  9852. {
  9853. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  9854. return DateTime.Now;
  9855. return PScriptSleep(2000);
  9856. }
  9857. /// <summary>
  9858. /// The SL implementation shouts an error, it is deprecated
  9859. /// This duplicates SL
  9860. /// </summary>
  9861. public DateTime llRefreshPrimURL()
  9862. {
  9863. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  9864. return DateTime.Now;
  9865. Deprecated("llRefreshPrimURL");
  9866. return PScriptSleep(20000);
  9867. }
  9868. public LSL_String llEscapeURL(string url)
  9869. {
  9870. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  9871. return new LSL_String();
  9872. try
  9873. {
  9874. return Uri.EscapeDataString(url);
  9875. }
  9876. catch (Exception ex)
  9877. {
  9878. return "llEscapeURL: " + ex;
  9879. }
  9880. }
  9881. public LSL_String llUnescapeURL(string url)
  9882. {
  9883. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";
  9884. try
  9885. {
  9886. return Uri.UnescapeDataString(url);
  9887. }
  9888. catch (Exception ex)
  9889. {
  9890. return "llUnescapeURL: " + ex;
  9891. }
  9892. }
  9893. public DateTime llMapDestination(string simname, LSL_Vector pos, LSL_Vector lookAt)
  9894. {
  9895. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  9896. return DateTime.Now;
  9897. UUID avatarID = m_host.OwnerID;
  9898. DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, 0);
  9899. // only works on the first detected avatar
  9900. //This only works in touch events or if the item is attached to the avatar
  9901. if (detectedParams == null && !m_host.IsAttachment) return DateTime.Now;
  9902. if (detectedParams != null)
  9903. avatarID = detectedParams.Key;
  9904. IScenePresence avatar = World.GetScenePresence(avatarID);
  9905. if (avatar != null)
  9906. {
  9907. IMuteListModule module = m_host.ParentEntity.Scene.RequestModuleInterface<IMuteListModule>();
  9908. if (module != null)
  9909. {
  9910. bool cached = false; //Unneeded
  9911. #if (!ISWIN)
  9912. foreach (MuteList mute in module.GetMutes(avatar.UUID, out cached))
  9913. if (mute.MuteID == m_host.OwnerID)
  9914. return DateTime.Now;//If the avatar is muted, they don't get any contact from the muted av
  9915. #else
  9916. if (module.GetMutes(avatar.UUID, out cached).Any(mute => mute.MuteID == m_host.OwnerID))
  9917. {
  9918. return DateTime.Now; //If the avatar is muted, they don't get any contact from the muted av
  9919. }
  9920. #endif
  9921. }
  9922. avatar.ControllingClient.SendScriptTeleportRequest(m_host.Name, simname,
  9923. new Vector3((float) pos.x, (float) pos.y,
  9924. (float) pos.z),
  9925. new Vector3((float) lookAt.x, (float) lookAt.y,
  9926. (float) lookAt.z));
  9927. }
  9928. return PScriptSleep(1000);
  9929. }
  9930. public DateTime llAddToLandBanList(string avatar, double hours)
  9931. {
  9932. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  9933. return DateTime.Now;
  9934. IParcelManagementModule parcelManagement = World.RequestModuleInterface<IParcelManagementModule>();
  9935. if (parcelManagement != null)
  9936. {
  9937. LandData land =
  9938. parcelManagement.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).LandData;
  9939. if (land.OwnerID == m_host.OwnerID)
  9940. {
  9941. ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
  9942. UUID key;
  9943. if (UUID.TryParse(avatar, out key))
  9944. {
  9945. entry.AgentID = key;
  9946. entry.Flags = AccessList.Ban;
  9947. entry.Time = DateTime.Now.AddHours(hours);
  9948. land.ParcelAccessList.Add(entry);
  9949. }
  9950. }
  9951. }
  9952. return PScriptSleep(100);
  9953. }
  9954. public DateTime llRemoveFromLandPassList(string avatar)
  9955. {
  9956. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  9957. return DateTime.Now;
  9958. IParcelManagementModule parcelManagement = World.RequestModuleInterface<IParcelManagementModule>();
  9959. if (parcelManagement != null)
  9960. {
  9961. LandData land =
  9962. parcelManagement.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).LandData;
  9963. if (land.OwnerID == m_host.OwnerID)
  9964. {
  9965. UUID key;
  9966. if (UUID.TryParse(avatar, out key))
  9967. {
  9968. foreach (ParcelManager.ParcelAccessEntry entry in land.ParcelAccessList)
  9969. {
  9970. if (entry.AgentID == key && entry.Flags == AccessList.Access)
  9971. {
  9972. land.ParcelAccessList.Remove(entry);
  9973. break;
  9974. }
  9975. }
  9976. }
  9977. }
  9978. }
  9979. return PScriptSleep(100);
  9980. }
  9981. public DateTime llRemoveFromLandBanList(string avatar)
  9982. {
  9983. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
  9984. return DateTime.Now;
  9985. IParcelManagementModule parcelManagement = World.RequestModuleInterface<IParcelManagementModule>();
  9986. if (parcelManagement != null)
  9987. {
  9988. LandData land =
  9989. parcelManagement.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).LandData;
  9990. if (land.OwnerID == m_host.OwnerID)
  9991. {
  9992. UUID key;
  9993. if (UUID.TryParse(avatar, out key))
  9994. {
  9995. foreach (ParcelManager.ParcelAccessEntry entry in land.ParcelAccessList)
  9996. {
  9997. if (entry.AgentID == key && entry.Flags == AccessList.Ban)
  9998. {
  9999. land.ParcelAccessList.Remove(entry);
  10000. break;
  10001. }
  10002. }
  10003. }
  10004. }
  10005. }
  10006. return PScriptSleep(100);
  10007. }
  10008. public void llSetCameraParams(LSL_List rules)
  10009. {
  10010. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  10011. // our key in the object we are in
  10012. UUID invItemID = InventorySelf();
  10013. if (invItemID == UUID.Zero) return;
  10014. // the object we are in
  10015. UUID objectID = m_host.ParentUUID;
  10016. if (objectID == UUID.Zero) return;
  10017. UUID agentID;
  10018. lock (m_host.TaskInventory)
  10019. {
  10020. // we need the permission first, to know which avatar we want to set the camera for
  10021. agentID = m_host.TaskInventory[invItemID].PermsGranter;
  10022. if (agentID == UUID.Zero) return;
  10023. if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0)
  10024. return;
  10025. }
  10026. IScenePresence presence = World.GetScenePresence(agentID);
  10027. // we are not interested in child-agents
  10028. if (presence.IsChildAgent) return;
  10029. SortedDictionary<int, float> parameters = new SortedDictionary<int, float>();
  10030. object[] data = rules.Data;
  10031. for (int i = 0; i < data.Length; ++i)
  10032. {
  10033. int type = Convert.ToInt32(data[i++].ToString());
  10034. if (i >= data.Length) break; // odd number of entries => ignore the last
  10035. // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3)
  10036. if (type == ScriptBaseClass.CAMERA_FOCUS ||
  10037. type == ScriptBaseClass.CAMERA_FOCUS_OFFSET ||
  10038. type == ScriptBaseClass.CAMERA_POSITION)
  10039. {
  10040. LSL_Vector v = (LSL_Vector) data[i];
  10041. parameters.Add(type + 1, (float) v.x);
  10042. parameters.Add(type + 2, (float) v.y);
  10043. parameters.Add(type + 3, (float) v.z);
  10044. }
  10045. else
  10046. {
  10047. if (data[i] is LSL_Float)
  10048. parameters.Add(type, (float) ((LSL_Float) data[i]).value);
  10049. else if (data[i] is LSL_Integer)
  10050. parameters.Add(type, ((LSL_Integer) data[i]).value);
  10051. else parameters.Add(type, Convert.ToSingle(data[i]));
  10052. }
  10053. }
  10054. if (parameters.Count > 0) presence.ControllingClient.SendSetFollowCamProperties(objectID, parameters);
  10055. }
  10056. public void llClearCameraParams()
  10057. {
  10058. if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
  10059. // our key in the object we are in
  10060. UUID invItemID = InventorySelf();
  10061. if (invItemID == UUID.Zero) return;
  10062. // the object we are in
  10063. UUID objec