/Aurora/AuroraDotNetEngine/APIs/LSL_Api.cs
C# | 11892 lines | 9029 code | 1744 blank | 1119 comment | 2752 complexity | 3e42528a41dc4612bd21e14c964eefd9 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- /*
- * Copyright (c) Contributors, http://aurora-sim.org/
- * See CONTRIBUTORS.TXT for a full list of copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the Aurora-Sim Project nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Linq;
- using System.Runtime.Remoting.Lifetime;
- using System.Text;
- using System.Threading;
- using System.Text.RegularExpressions;
- using Nini.Config;
- using OpenMetaverse;
- using OpenMetaverse.Packets;
- using Aurora.Framework;
- using OpenSim.Region.Framework.Interfaces;
- using OpenSim.Region.Framework.Scenes;
- using OpenSim.Region.Framework.Scenes.Serialization;
- using Aurora.ScriptEngine.AuroraDotNetEngine.Plugins;
- using Aurora.ScriptEngine.AuroraDotNetEngine.APIs.Interfaces;
- using Aurora.ScriptEngine.AuroraDotNetEngine.Runtime;
- using OpenSim.Services.Interfaces;
- using GridRegion = OpenSim.Services.Interfaces.GridRegion;
- using PrimType = Aurora.Framework.PrimType;
- using AssetLandmark = Aurora.Framework.AssetLandmark;
-
- using LSL_Float = Aurora.ScriptEngine.AuroraDotNetEngine.LSL_Types.LSLFloat;
- using LSL_Integer = Aurora.ScriptEngine.AuroraDotNetEngine.LSL_Types.LSLInteger;
- using LSL_Key = Aurora.ScriptEngine.AuroraDotNetEngine.LSL_Types.LSLString;
- using LSL_List = Aurora.ScriptEngine.AuroraDotNetEngine.LSL_Types.list;
- using LSL_Rotation = Aurora.ScriptEngine.AuroraDotNetEngine.LSL_Types.Quaternion;
- using LSL_String = Aurora.ScriptEngine.AuroraDotNetEngine.LSL_Types.LSLString;
- using LSL_Vector = Aurora.ScriptEngine.AuroraDotNetEngine.LSL_Types.Vector3;
-
- namespace Aurora.ScriptEngine.AuroraDotNetEngine.APIs
- {
- /// <summary>
- /// Contains all LSL ll-functions. This class will be in Default AppDomain.
- /// </summary>
- [Serializable]
- public class LSL_Api : MarshalByRefObject, ILSL_Api, IScriptApi
- {
- protected IScriptModulePlugin m_ScriptEngine;
- protected ISceneChildEntity m_host;
- protected uint m_localID;
- protected UUID m_itemID;
- protected bool throwErrorOnNotImplemented = true;
- protected float m_ScriptDelayFactor = 1.0f;
- protected float m_ScriptDistanceFactor = 1.0f;
- protected float m_MinTimerInterval = 0.1f;
-
- protected DateTime m_timer = DateTime.Now;
- protected bool m_waitingForScriptAnswer = false;
- protected bool m_automaticLinkPermission = false;
- protected IMessageTransferModule m_TransferModule = null;
- protected int m_notecardLineReadCharsMax = 255;
- protected int m_scriptConsoleChannel = 0;
- protected bool m_scriptConsoleChannelEnabled = false;
- protected IUrlModule m_UrlModule = null;
- internal ScriptProtectionModule ScriptProtection;
- protected IWorldComm m_comms = null;
-
- // MUST be a ref type
- public class UserInfoCacheEntry
- {
- public int time;
- public UserAccount account;
- public UserInfo pinfo;
- }
- protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache =
- new Dictionary<UUID, UserInfoCacheEntry>();
-
- public void Initialize(IScriptModulePlugin ScriptEngine, ISceneChildEntity host, uint localID, UUID itemID, ScriptProtectionModule module)
- {
- m_ScriptEngine = ScriptEngine;
- m_host = host;
- m_localID = localID;
- m_itemID = itemID;
- ScriptProtection = module;
-
- m_ScriptDelayFactor =
- m_ScriptEngine.Config.GetFloat("ScriptDelayFactor", 1.0f);
- m_ScriptDistanceFactor =
- m_ScriptEngine.Config.GetFloat("ScriptDistanceLimitFactor", 1.0f);
- m_MinTimerInterval =
- m_ScriptEngine.Config.GetFloat("MinTimerInterval", 0.5f);
- m_automaticLinkPermission =
- m_ScriptEngine.Config.GetBoolean("AutomaticLinkPermission", false);
- m_notecardLineReadCharsMax =
- m_ScriptEngine.Config.GetInt("NotecardLineReadCharsMax", 255);
- if (m_notecardLineReadCharsMax > 65535)
- m_notecardLineReadCharsMax = 65535;
-
- m_TransferModule =
- World.RequestModuleInterface<IMessageTransferModule>();
- m_UrlModule = World.RequestModuleInterface<IUrlModule>();
- m_comms = World.RequestModuleInterface<IWorldComm>();
- }
-
- public IScriptApi Copy()
- {
- return new LSL_Api();
- }
-
- public string Name
- {
- get { return "ll"; }
- }
-
- public string InterfaceName
- {
- get { return "ILSL_Api"; }
- }
-
- /// <summary>
- /// We don't have to add any assemblies here
- /// </summary>
- public string[] ReferencedAssemblies
- {
- get { return new string[0]; }
- }
-
- /// <summary>
- /// We use the default namespace, so we don't have any to add
- /// </summary>
- public string[] NamespaceAdditions
- {
- get { return new string[0]; }
- }
-
- public void Dispose()
- {
- }
-
- public override Object InitializeLifetimeService()
- {
- ILease lease = (ILease)base.InitializeLifetimeService();
-
- if (lease != null && lease.CurrentState == LeaseState.Initial)
- {
- lease.InitialLeaseTime = TimeSpan.FromMinutes(0);
- // lease.RenewOnCallTime = TimeSpan.FromSeconds(10.0);
- // lease.SponsorshipTimeout = TimeSpan.FromMinutes(1.0);
- }
- return lease;
-
- }
-
- protected virtual void ScriptSleep(int delay)
- {
- delay = (int)(delay * m_ScriptDelayFactor);
- if (delay == 0)
- return;
-
- Thread.Sleep(delay);
- }
-
- /// <summary>
- /// This is the new sleep implementation that allows for us to not freeze the script thread while we run
- /// </summary>
- /// <param name="delay"></param>
- /// <returns></returns>
- protected DateTime PScriptSleep(int delay)
- {
- double dly = (delay * m_ScriptDelayFactor);
- if (dly == 0.0)
- return DateTime.Now;
-
- DateTime timeToStopSleeping = DateTime.Now.AddMilliseconds(dly);
- return timeToStopSleeping;
- }
-
- public IScene World
- {
- get { return m_host.ParentEntity.Scene; }
- }
-
- public void state(string newState)
- {
- m_ScriptEngine.SetState(m_itemID, newState);
- throw new EventAbortException();
- }
-
- /// <summary>
- /// Reset the named script. The script must be present
- /// in the same prim.
- /// </summary>
- public void llResetScript()
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
- if (m_UrlModule != null)
- {
- m_UrlModule.ScriptRemoved(m_itemID);
- }
- m_ScriptEngine.ResetScript(m_host.UUID, m_itemID, true);
- }
-
- public void llResetOtherScript(string name)
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
- UUID item;
-
-
-
- if ((item = ScriptByName(name)) != UUID.Zero)
- m_ScriptEngine.ResetScript(m_host.UUID, item, false);
- else
- ShoutError("llResetOtherScript: script " + name + " not found");
- }
-
-
- public LSL_Integer llGetScriptState(string name)
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
- return new LSL_Integer();
- UUID item;
-
-
-
- if ((item = ScriptByName(name)) != UUID.Zero)
- {
- return m_ScriptEngine.GetScriptRunningState(item) ? 1 : 0;
- }
-
- ShoutError("llGetScriptState: script " + name + " not found");
-
- // If we didn't find it, then it's safe to
- // assume it is not running.
-
- return 0;
- }
-
- public LSL_Key llGenerateKey()
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Key();
-
- return UUID.Random().ToString();
- }
-
- public void llSetScriptState(string name, int run)
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
- UUID item;
-
-
-
- // These functions are supposed to be robust,
- // so get the state one step at a time.
-
- if ((item = ScriptByName(name)) != UUID.Zero)
- {
- m_ScriptEngine.SetScriptRunningState(item, run == 1);
- }
- else
- {
- ShoutError("llSetScriptState: script " + name + " not found");
- }
- }
-
- public List<ISceneChildEntity> GetLinkParts(int linkType)
- {
- List<ISceneChildEntity> ret = new List<ISceneChildEntity> { m_host };
-
- if (linkType == ScriptBaseClass.LINK_SET)
- {
- if (m_host.ParentEntity != null)
- return new List<ISceneChildEntity>(m_host.ParentEntity.ChildrenEntities());
- return ret;
- }
-
- if (linkType == ScriptBaseClass.LINK_ROOT)
- {
- if (m_host.ParentEntity != null)
- {
- ret = new List<ISceneChildEntity> { m_host.ParentEntity.RootChild };
- return ret;
- }
- return ret;
- }
-
- if (linkType == ScriptBaseClass.LINK_ALL_OTHERS)
- {
- if (m_host.ParentEntity == null)
- return new List<ISceneChildEntity>();
- ret = new List<ISceneChildEntity>(m_host.ParentEntity.ChildrenEntities());
- if (ret.Contains(m_host))
- ret.Remove(m_host);
- return ret;
- }
-
- if (linkType == ScriptBaseClass.LINK_ALL_CHILDREN)
- {
- if (m_host.ParentEntity == null)
- return new List<ISceneChildEntity>();
- ret = new List<ISceneChildEntity>(m_host.ParentEntity.ChildrenEntities());
- if (ret.Contains(m_host.ParentEntity.RootChild))
- ret.Remove(m_host.ParentEntity.RootChild);
- return ret;
- }
-
- if (linkType == ScriptBaseClass.LINK_THIS)
- {
- return ret;
- }
-
- if (linkType < 0 || m_host.ParentEntity == null)
- return new List<ISceneChildEntity>();
- IEntity target = m_host.ParentEntity.GetLinkNumPart(linkType);
- if (target is ISceneChildEntity)
- {
- ret = new List<ISceneChildEntity> { target as ISceneChildEntity };
- }
- //No allowing scene presences to be found here
- return ret;
- }
-
- public List<IEntity> GetLinkPartsAndEntities(int linkType)
- {
- List<IEntity> ret = new List<IEntity> { m_host };
-
- if (linkType == ScriptBaseClass.LINK_SET)
- {
- if (m_host.ParentEntity != null)
- {
- List<ISceneChildEntity> parts = new List<ISceneChildEntity>(m_host.ParentEntity.ChildrenEntities());
- #if (!ISWIN)
- return parts.ConvertAll<IEntity>(new Converter<ISceneChildEntity, IEntity>(delegate(ISceneChildEntity part)
- {
- return (IEntity)part;
- }));
- #else
- return parts.ConvertAll (part => (IEntity) part);
- #endif
- }
- return ret;
- }
-
- if (linkType == ScriptBaseClass.LINK_ROOT)
- {
- if (m_host.ParentEntity != null)
- {
- ret = new List<IEntity> { m_host.ParentEntity.RootChild };
- return ret;
- }
- return ret;
- }
-
- if (linkType == ScriptBaseClass.LINK_ALL_OTHERS)
- {
- if (m_host.ParentEntity == null)
- return new List<IEntity>();
- List<ISceneChildEntity> sceneobjectparts = new List<ISceneChildEntity>(m_host.ParentEntity.ChildrenEntities());
- #if (!ISWIN)
- ret = sceneobjectparts.ConvertAll<IEntity>(new Converter<ISceneChildEntity, IEntity>(delegate(ISceneChildEntity part)
- {
- return (IEntity)part;
- }));
- #else
- ret = sceneobjectparts.ConvertAll (part => (IEntity) part);
- #endif
- if (ret.Contains(m_host))
- ret.Remove(m_host);
- return ret;
- }
-
- if (linkType == ScriptBaseClass.LINK_ALL_CHILDREN)
- {
- if (m_host.ParentEntity == null)
- return new List<IEntity>();
- List<ISceneChildEntity> children = new List<ISceneChildEntity>(m_host.ParentEntity.ChildrenEntities());
- #if (!ISWIN)
- ret = children.ConvertAll<IEntity>(new Converter<ISceneChildEntity, IEntity>(delegate(ISceneChildEntity part)
- {
- return (IEntity)part;
- }));
- #else
- ret = children.ConvertAll (part => (IEntity) part);
- #endif
- if (ret.Contains(m_host.ParentEntity.RootChild))
- ret.Remove(m_host.ParentEntity.RootChild);
- return ret;
- }
-
- if (linkType == ScriptBaseClass.LINK_THIS)
- {
- return ret;
- }
-
- if (linkType < 0 || m_host.ParentEntity == null)
- return new List<IEntity>();
- IEntity target = m_host.ParentEntity.GetLinkNumPart(linkType);
- if (target == null)
- return new List<IEntity>();
- ret = new List<IEntity> { target };
-
- return ret;
- }
-
- protected UUID InventorySelf()
- {
- UUID invItemID = new UUID();
-
- lock (m_host.TaskInventory)
- {
- foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
- {
- if (inv.Value.Type == 10 && inv.Value.ItemID == m_itemID)
- {
- invItemID = inv.Key;
- break;
- }
- }
- }
-
- return invItemID;
- }
-
- protected UUID InventoryKey(string name, int type)
- {
- lock (m_host.TaskInventory)
- {
- foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
- {
- if (inv.Value.Name == name)
- {
- if (inv.Value.Type != type)
- return UUID.Zero;
-
- return inv.Value.AssetID;
- }
- }
- }
-
- return UUID.Zero;
- }
-
- protected UUID InventoryKey(string name, bool throwExceptionIfDoesNotExist)
- {
- lock (m_host.TaskInventory)
- {
- foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
- {
- if (inv.Value.Name == name)
- {
- return inv.Value.AssetID;
- }
- }
- }
-
- if (throwExceptionIfDoesNotExist)
- {
- IChatModule chatModule = World.RequestModuleInterface<IChatModule>();
- if (chatModule != null)
- chatModule.SimChat("Could not find sound '" + name + "'.",
- ChatTypeEnum.DebugChannel, 2147483647, m_host.AbsolutePosition,
- m_host.Name, m_host.UUID, false, World);
- }
-
- return UUID.Zero;
- }
-
-
- /// <summary>
- /// accepts a valid UUID, -or- a name of an inventory item.
- /// Returns a valid UUID or UUID.Zero if key invalid and item not found
- /// in prim inventory.
- /// </summary>
- /// <param name="k"></param>
- /// <param name="throwExceptionIfDoesNotExist"></param>
- /// <returns></returns>
- protected UUID KeyOrName(string k, bool throwExceptionIfDoesNotExist)
- {
- UUID key = UUID.Zero;
-
- // if we can parse the string as a key, use it.
- if (UUID.TryParse(k, out key))
- {
- return key;
- }
- // else try to locate the name in inventory of object. found returns key,
- // not found returns UUID.Zero which will translate to the default particle texture
- return InventoryKey(k, throwExceptionIfDoesNotExist);
- }
-
- // convert a LSL_Rotation to a Quaternion
- protected Quaternion Rot2Quaternion(LSL_Rotation r)
- {
- Quaternion q = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s);
- q.Normalize();
- return q;
- }
-
- //These are the implementations of the various ll-functions used by the LSL scripts.
- public LSL_Float llSin(double f)
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
-
- return Math.Sin(f);
- }
-
- public LSL_Float llCos(double f)
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
-
- return Math.Cos(f);
- }
-
- public LSL_Float llTan(double f)
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
-
- return Math.Tan(f);
- }
-
- public LSL_Float llAtan2(double x, double y)
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
-
- return Math.Atan2(x, y);
- }
-
- public LSL_Float llSqrt(double f)
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
-
- return Math.Sqrt(f);
- }
-
- public LSL_Float llPow(double fbase, double fexponent)
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
-
- return Math.Pow(fbase, fexponent);
- }
-
- public LSL_Integer llAbs(int i)
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Integer();
- // changed to replicate LSL behaviour whereby minimum int value is returned untouched.
-
- if (i == Int32.MinValue)
- return i;
- return Math.Abs(i);
- }
-
- public LSL_Float llFabs(double f)
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
-
- return Math.Abs(f);
- }
-
- public LSL_Float llFrand(double mag)
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
-
- lock (Util.RandomClass)
- {
- return Util.RandomClass.NextDouble() * mag;
- }
- }
-
- public LSL_Integer llFloor(double f)
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Integer();
-
- return (int)Math.Floor(f);
- }
-
- public LSL_Integer llCeil(double f)
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Integer();
-
- return (int)Math.Ceiling(f);
- }
-
- // Xantor 01/May/2008 fixed midpointrounding (2.5 becomes 3.0 instead of 2.0, default = ToEven)
- public LSL_Integer llRound(double f)
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Integer();
-
- double RoundedNumber = Math.Round(f, MidpointRounding.AwayFromZero);
- //Attempt to fix rounded numbers like -4.5 arounding away from zero
- if (f < 0)
- {
- if (f + 0.5 == RoundedNumber || f - 0.5 == RoundedNumber)
- {
- RoundedNumber += 1;
- }
- }
- return (int)RoundedNumber;
- }
-
- //This next group are vector operations involving squaring and square root. ckrinke
- public LSL_Float llVecMag(LSL_Vector v)
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
-
- return LSL_Vector.Mag(v);
- }
-
- public LSL_Vector llVecNorm(LSL_Vector v)
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
- return LSL_Vector.Norm(v);
- }
-
- public LSL_Float llVecDist(LSL_Vector a, LSL_Vector b)
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Float();
-
- double dx = a.x - b.x;
- double dy = a.y - b.y;
- double dz = a.z - b.z;
- return Math.Sqrt(dx * dx + dy * dy + dz * dz);
- }
-
- //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke
-
- // Old implementation of llRot2Euler. Normalization not required as Atan2 function will
- // only return values >= -PI (-180 degrees) and <= PI (180 degrees).
-
- public LSL_Vector llRot2Euler(LSL_Rotation r)
- {
- //This implementation is from http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions. ckrinke
- LSL_Rotation t = new LSL_Rotation(r.x * r.x, r.y * r.y, r.z * r.z, r.s * r.s);
- double m = (t.x + t.y + t.z + t.s);
- if (m == 0) return new LSL_Vector();
- double n = 2 * (r.y * r.s + r.x * r.z);
- double p = m * m - n * n;
- if (p > 0)
- return new LSL_Vector(Math.Atan2(2.0 * (r.x * r.s - r.y * r.z), (-t.x - t.y + t.z + t.s)),
- Math.Atan2(n, Math.Sqrt(p)),
- Math.Atan2(2.0 * (r.z * r.s - r.x * r.y), (t.x - t.y - t.z + t.s)));
- if (n > 0)
- return new LSL_Vector(0.0, Math.PI * 0.5, Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z));
- return new LSL_Vector(0.0, -Math.PI * 0.5, Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z));
- }
-
- /* From wiki:
- The Euler angle vector (in radians) is converted to a rotation by doing the rotations around the 3 axes
- in Z, Y, X order. So llEuler2Rot(<1.0, 2.0, 3.0> * DEG_TO_RAD) generates a rotation by taking the zero rotation,
- a vector pointing along the X axis, first rotating it 3 degrees around the global Z axis, then rotating the resulting
- vector 2 degrees around the global Y axis, and finally rotating that 1 degree around the global X axis.
- */
-
- /* How we arrived at this llEuler2Rot
- *
- * Experiment in SL to determine conventions:
- * llEuler2Rot(<PI,0,0>)=<1,0,0,0>
- * llEuler2Rot(<0,PI,0>)=<0,1,0,0>
- * llEuler2Rot(<0,0,PI>)=<0,0,1,0>
- *
- * Important facts about Quaternions
- * - multiplication is non-commutative (a*b != b*a)
- * - http://en.wikipedia.org/wiki/Quaternion#Basis_multiplication
- *
- * Above SL experiment gives (c1,c2,c3,s1,s2,s3 as defined in our llEuler2Rot):
- * Qx = c1+i*s1
- * Qy = c2+j*s2;
- * Qz = c3+k*s3;
- *
- * Rotations applied in order (from above) Z, Y, X
- * Q = (Qz * Qy) * Qx
- * ((c1+i*s1)*(c2+j*s2))*(c3+k*s3)
- * (c1*c2+i*s1*c2+j*c1*s2+ij*s1*s2)*(c3+k*s3)
- * (c1*c2+i*s1*c2+j*c1*s2+k*s1*s2)*(c3+k*s3)
- * 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
- * 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
- * regroup: x=i*(s1*c2*c3+c1*s2*s3)
- * y=j*(c1*s2*c3-s1*c2*s3)
- * z=k*(s1*s2*c3+c1*c2*s3)
- * s= c1*c2*c3-s1*s2*s3
- *
- * This implementation agrees with the functions found here:
- * http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions
- * And with the results in SL.
- *
- * It's also possible to calculate llEuler2Rot by direct multiplication of
- * the Qz, Qy, and Qx vectors (as above - and done in the "accurate" function
- * from the wiki).
- * Apparently in some cases this is better from a numerical precision perspective?
- */
-
- public LSL_Rotation llEuler2Rot(LSL_Vector v)
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Rotation();
-
-
- double c1 = Math.Cos(v.x * 0.5);
- double c2 = Math.Cos(v.y * 0.5);
- double c3 = Math.Cos(v.z * 0.5);
- double s1 = Math.Sin(v.x * 0.5);
- double s2 = Math.Sin(v.y * 0.5);
- double s3 = Math.Sin(v.z * 0.5);
-
- double x = s1 * c2 * c3 + c1 * s2 * s3;
- double y = c1 * s2 * c3 - s1 * c2 * s3;
- double z = s1 * s2 * c3 + c1 * c2 * s3;
- double s = c1 * c2 * c3 - s1 * s2 * s3;
-
- return new LSL_Rotation(x, y, z, s);
- }
-
- public LSL_Rotation llAxes2Rot(LSL_Vector fwd, LSL_Vector left, LSL_Vector up)
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Rotation();
-
- double s;
- double tr = fwd.x + left.y + up.z + 1.0;
-
- if (tr >= 1.0)
- {
- s = 0.5 / Math.Sqrt(tr);
- return new LSL_Rotation(
- (left.z - up.y) * s,
- (up.x - fwd.z) * s,
- (fwd.y - left.x) * s,
- 0.25 / s);
- }
- double max = (left.y > up.z) ? left.y : up.z;
-
- if (max < fwd.x)
- {
- s = Math.Sqrt(fwd.x - (left.y + up.z) + 1.0);
- double x = s * 0.5;
- s = 0.5 / s;
- return new LSL_Rotation(
- x,
- (fwd.y + left.x) * s,
- (up.x + fwd.z) * s,
- (left.z - up.y) * s);
- }
- if (max == left.y)
- {
- s = Math.Sqrt(left.y - (up.z + fwd.x) + 1.0);
- double y = s * 0.5;
- s = 0.5 / s;
- return new LSL_Rotation(
- (fwd.y + left.x) * s,
- y,
- (left.z + up.y) * s,
- (up.x - fwd.z) * s);
- }
- s = Math.Sqrt(up.z - (fwd.x + left.y) + 1.0);
- double z = s * 0.5;
- s = 0.5 / s;
- return new LSL_Rotation(
- (up.x + fwd.z) * s,
- (left.z + up.y) * s,
- z,
- (fwd.y - left.x) * s);
- }
-
- public LSL_Vector llRot2Fwd(LSL_Rotation r)
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
- return new LSL_Vector();
-
-
- double m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s;
- // m is always greater than zero
- // if m is not equal to 1 then Rotation needs to be normalized
- if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision
- {
- m = 1.0 / Math.Sqrt(m);
- r.x *= m;
- r.y *= m;
- r.z *= m;
- r.s *= m;
- }
-
- // Fast Algebric Calculations instead of Vectors & Quaternions Product
- double x = r.x * r.x - r.y * r.y - r.z * r.z + r.s * r.s;
- double y = 2 * (r.x * r.y + r.z * r.s);
- double z = 2 * (r.x * r.z - r.y * r.s);
- return (new LSL_Vector(x, y, z));
- }
-
- public LSL_Vector llRot2Left(LSL_Rotation r)
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
-
-
- double m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s;
- // m is always greater than zero
- // if m is not equal to 1 then Rotation needs to be normalized
- if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision
- {
- m = 1.0 / Math.Sqrt(m);
- r.x *= m;
- r.y *= m;
- r.z *= m;
- r.s *= m;
- }
-
- // Fast Algebric Calculations instead of Vectors & Quaternions Product
- double x = 2 * (r.x * r.y - r.z * r.s);
- double y = -r.x * r.x + r.y * r.y - r.z * r.z + r.s * r.s;
- double z = 2 * (r.x * r.s + r.y * r.z);
- return (new LSL_Vector(x, y, z));
- }
-
- public LSL_Vector llRot2Up(LSL_Rotation r)
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
-
- double m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s;
- // m is always greater than zero
- // if m is not equal to 1 then Rotation needs to be normalized
- if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision
- {
- m = 1.0 / Math.Sqrt(m);
- r.x *= m;
- r.y *= m;
- r.z *= m;
- r.s *= m;
- }
-
- // Fast Algebric Calculations instead of Vectors & Quaternions Product
- double x = 2 * (r.x * r.z + r.y * r.s);
- double y = 2 * (-r.x * r.s + r.y * r.z);
- double z = -r.x * r.x - r.y * r.y + r.z * r.z + r.s * r.s;
- return (new LSL_Vector(x, y, z));
- }
-
- public LSL_Rotation llRotBetween(LSL_Vector a, LSL_Vector b)
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Rotation();
- //A and B should both be normalized
-
- LSL_Rotation rotBetween;
- // Check for zero vectors. If either is zero, return zero rotation. Otherwise,
- // continue calculation.
- if (a == new LSL_Vector(0.0f, 0.0f, 0.0f) || b == new LSL_Vector(0.0f, 0.0f, 0.0f))
- {
- rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
- }
- else
- {
- a = LSL_Vector.Norm(a);
- b = LSL_Vector.Norm(b);
- double dotProduct = LSL_Vector.Dot(a, b);
- // There are two degenerate cases possible. These are for vectors 180 or
- // 0 degrees apart. These have to be detected and handled individually.
- //
- // Check for vectors 180 degrees apart.
- // A dot product of -1 would mean the angle between vectors is 180 degrees.
- if (dotProduct < -0.9999999f)
- {
- // First assume X axis is orthogonal to the vectors.
- LSL_Vector orthoVector = new LSL_Vector(1.0f, 0.0f, 0.0f);
- orthoVector = orthoVector - a * (a.x / LSL_Vector.Dot(a, a));
- // Check for near zero vector. A very small non-zero number here will create
- // a rotation in an undesired direction.
- rotBetween = LSL_Vector.Mag(orthoVector) > 0.0001 ? new LSL_Rotation(orthoVector.x, orthoVector.y, orthoVector.z, 0.0f) : new LSL_Rotation(0.0f, 0.0f, 1.0f, 0.0f);
- }
- // Check for parallel vectors.
- // A dot product of 1 would mean the angle between vectors is 0 degrees.
- else if (dotProduct > 0.9999999f)
- {
- // Set zero rotation.
- rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
- }
- else
- {
- // All special checks have been performed so get the axis of rotation.
- LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
- // Quarternion s value is the length of the unit vector + dot product.
- double qs = 1.0 + dotProduct;
- rotBetween = new LSL_Rotation(crossProduct.x, crossProduct.y, crossProduct.z, qs);
- // Normalize the rotation.
- double mag = LSL_Rotation.Mag(rotBetween);
- // We shouldn't have to worry about a divide by zero here. The qs value will be
- // non-zero because we already know if we're here, then the dotProduct is not -1 so
- // qs will not be zero. Also, we've already handled the input vectors being zero so the
- // crossProduct vector should also not be zero.
- rotBetween.x = rotBetween.x / mag;
- rotBetween.y = rotBetween.y / mag;
- rotBetween.z = rotBetween.z / mag;
- rotBetween.s = rotBetween.s / mag;
- // Check for undefined values and set zero rotation if any found. This code might not actually be required
- // any longer since zero vectors are checked for at the top.
- if (Double.IsNaN(rotBetween.x) || Double.IsNaN(rotBetween.y) || Double.IsNaN(rotBetween.z) || Double.IsNaN(rotBetween.s))
- {
- rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
- }
- }
- }
- return rotBetween;
- }
-
- public void llWhisper(int channelID, string text)
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
-
-
- if (text.Length > 1023)
- text = text.Substring(0, 1023);
-
- IChatModule chatModule = World.RequestModuleInterface<IChatModule>();
- if (chatModule != null)
- chatModule.SimChat(text, ChatTypeEnum.Whisper, channelID,
- m_host.ParentEntity.RootChild.AbsolutePosition, m_host.Name, m_host.UUID, false, World);
-
- if (m_comms != null)
- m_comms.DeliverMessage(ChatTypeEnum.Whisper, channelID, m_host.Name, m_host.UUID, text);
- }
-
- public void llSay(int channelID, object m_text)
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
-
- string text = m_text.ToString();
-
- if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel))
- {
- Console.WriteLine(text);
- }
- else
- {
- if (text.Length > 1023)
- text = text.Substring(0, 1023);
-
- IChatModule chatModule = World.RequestModuleInterface<IChatModule>();
- if (chatModule != null)
- chatModule.SimChat(text, ChatTypeEnum.Say, channelID,
- m_host.ParentEntity.RootChild.AbsolutePosition, m_host.Name, m_host.UUID, false, World);
-
- if (m_comms != null)
- m_comms.DeliverMessage(ChatTypeEnum.Say, channelID, m_host.Name, m_host.UUID, text);
- }
- }
-
- public void llShout(int channelID, string text)
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
-
- if (text.Length > 1023)
- text = text.Substring(0, 1023);
-
- IChatModule chatModule = World.RequestModuleInterface<IChatModule>();
- if (chatModule != null)
- chatModule.SimChat(text, ChatTypeEnum.Shout, channelID,
- m_host.ParentEntity.RootChild.AbsolutePosition, m_host.Name, m_host.UUID, true, World);
-
- if (m_comms != null)
- m_comms.DeliverMessage(ChatTypeEnum.Shout, channelID, m_host.Name, m_host.UUID, text);
- }
-
- public void llRegionSay(int channelID, string text)
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
- if (text.Length > 1023)
- text = text.Substring(0, 1023);
-
- if (channelID == 0) //0 isn't normally allowed, so check against a higher threat level
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.Moderate, "LSL", m_host, "LSL", m_itemID)) return;
-
- IChatModule chatModule = World.RequestModuleInterface<IChatModule>();
- if (chatModule != null)
- chatModule.SimChat(text, ChatTypeEnum.Region, channelID,
- m_host.ParentEntity.RootChild.AbsolutePosition, m_host.Name, m_host.UUID, false, World);
-
- if (m_comms != null)
- m_comms.DeliverMessage(ChatTypeEnum.Region, channelID, m_host.Name, m_host.UUID, text);
- }
-
- public void llRegionSayTo(LSL_Key toID, int channelID, string text)
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
-
- IChatModule chatModule = World.RequestModuleInterface<IChatModule>();
-
- if (text.Length > 1023)
- text = text.Substring(0, 1023);
- if (channelID == 0)
- {
- IScenePresence presence = World.GetScenePresence(UUID.Parse(toID.m_string));
- if (presence != null)
- {
- if (chatModule != null)
- chatModule.TrySendChatMessage(presence, m_host.AbsolutePosition, m_host.AbsolutePosition,
- m_host.UUID, m_host.Name, ChatTypeEnum.Say, text, ChatSourceType.Object, 10000);
- }
- }
-
- if (m_comms != null)
- m_comms.DeliverMessage(ChatTypeEnum.Region, channelID, m_host.Name, m_host.UUID, UUID.Parse(toID.m_string), text);
- }
-
- public LSL_Integer llListen(int channelID, string name, string ID, string msg)
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Integer();
-
- UUID keyID;
- UUID.TryParse(ID, out keyID);
- if (m_comms != null)
- return m_comms.Listen(m_itemID, m_host.UUID, channelID, name, keyID, msg);
- return -1;
- }
-
- public void llListenControl(int number, int active)
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
-
- if (m_comms != null)
- m_comms.ListenControl(m_itemID, number, active);
- }
-
- public void llListenRemove(int number)
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
-
- if (m_comms != null)
- m_comms.ListenRemove(m_itemID, number);
- }
-
- public void llSensor(string name, string id, int type, double range, double arc)
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
-
- UUID keyID = UUID.Zero;
- UUID.TryParse(id, out keyID);
- SensorRepeatPlugin sensorPlugin = (SensorRepeatPlugin)m_ScriptEngine.GetScriptPlugin("SensorRepeat");
- sensorPlugin.SenseOnce(m_host.UUID, m_itemID, name, keyID, type, range, arc, m_host);
- }
-
- public void llSensorRepeat(string name, string id, int type, double range, double arc, double rate)
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
-
- UUID keyID = UUID.Zero;
- UUID.TryParse(id, out keyID);
-
- SensorRepeatPlugin sensorPlugin = (SensorRepeatPlugin)m_ScriptEngine.GetScriptPlugin("SensorRepeat");
- sensorPlugin.SetSenseRepeatEvent(m_host.UUID, m_itemID, name, keyID, type, range, arc, rate, m_host);
- }
-
- public void llSensorRemove()
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
-
- SensorRepeatPlugin sensorPlugin = (SensorRepeatPlugin)m_ScriptEngine.GetScriptPlugin("SensorRepeat");
- sensorPlugin.RemoveScript(m_host.UUID, m_itemID);
- }
-
- public string resolveName(UUID objecUUID)
- {
- // try avatar username surname
- UserAccount account = World.UserAccountService.GetUserAccount(World.RegionInfo.AllScopeIDs, objecUUID);
- if (account != null)
- return account.Name;
-
- // try an scene object
- ISceneChildEntity SOP = World.GetSceneObjectPart(objecUUID);
- if (SOP != null)
- return SOP.Name;
-
- IEntity SensedObject;
- if (!World.Entities.TryGetValue(objecUUID, out SensedObject))
- {
- IGroupsModule groups = World.RequestModuleInterface<IGroupsModule>();
- if (groups != null)
- {
- GroupRecord gr = groups.GetGroupRecord(objecUUID);
- if (gr != null)
- return gr.GroupName;
- }
- return String.Empty;
- }
-
- return SensedObject.Name;
- }
-
- public LSL_String llDetectedName(int number)
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_String();
-
- DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, number);
- if (detectedParams == null)
- return String.Empty;
- return detectedParams.Name;
- }
-
- public LSL_String llDetectedKey(int number)
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_String();
-
- DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, number);
- if (detectedParams == null)
- return String.Empty;
- return detectedParams.Key.ToString();
- }
-
- public LSL_String llDetectedOwner(int number)
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_String();
-
- DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, number);
- if (detectedParams == null)
- return String.Empty;
- return detectedParams.Owner.ToString();
- }
-
- public LSL_Integer llDetectedType(int number)
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Integer();
-
- DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, number);
- if (detectedParams == null)
- return 0;
- return new LSL_Integer(detectedParams.Type);
- }
-
- public LSL_Vector llDetectedPos(int number)
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
-
- DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, number);
- if (detectedParams == null)
- return new LSL_Vector();
- return detectedParams.Position;
- }
-
- public LSL_Vector llDetectedVel(int number)
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
-
- DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, number);
- if (detectedParams == null)
- return new LSL_Vector();
- return detectedParams.Velocity;
- }
-
- public LSL_Vector llDetectedGrab(int number)
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
-
- DetectParams parms = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, number);
- if (parms == null)
- return new LSL_Vector(0, 0, 0);
-
- return parms.OffsetPos;
- }
-
- public LSL_Rotation llDetectedRot(int number)
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Rotation();
-
- DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, number);
- if (detectedParams == null)
- return new LSL_Rotation();
- return detectedParams.Rotation;
- }
-
- public LSL_Integer llDetectedGroup(int number)
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Integer();
-
- DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, number);
- if (detectedParams == null)
- return new LSL_Integer(0);
- if (m_host.GroupID == detectedParams.Group)
- return new LSL_Integer(1);
- return new LSL_Integer(0);
- }
-
- public LSL_Integer llDetectedLinkNumber(int number)
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Integer();
-
- DetectParams parms = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, number);
- if (parms == null)
- return new LSL_Integer(0);
-
- return new LSL_Integer(parms.LinkNum);
- }
-
- /// <summary>
- /// See http://wiki.secondlife.com/wiki/LlDetectedTouchBinormal for details
- /// </summary>
- public LSL_Vector llDetectedTouchBinormal(int index)
- {
- if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return new LSL_Vector();
-
- DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_host.UUID, m_itemID, index);
- if (detectedParams == null)
- return new LSL_Vector();
- return detectedParams.TouchBinormal;
- …
Large files files are truncated, but you can click here to view the full file