public LSL_List llGetPhysicsMaterial()
        {
            var result = new LSL_List();

            result.Add(new LSL_Float(m_host.GravityMultiplier));
            result.Add(new LSL_Float(m_host.Restitution));
            result.Add(new LSL_Float(m_host.Friction));
            result.Add(new LSL_Float(m_host.Density));

            return(result);
        }
        /// <summary>
        ///     The supplied string is scanned for commas
        ///     and converted into a list. Commas are only
        ///     effective if they are encountered outside
        ///     of &apos;&lt;&apos; &apos;&gt;&apos; delimiters. Any whitespace
        ///     before or after an element is trimmed.
        /// </summary>
        public LSL_List llCSV2List(string src)
        {
            LSL_List result = new LSL_List();
            int      parens = 0;
            int      start  = 0;
            int      length = 0;

            if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
            {
                return(new LSL_List());
            }


            for (int i = 0; i < src.Length; i++)
            {
                switch (src[i])
                {
                case '<':
                    parens++;
                    length++;
                    break;

                case '>':
                    if (parens > 0)
                    {
                        parens--;
                    }
                    length++;
                    break;

                case ',':
                    if (parens == 0)
                    {
                        result.Add(new LSL_String(src.Substring(start, length).Trim()));
                        start += length + 1;
                        length = 0;
                    }
                    else
                    {
                        length++;
                    }
                    break;

                default:
                    length++;
                    break;
                }
            }

            result.Add(new LSL_String(src.Substring(start, length).Trim()));

            return(result);
        }
 object ParseJsonNode(OSD node)
 {
     if (node.Type == OSDType.Integer)
     {
         return(new LSL_Integer(node.AsInteger()));
     }
     if (node.Type == OSDType.Boolean)
     {
         return(new LSL_Integer(node.AsBoolean() ? 1 : 0));
     }
     if (node.Type == OSDType.Real)
     {
         return(new LSL_Float(node.AsReal()));
     }
     if (node.Type == OSDType.UUID || node.Type == OSDType.String)
     {
         return(new LSL_String(node.AsString()));
     }
     if (node.Type == OSDType.Array)
     {
         LSL_List resp = new LSL_List();
         OSDArray ar   = node as OSDArray;
         foreach (OSD o in ar)
         {
             resp.Add(ParseJsonNode(o));
         }
         return(resp);
     }
     if (node.Type == OSDType.Map)
     {
         LSL_List resp = new LSL_List();
         OSDMap   ar   = node as OSDMap;
         foreach (KeyValuePair <string, OSD> o in ar)
         {
             resp.Add(new LSL_String(o.Key));
             resp.Add(ParseJsonNode(o.Value));
         }
         return(resp);
     }
     throw new Exception(ScriptBaseClass.JSON_INVALID);
 }
Example #4
0
        public LSL_List botGetBotsWithTag(string tag)
        {
            if (!ScriptProtection.CheckThreatLevel(ThreatLevel.Moderate, "botGetBotsWithTag", m_host, "bot", m_itemID))
            {
                return(new LSL_List());
            }
            IBotManager manager = World.RequestModuleInterface <IBotManager>();
            List <UUID> bots    = new List <UUID>();

            if (manager != null)
            {
                bots = manager.GetBotsWithTag(tag);
            }
            LSL_List b = new LSL_List();

            foreach (UUID bot in bots)
            {
                b.Add(bot.ToString());
            }

            return(b);
        }
