PageRenderTime 102ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs

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