Example #5
0
        public LSL_List llParcelMediaQuery(LSL_List aList)
        {
            if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
            {
                return(new LSL_List());
            }

            LSL_List list = new LSL_List();

            foreach (object t in aList.Data)
            {
                if (t != null)
                {
                    IParcelManagementModule parcelManagement = World.RequestModuleInterface <IParcelManagementModule>();
                    if (parcelManagement != null)
                    {
                        LSL_Integer tmp = (LSL_Integer)t;
                        switch ((ParcelMediaCommandEnum)tmp.value)
                        {
                        case ParcelMediaCommandEnum.Url:
                            list.Add(
                                new LSL_String(
                                    parcelManagement.GetLandObject(m_host.AbsolutePosition.X,
                                                                   m_host.AbsolutePosition.Y).LandData.MediaURL));
                            break;

                        case ParcelMediaCommandEnum.Desc:
                            list.Add(
                                new LSL_String(
                                    parcelManagement.GetLandObject(m_host.AbsolutePosition.X,
                                                                   m_host.AbsolutePosition.Y)
                                    .LandData.MediaDescription));
                            break;

                        case ParcelMediaCommandEnum.Texture:
                            list.Add(
                                new LSL_String(
                                    parcelManagement.GetLandObject(m_host.AbsolutePosition.X,
                                                                   m_host.AbsolutePosition.Y)
                                    .LandData.MediaID.ToString()));
                            break;

                        case ParcelMediaCommandEnum.Type:
                            list.Add(
                                new LSL_String(
                                    parcelManagement.GetLandObject(m_host.AbsolutePosition.X,
                                                                   m_host.AbsolutePosition.Y).LandData.MediaType));
                            break;

                        case ParcelMediaCommandEnum.Loop:
                            list.Add(
                                new LSL_Integer(
                                    parcelManagement.GetLandObject(m_host.AbsolutePosition.X,
                                                                   m_host.AbsolutePosition.Y).LandData.MediaLoop
                                            ? 1
                                            : 0));
                            break;

                        case ParcelMediaCommandEnum.LoopSet:
                            list.Add(
                                new LSL_Integer(
                                    parcelManagement.GetLandObject(m_host.AbsolutePosition.X,
                                                                   m_host.AbsolutePosition.Y).LandData.MediaLoopSet));
                            break;

                        case ParcelMediaCommandEnum.Size:
                            list.Add(
                                new LSL_String(
                                    parcelManagement.GetLandObject(m_host.AbsolutePosition.X,
                                                                   m_host.AbsolutePosition.Y).LandData.MediaHeight));
                            list.Add(
                                new LSL_String(
                                    parcelManagement.GetLandObject(m_host.AbsolutePosition.X,
                                                                   m_host.AbsolutePosition.Y).LandData.MediaWidth));
                            break;

                        default:
                            const ParcelMediaCommandEnum mediaCommandEnum = ParcelMediaCommandEnum.Url;
                            NotImplemented("llParcelMediaQuery", "Parameter not supported yet: " +
                                           Enum.Parse(mediaCommandEnum.GetType(), t.ToString()));
                            break;
                        }
                    }
                }
            }
            PScriptSleep(m_sleepMsOnParcelMediaQuery);
            return(list);
        }
Example #6
0
        //  <summary>
        //  Scan the string supplied in 'src' and tokenize it based upon two sets of
        //  tokenizers provided in two lists, separators and spacers.
        //  </summary>
        //
        //  <remarks>
        //  Separators demarcate tokens and are elided as they are encountered. Spacers
        //  also demarcate tokens, but are themselves retained as tokens.
        //
        //  Both separators and spacers may be arbitrarily long strings. i.e. ":::".
        //
        //  The function returns an ordered list representing the tokens found in the supplied
        //  sources string. If two successive tokenizers are encountered, then a NULL entry is added
        //  to the list.
        //
        //  It is a precondition that the source and toekizer lisst are non-null. If they are null,
        //  then a null pointer exception will be thrown while their lengths are being determined.
        //
        //  A small amount of working memoryis required of approximately 8*#tokenizers.
        //
        //  There are many ways in which this function can be implemented, this implementation is
        //  fairly naive and assumes that when the function is invooked with a short source
        //  string and/or short lists of tokenizers, then performance will not be an issue.
        //
        //  In order to minimize the perofrmance effects of long strings, or large numbers
        //  of tokeizers, the function skips as far as possible whenever a toekenizer is found,
        //  and eliminates redundant tokenizers as soon as is possible.
        //
        //  The implementation tries to avoid any copying of arrays or other objects.
        //  </remarks>

        LSL_List ParseString(string src, LSL_List separators, LSL_List spacers, bool keepNulls)
        {
            int beginning = 0;
            int srclen    = src.Length;
            int seplen    = separators.Length;

            object[] separray = separators.Data;
            int      spclen   = spacers.Length;

            object[] spcarray = spacers.Data;
            int      mlen     = seplen + spclen;

            int[]  offset = new int[mlen + 1];
            bool[] active = new bool[mlen];

            //    Initial capacity reduces resize cost

            LSL_List tokens = new LSL_List();

            //    All entries are initially valid

            for (int i = 0; i < mlen; i++)
            {
                active[i] = true;
            }

            offset[mlen] = srclen;

            while (beginning < srclen)
            {
                int best = mlen;

                //    Scan for separators

                int j;
                for (j = 0; j < seplen; j++)
                {
                    if (separray[j].ToString() == string.Empty)
                    {
                        active[j] = false;
                    }

                    if (active[j])
                    {
                        // scan all of the markers
                        if ((offset[j] = src.IndexOf(separray[j].ToString(), beginning, StringComparison.Ordinal)) == -1)
                        {
                            // not present at all
                            active[j] = false;
                        }
                        else
                        {
                            // present and correct
                            if (offset[j] < offset[best])
                            {
                                // closest so far
                                best = j;
                                if (offset[best] == beginning)
                                {
                                    break;
                                }
                            }
                        }
                    }
                }

                //    Scan for spacers

                if (offset[best] != beginning)
                {
                    for (j = seplen; (j < mlen) && (offset[best] > beginning); j++)
                    {
                        if (spcarray[j - seplen].ToString() == string.Empty)
                        {
                            active[j] = false;
                        }

                        if (active[j])
                        {
                            // scan all of the markers
                            if ((offset[j] = src.IndexOf(spcarray[j - seplen].ToString(), beginning, StringComparison.Ordinal)) == -1)
                            {
                                // not present at all
                                active[j] = false;
                            }
                            else
                            {
                                // present and correct
                                if (offset[j] < offset[best])
                                {
                                    // closest so far
                                    best = j;
                                }
                            }
                        }
                    }
                }

                //    This is the normal exit from the scanning loop

                if (best == mlen)
                {
                    // no markers were found on this pass
                    // so we're pretty much done
                    if ((keepNulls) || ((srclen - beginning) > 0))
                    {
                        tokens.Add(new LSL_String(src.Substring(beginning, srclen - beginning)));
                    }
                    break;
                }

                //    Otherwise we just add the newly delimited token
                //    and recalculate where the search should continue.
                if ((keepNulls) || ((offset[best] - beginning) > 0))
                {
                    tokens.Add(new LSL_String(src.Substring(beginning, offset[best] - beginning)));
                }

                if (best < seplen)
                {
                    beginning = offset[best] + (separray[best].ToString()).Length;
                }
                else
                {
                    beginning = offset[best] + (spcarray[best - seplen].ToString()).Length;
                    string str = spcarray[best - seplen].ToString();
                    if ((keepNulls) || ((str.Length > 0)))
                    {
                        tokens.Add(new LSL_String(str));
                    }
                }
            }

            //    This an awkward an not very intuitive boundary case. If the
            //    last substring is a tokenizer, then there is an implied trailing
            //    null list entry. Hopefully the single comparison will not be too
            //    arduous. Alternatively the 'break' could be replced with a return
            //    but that's shabby programming.

            if ((beginning == srclen) && (keepNulls))
            {
                if (srclen != 0)
                {
                    tokens.Add(new LSL_String(""));
                }
            }

            return(tokens);
        }
        /// <summary>
        ///     Elements in the source list starting with 0 and then
        ///     every i+stride. If the stride is negative then the scan
        ///     is backwards producing an inverted result.
        ///     Only those elements that are also in the specified
        ///     range are included in the result.
        /// </summary>
        public LSL_List llList2ListStrided(LSL_List src, int start, int end, int stride)
        {
            LSL_List result = new LSL_List();

            int[] si      = new int[2];
            int[] ei      = new int[2];
            bool  twopass = false;

            if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
            {
                return(new LSL_List());
            }


            //  First step is always to deal with negative indices

            if (start < 0)
            {
                start = src.Length + start;
            }
            if (end < 0)
            {
                end = src.Length + end;
            }

            //  Out of bounds indices are OK, just trim them
            //  accordingly

            if (start > src.Length)
            {
                start = src.Length;
            }

            if (end > src.Length)
            {
                end = src.Length;
            }

            if (stride == 0)
            {
                stride = 1;
            }

            //  There may be one or two ranges to be considered

            if (start != end)
            {
                if (start <= end)
                {
                    si[0] = start;
                    ei[0] = end;
                }
                else
                {
                    si[1]   = start;
                    ei[1]   = src.Length;
                    si[0]   = 0;
                    ei[0]   = end;
                    twopass = true;
                }

                //  The scan always starts from the beginning of the
                //  source list, but members are only selected if they
                //  fall within the specified sub-range. The specified
                //  range values are inclusive.
                //  A negative stride reverses the direction of the
                //  scan producing an inverted list as a result.

                if (stride > 0)
                {
                    for (int i = 0; i < src.Length; i += stride)
                    {
                        if (i <= ei[0] && i >= si[0])
                        {
                            result.Add(src.Data[i]);
                        }
                        if (twopass && i >= si[1] && i <= ei[1])
                        {
                            result.Add(src.Data[i]);
                        }
                    }
                }
                else if (stride < 0)
                {
                    for (int i = src.Length - 1; i >= 0; i += stride)
                    {
                        if (i <= ei[0] && i >= si[0])
                        {
                            result.Add(src.Data[i]);
                        }
                        if (twopass && i >= si[1] && i <= ei[1])
                        {
                            result.Add(src.Data[i]);
                        }
                    }
                }
            }
            else
            {
                if (start % stride == 0)
                {
                    result.Add(src.Data[start]);
                }
            }

            return(result);
        }
        /// <summary>
        ///     Randomizes the list, be arbitrarily reordering
        ///     sublists of stride elements. As the stride approaches
        ///     the size of the list, the options become very
        ///     limited.
        /// </summary>
        /// <remarks>
        ///     This could take a while for very large list
        ///     sizes.
        /// </remarks>
        public LSL_List llListRandomize(LSL_List src, int stride)
        {
            LSL_List result;
            Random   rand = new Random();

            if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
            {
                return(new LSL_List());
            }


            if (stride <= 0)
            {
                stride = 1;
            }

            // Stride MUST be a factor of the list length
            // If not, then return the src list. This also
            // traps those cases where stride > length.

            if (src.Length != stride && src.Length % stride == 0)
            {
                int chunkk = src.Length / stride;

                int[] chunks = new int[chunkk];

                for (int i = 0; i < chunkk; i++)
                {
                    chunks[i] = i;
                }

                // Knuth shuffle the chunkk index
                for (int i = chunkk - 1; i >= 1; i--)
                {
                    // Elect an unrandomized chunk to swap
                    int index = rand.Next(i + 1);

                    // and swap position with first unrandomized chunk
                    int tmp = chunks[i];
                    chunks[i]     = chunks[index];
                    chunks[index] = tmp;
                }

                // Construct the randomized list

                result = new LSL_List();

                for (int i = 0; i < chunkk; i++)
                {
                    for (int j = 0; j < stride; j++)
                    {
                        result.Add(src.Data[chunks[i] * stride + j]);
                    }
                }
            }
            else
            {
                object[] array = new object[src.Length];
                Array.Copy(src.Data, 0, array, 0, src.Length);
                result = new LSL_List(array);
            }

            return(result);
        }
        /// <summary>
        ///     A partial implementation.
        ///     http://lslwiki.net/lslwiki/wakka.php?wakka=llGetBoundingBox
        ///     So far only valid for standing/flying/ground sitting avatars and single prim objects.
        ///     If the object has multiple prims and/or a sitting avatar then the bounding
        ///     box is for the root prim only.
        /// </summary>
        public LSL_List llGetBoundingBox(string obj)
        {
            if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
            {
                return(new LSL_List());
            }

            UUID     objID  = UUID.Zero;
            LSL_List result = new LSL_List();

            if (!UUID.TryParse(obj, out objID))
            {
                result.Add(new LSL_Vector());
                result.Add(new LSL_Vector());
                return(result);
            }
            IScenePresence presence = World.GetScenePresence(objID);

            if (presence != null)
            {
                if (presence.ParentID == UUID.Zero) // not sat on an object
                {
                    LSL_Vector lower = new LSL_Vector();
                    LSL_Vector upper = new LSL_Vector();
                    if (presence.Animator.Animations.ImplicitDefaultAnimation.AnimID
                        == AnimationSet.Animations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
                    {
                        // This is for ground sitting avatars
                        IAvatarAppearanceModule appearance = presence.RequestModuleInterface <IAvatarAppearanceModule>();
                        if (appearance != null)
                        {
                            float height = appearance.Appearance.AvatarHeight / 2.66666667f;
                            lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
                            upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
                        }
                    }
                    else
                    {
                        // This is for standing/flying avatars
                        IAvatarAppearanceModule appearance = presence.RequestModuleInterface <IAvatarAppearanceModule>();
                        if (appearance != null)
                        {
                            float height = appearance.Appearance.AvatarHeight / 2.0f;
                            lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f);
                            upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
                        }
                    }
                    result.Add(lower);
                    result.Add(upper);
                    return(result);
                }
                // sitting on an object so we need the bounding box of that
                // which should include the avatar so set the UUID to the
                // UUID of the object the avatar is sat on and allow it to fall through
                // to processing an object
                ISceneChildEntity p = World.GetSceneObjectPart(presence.ParentID);
                objID = p.UUID;
            }
            ISceneChildEntity part = World.GetSceneObjectPart(objID);

            // Currently only works for single prims without a sitting avatar
            if (part != null)
            {
                Vector3    halfSize = part.Scale * 0.5f;
                LSL_Vector lower    = new LSL_Vector(halfSize.X * -1.0f, halfSize.Y * -1.0f, halfSize.Z * -1.0f);
                LSL_Vector upper    = new LSL_Vector(halfSize.X, halfSize.Y, halfSize.Z);
                result.Add(lower);
                result.Add(upper);
                return(result);
            }

            // Not found so return empty values
            result.Add(new LSL_Vector());
            result.Add(new LSL_Vector());
            return(result);
        }
        public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options)
        {
            if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
            {
                return(new LSL_List());
            }

            LSL_List list = new LSL_List();

            Vector3 rayStart = start.ToVector3();
            Vector3 rayEnd   = end.ToVector3();
            Vector3 dir      = rayEnd - rayStart;

            float dist = Vector3.Mag(dir);

            int  count         = 1;
            bool detectPhantom = false;
            int  dataFlags     = 0;
            int  rejectTypes   = 0;

            for (int i = 0; i < options.Length; i += 2)
            {
                if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS)
                {
                    count = options.GetLSLIntegerItem(i + 1);
                }
                else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM)
                {
                    detectPhantom = (options.GetLSLIntegerItem(i + 1) > 0);
                }
                else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS)
                {
                    dataFlags = options.GetLSLIntegerItem(i + 1);
                }
                else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES)
                {
                    rejectTypes = options.GetLSLIntegerItem(i + 1);
                }
            }

            if (count > 16)
            {
                count = 16;
            }
            else if (count <= 0)
            {
                Error("llCastRay", "You must request at least one result from llCastRay.");
                return(new LSL_List());
            }

            List <ContactResult> results = new List <ContactResult>();

            bool checkTerrain     = !((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) == ScriptBaseClass.RC_REJECT_LAND);
            bool checkAgents      = !((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) == ScriptBaseClass.RC_REJECT_AGENTS);
            bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL);
            bool checkPhysical    = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL);


            if (checkAgents)
            {
                ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd);
                foreach (ContactResult r in agentHits)
                {
                    results.Add(r);
                }
            }

            if (checkPhysical || checkNonPhysical || detectPhantom)
            {
                ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, checkPhysical, checkNonPhysical, detectPhantom, count + 2);
                for (int iter = 0; iter < objectHits.Length; iter++)
                {
                    // Redistance the Depth because the Scene RayCaster returns distance from center to make the rezzing code simpler.
                    objectHits[iter].Depth = Vector3.Distance(objectHits[iter].Pos, rayStart);
                    results.Add(objectHits[iter]);
                }
            }

            if (checkTerrain)
            {
                ContactResult?groundContact = GroundIntersection(rayStart, rayEnd);
                if (groundContact != null)
                {
                    results.Add((ContactResult)groundContact);
                }
            }

            results.Sort(delegate(ContactResult a, ContactResult b) {
                return(a.Depth.CompareTo(b.Depth));
            });

            int          values  = 0;
            ISceneEntity thisgrp = m_host.ParentEntity;

            foreach (ContactResult result in results)
            {
                if (result.Depth > dist)
                {
                    continue;
                }

                // physics ray can return colisions with host prim
                // this is supposed to happen
                if (m_host.LocalId == result.ConsumerID)
                {
                    continue;
                }

                if (!checkTerrain && result.ConsumerID == 0)
                {
                    continue; //Terrain
                }
                UUID itemID  = UUID.Zero;
                int  linkNum = 0;

                ISceneChildEntity part = World.GetSceneObjectPart(result.ConsumerID);
                // It's a prim!
                if (part != null)
                {
                    // dont detect members of same object ???
                    if (part.ParentEntity == thisgrp)
                    {
                        continue;
                    }

                    if ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) == ScriptBaseClass.RC_GET_ROOT_KEY)
                    {
                        itemID = part.ParentEntity.UUID;
                    }
                    else
                    {
                        itemID = part.UUID;
                    }

                    linkNum = part.LinkNum;
                }
                else
                {
                    IScenePresence sp = World.GetScenePresence(result.ConsumerID);
                    /// It it a boy? a girl?
                    if (sp != null)
                    {
                        itemID = sp.UUID;
                    }
                }

                list.Add(new LSL_String(itemID.ToString()));

                if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM)
                {
                    list.Add(new LSL_Integer(linkNum));
                }

                list.Add(new LSL_Vector(result.Pos));

                if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL)
                {
                    Vector3 norm = result.Normal * -1;
                    list.Add(new LSL_Vector(norm));
                }

                values++;
                if (values >= count)
                {
                    break;
                }
            }

            list.Add(new LSL_Integer(values));

            return(list);
        }