/// <summary>
        ///     Process the supplied list and return the
        ///     content of the list formatted as a comma
        ///     separated list. There is a space after
        ///     each comma.
        /// </summary>
        public LSL_String llList2CSV(LSL_List src)
        {
            string ret = String.Empty;
            int x = 0;

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

            if (src.Data.Length > 0)
            {
                ret = src.Data[x++].ToString();
                for (; x < src.Data.Length; x++)
                {
                    ret += ", " + src.Data[x].ToString();
                }
            }

            return ret;
        }
        public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules)
        {
            List<ISceneChildEntity> parts = GetLinkParts(linknumber);

            foreach (ISceneChildEntity part in parts)
                SetPrimParams(part, rules, m_allowOpenSimParams);
        }
        public void llSetPrimitiveParams(LSL_List rules)
        {
            if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;

            SetPrimParams(m_host, rules, m_allowOpenSimParams);
        }
 public void llSetKeyframedMotion(LSL_List keyframes, LSL_List options)
 {
     if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
     if (!m_host.IsRoot)
     {
         ShoutError("Must be used in the root object!");
         return;
     }
     KeyframeAnimation.Data dataType = KeyframeAnimation.Data.Both;
     KeyframeAnimation.Modes currentMode = KeyframeAnimation.Modes.Forward;
     for (int i = 0; i < options.Length; i += 2)
     {
         LSL_Integer option = options.GetLSLIntegerItem(i);
         LSL_Integer value = options.GetLSLIntegerItem(i + 1);
         if (option == ScriptBaseClass.KFM_COMMAND)
         {
             m_host.ParentEntity.AddKeyframedMotion(null, (KeyframeAnimation.Commands) value.value);
             break; //Its supposed to be the only option in the list
         }
         if (option == ScriptBaseClass.KFM_MODE)
         {
             currentMode = (KeyframeAnimation.Modes) value.value;
         }
         else if (option == ScriptBaseClass.KFM_DATA)
         {
             dataType = (KeyframeAnimation.Data) value.value;
         }
     }
     List<Vector3> positions = new List<Vector3>();
     List<Quaternion> rotations = new List<Quaternion>();
     List<float> times = new List<float>();
     for (int i = 0; i < keyframes.Length; i += (dataType == KeyframeAnimation.Data.Both ? 3 : 2))
     {
         if (dataType == KeyframeAnimation.Data.Both ||
             dataType == KeyframeAnimation.Data.Translation)
         {
             LSL_Vector pos = keyframes.GetVector3Item(i);
             positions.Add(pos.ToVector3());
         }
         if (dataType == KeyframeAnimation.Data.Both ||
             dataType == KeyframeAnimation.Data.Rotation)
         {
             LSL_Rotation rot = keyframes.GetQuaternionItem(i + (dataType == KeyframeAnimation.Data.Both ? 1 : 0));
             Quaternion quat = rot.ToQuaternion();
             quat.Normalize();
             rotations.Add(quat);
         }
         LSL_Float time = keyframes.GetLSLFloatItem(i + (dataType == KeyframeAnimation.Data.Both ? 2 : 1));
         times.Add((float)time);
     }
     KeyframeAnimation animation = new KeyframeAnimation
                                       {
                                           CurrentMode = currentMode,
                                           PositionList = positions.ToArray(),
                                           RotationList = rotations.ToArray(),
                                           TimeList = times.ToArray(),
                                           CurrentAnimationPosition = 0,
                                           InitialPosition = m_host.AbsolutePosition,
                                           InitialRotation = m_host.GetRotationOffset()
                                       };
     m_host.ParentEntity.AddKeyframedMotion(animation, KeyframeAnimation.Commands.Play);
 }
        public LSL_Integer llSetLinkMedia(LSL_Integer link, LSL_Integer face, LSL_List rules)
        {
            ScriptSleep(1000);

            // LSL Spec http://wiki.secondlife.com/wiki/LlSetPrimMediaParams says to fail silently if face is invalid
            // Assuming silently fail means sending back LSL_STATUS_OK.  Ideally, need to check this.
            // Don't perform the media check directly
            List<ISceneChildEntity> entities = GetLinkParts(link);
            if (entities.Count == 0 || face < 0 || face > entities[0].GetNumberOfSides() - 1)
                return ScriptBaseClass.LSL_STATUS_OK;
            foreach (ISceneChildEntity child in entities)
                SetPrimMediaParams(child, face, rules);
            return ScriptBaseClass.LSL_STATUS_OK;
        }
        public void llParticleSystem(LSL_List rules)
        {
            if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;

            SetParticleSystem(m_host, rules);
        }
 public void llPursue(LSL_String target, LSL_List options)
 {
     IBotManager botManager = World.RequestModuleInterface<IBotManager>();
     if (botManager != null)
     {
         float fuzz = 2;
         Vector3 offset = Vector3.Zero;
         bool requireLOS = false;
         bool intercept = false; //Not implemented
         for (int i = 0; i < options.Length; i += 2)
         {
             LSL_Types.LSLInteger opt = options.GetLSLIntegerItem(i);
             if (opt == ScriptBaseClass.PURSUIT_FUZZ_FACTOR)
                 fuzz = (float) options.GetLSLFloatItem(i + 1).value;
             if (opt == ScriptBaseClass.PURSUIT_OFFSET)
                 offset = options.GetVector3Item(i + 1).ToVector3();
             if (opt == ScriptBaseClass.REQUIRE_LINE_OF_SIGHT)
                 requireLOS = options.GetLSLIntegerItem(i + 1) == 1;
             if (opt == ScriptBaseClass.PURSUIT_INTERCEPT)
                 intercept = options.GetLSLIntegerItem(i + 1) == 1;
         }
         botManager.FollowAvatar(m_host.ParentEntity.UUID, target.m_string, fuzz, fuzz, requireLOS, offset,
                                 m_host.ParentEntity.OwnerID);
     }
 }
        public LSL_Vector llList2Vector(LSL_List src, int index)
        {
            if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
                return new LSL_Vector();

            if (index < 0)
            {
                index = src.Length + index;
            }
            if (index >= src.Length || index < 0)
            {
                return new LSL_Vector(0, 0, 0);
            }
            if (src.Data[index] is LSL_Vector)
            {
                return (LSL_Vector) src.Data[index];
            }
            return new LSL_Vector(src.Data[index].ToString());
        }
        /// <summary>
        ///     Returns the index of the first occurrence of test
        ///     in src.
        /// </summary>
        public LSL_Integer llListFindList(LSL_List src, LSL_List test)
        {
            int index = -1;
            int length = src.Length - test.Length + 1;

            if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;

            // If either list is empty, do not match

            if (src.Length != 0 && test.Length != 0)
            {
                for (int i = 0; i < length; i++)
                {
                    if (src.Data[i].Equals(test.Data[0]) || test.Data[0].Equals(src.Data[i]))
                    {
                        int j;
                        for (j = 1; j < test.Length; j++)
                            if (!(src.Data[i + j].Equals(test.Data[j]) || test.Data[j].Equals(src.Data[i + j])))
                                break;

                        if (j == test.Length)
                        {
                            index = i;
                            break;
                        }
                    }
                }
            }

            return index;
        }
        /// <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;
        }
        public LSL_String llList2String(LSL_List src, int index)
        {
            if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return "";

            if (index < 0)
            {
                index = src.Length + index;
            }
            if (index >= src.Length || index < 0)
            {
                return String.Empty;
            }
            return new LSL_String(src.Data[index].ToString());
        }
        public LSL_List llList2List(LSL_List src, int start, int end)
        {
            if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
                return new LSL_List();

            return src.GetSublist(start, end);
        }
 public LSL_String llList2Json(LSL_String type, LSL_List values)
 {
     try
     {
         if (type == ScriptBaseClass.JSON_ARRAY)
         {
             OSDArray array = new OSDArray();
             foreach (object o in values.Data)
             {
                 array.Add(ListToJson(o));
             }
             return OSDParser.SerializeJsonString(array);
         }
         else if (type == ScriptBaseClass.JSON_OBJECT)
         {
             OSDMap map = new OSDMap();
             for (int i = 0; i < values.Data.Length; i += 2)
             {
                 if (!(values.Data[i] is LSL_String))
                     return ScriptBaseClass.JSON_INVALID;
                 map.Add(((LSL_String)values.Data[i]).m_string, ListToJson(values.Data[i+1]));
             }
             return OSDParser.SerializeJsonString(map);
         }
         return ScriptBaseClass.JSON_INVALID;
     }
     catch (Exception ex)
     {
         return ex.Message;
     }
 }
        public LSL_Integer llList2Integer(LSL_List src, int index)
        {
            if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return 0;

            if (index < 0)
            {
                index = src.Length + index;
            }
            if (index >= src.Length || index < 0)
            {
                return 0;
            }
            try
            {
                if (src.Data[index] is LSL_Integer)
                    return (LSL_Integer) src.Data[index];
                if (src.Data[index] is LSL_Float)
                    return Convert.ToInt32(((LSL_Float) src.Data[index]).value);
                return new LSL_Integer(src.Data[index].ToString());
            }
            catch (FormatException)
            {
                return 0;
            }
            catch (InvalidCastException)
            {
                return 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 do not supported yet: " +
                                               Enum.Parse(mediaCommandEnum.GetType(), t.ToString()));
                                break;
                        }
                    }
                }
            }
            ScriptSleep(2000);
            return list;
        }
        /// <summary>
        ///     Insert the list identified by &lt;src&gt; into the
        ///     list designated by &lt;dest&gt; such that the first
        ///     new element has the index specified by &lt;index&gt;
        /// </summary>
        public LSL_List llListInsertList(LSL_List dest, LSL_List src, int index)
        {
            if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
                return new LSL_List();

            LSL_List pref = null;
            LSL_List suff = null;

            if (index < 0)
            {
                index = index + dest.Length;
                if (index < 0)
                {
                    index = 0;
                }
            }

            if (index != 0)
            {
                pref = dest.GetSublist(0, index - 1);
                if (index < dest.Length)
                {
                    suff = dest.GetSublist(index, -1);
                    return pref + src + suff;
                }
                return pref + src;
            }
            if (index < dest.Length)
            {
                suff = dest.GetSublist(index, -1);
                return src + suff;
            }
            return src;
        }
 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
 {
     if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "llParseStringKeepNulls", m_host, "LSL", m_itemID))
         return new LSL_List();
     return ParseString(src, separators, spacers, true);
 }
        /// <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;
        }
 public void llPatrolPoints(LSL_List patrolPoints, LSL_List options)
 {
     List<Vector3> positions = new List<Vector3>();
     List<TravelMode> travelMode = new List<TravelMode>();
     foreach (object pos in patrolPoints.Data)
     {
         if (!(pos is LSL_Vector))
             continue;
         LSL_Vector p = (LSL_Vector) pos;
         positions.Add(p.ToVector3());
         travelMode.Add(TravelMode.Walk);
     }
     IBotManager botManager = World.RequestModuleInterface<IBotManager>();
     if (botManager != null)
         botManager.SetBotMap(m_host.ParentEntity.UUID, positions, travelMode, 1, m_host.ParentEntity.OwnerID);
 }
        /// <summary>
        ///     illListReplaceList removes the sub-list defined by the inclusive indices
        ///     start and end and inserts the src list in its place. The inclusive
        ///     nature of the indices means that at least one element must be deleted
        ///     if the indices are within the bounds of the existing list. I.e. 2,2
        ///     will remove the element at index 2 and replace it with the source
        ///     list. Both indices may be negative, with the usual interpretation. An
        ///     interesting case is where end is lower than start. As these indices
        ///     bound the list to be removed, then 0->end, and start->lim are removed
        ///     and the source list is added as a suffix.
        /// </summary>
        public LSL_List llListReplaceList(LSL_List dest, LSL_List src, int start, int end)
        {
            if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
                return new LSL_List();

            // Note that although we have normalized, both
            // indices could still be negative.
            if (start < 0)
            {
                start = start + dest.Length;
            }

            if (end < 0)
            {
                end = end + dest.Length;
            }
            // The comventional case, remove a sequence starting with
            // start and ending with end. And then insert the source
            // list.
            if (start <= end)
            {
                // If greater than zero, then there is going to be a
                // surviving prefix. Otherwise the inclusive nature
                // of the indices mean that we're going to add the
                // source list as a prefix.
                if (start > 0)
                {
                    LSL_List pref = dest.GetSublist(0, start - 1);
                    // Only add a suffix if there is something
                    // beyond the end index (it's inclusive too).
                    if (end + 1 < dest.Length)
                    {
                        return pref + src + dest.GetSublist(end + 1, -1);
                    }
                    return pref + src;
                }
                // If start is less than or equal to zero, then
                // the new list is simply a prefix. We still need to
                // figure out any necessary surgery to the destination
                // based upon end. Note that if end exceeds the upper
                // bound in this case, the entire destination list
                // is removed.
                if (end + 1 < dest.Length)
                {
                    return src + dest.GetSublist(end + 1, -1);
                }
                return src;
            }
            // Finally, if start > end, we strip away a prefix and
            // a suffix, to leave the list that sits <between> ens
            // and start, and then tag on the src list. AT least
            // that's my interpretation. We can get sublist to do
            // this for us. Note that one, or both of the indices
            // might have been negative.
            return dest.GetSublist(end + 1, start - 1) + src;
        }
        public void llSetCameraParams(LSL_List rules)
        {
            if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;

            // our key in the object we are in
            UUID invItemID = InventorySelf();
            if (invItemID == UUID.Zero) return;

            // the object we are in
            UUID objectID = m_host.ParentUUID;
            if (objectID == UUID.Zero) return;

            UUID agentID;
            lock (m_host.TaskInventory)
            {
                // we need the permission first, to know which avatar we want to set the camera for
                agentID = m_host.TaskInventory[invItemID].PermsGranter;

                if (agentID == UUID.Zero) return;
                if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0)
                    return;
            }

            IScenePresence presence = World.GetScenePresence(agentID);

            // we are not interested in child-agents
            if (presence.IsChildAgent) return;

            SortedDictionary<int, float> parameters = new SortedDictionary<int, float>();
            object[] data = rules.Data;
            for (int i = 0; i < data.Length; ++i)
            {
                int type = Convert.ToInt32(data[i++].ToString());
                if (i >= data.Length) break; // odd number of entries => ignore the last

                // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3)
                if (type == ScriptBaseClass.CAMERA_FOCUS ||
                    type == ScriptBaseClass.CAMERA_FOCUS_OFFSET ||
                    type == ScriptBaseClass.CAMERA_POSITION)
                {
                    LSL_Vector v = (LSL_Vector) data[i];
                    parameters.Add(type + 1, (float) v.x);
                    parameters.Add(type + 2, (float) v.y);
                    parameters.Add(type + 3, (float) v.z);
                }
                else
                {
                    if (data[i] is LSL_Float)
                        parameters.Add(type, (float) ((LSL_Float) data[i]).value);
                    else if (data[i] is LSL_Integer)
                        parameters.Add(type, ((LSL_Integer) data[i]).value);
                    else parameters.Add(type, Convert.ToSingle(data[i]));
                }
            }
            if (parameters.Count > 0) presence.ControllingClient.SendSetFollowCamProperties(objectID, parameters);
        }
        public LSL_List llListSort(LSL_List src, int stride, int ascending)
        {
            if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
                return new LSL_List();

            if (stride <= 0)
            {
                stride = 1;
            }
            return src.Sort(stride, ascending);
        }
        public LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules)
        {
            ISceneChildEntity obj = World.GetSceneObjectPart(prim);
            if (obj == null)
                return new LSL_List();

            if (obj.OwnerID == m_host.OwnerID)
                return new LSL_List();

            return GetLinkPrimitiveParams(obj, rules, true);
        }
        public LSL_Float llListStatistics(int operation, LSL_List src)
        {
            if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
                return new LSL_Float();

            LSL_List nums = LSL_List.ToDoubleList(src);
            if (operation == ScriptBaseClass.LIST_STAT_RANGE)
                return nums.Range();
            if (operation == ScriptBaseClass.LIST_STAT_MIN)
                return nums.Min();
            if (operation == ScriptBaseClass.LIST_STAT_MAX)
                return nums.Max();
            if (operation == ScriptBaseClass.LIST_STAT_MEAN)
                return nums.Mean();
            if (operation == ScriptBaseClass.LIST_STAT_MEDIAN)
                return nums.Median();
            if (operation == ScriptBaseClass.LIST_STAT_NUM_COUNT)
                return nums.NumericLength();
            if (operation == ScriptBaseClass.LIST_STAT_STD_DEV)
                return nums.StdDev();
            if (operation == ScriptBaseClass.LIST_STAT_SUM)
                return nums.Sum();
            if (operation == ScriptBaseClass.LIST_STAT_SUM_SQUARES)
                return nums.SumSqrs();
            if (operation == ScriptBaseClass.LIST_STAT_GEOMETRIC_MEAN)
                return nums.GeometricMean();
            if (operation == ScriptBaseClass.LIST_STAT_HARMONIC_MEAN)
                return nums.HarmonicMean();
            return 0.0;
        }
        public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules)
        {
            if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;

            List<IEntity> parts = GetLinkPartsAndEntities(linknumber);

            foreach (IEntity part in parts)
                SetPrimParams(part, rules, m_allowOpenSimParams);
        }
 public void llNavigateTo(LSL_Vector point, LSL_List options)
 {
     List<Vector3> positions = new List<Vector3>() {point.ToVector3()};
     List<TravelMode> travelMode = new List<TravelMode>() {TravelMode.Walk};
     IBotManager botManager = World.RequestModuleInterface<IBotManager>();
     int flags = 0;
     if (options.Length > 0)
         flags |= options.GetLSLIntegerItem(0);
     if (botManager != null)
         botManager.SetBotMap(m_host.ParentEntity.UUID, positions, travelMode, flags, m_host.ParentEntity.OwnerID);
 }
        public void llSetPayPrice(int price, LSL_List quick_pay_buttons)
        {
            if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;
            m_host.ParentEntity.RootChild.PayPrice[0] = price;

            if (quick_pay_buttons.Data.Length > 0)
                m_host.ParentEntity.RootChild.PayPrice[1] = (LSL_Integer) quick_pay_buttons.Data[0];
            else
                m_host.ParentEntity.RootChild.PayPrice[1] = (LSL_Integer) (-2);
            if (quick_pay_buttons.Data.Length > 1)
                m_host.ParentEntity.RootChild.PayPrice[2] = (LSL_Integer) quick_pay_buttons.Data[1];
            else
                m_host.ParentEntity.RootChild.PayPrice[2] = (LSL_Integer) (-2);
            if (quick_pay_buttons.Data.Length > 2)
                m_host.ParentEntity.RootChild.PayPrice[3] = (LSL_Integer) quick_pay_buttons.Data[2];
            else
                m_host.ParentEntity.RootChild.PayPrice[3] = (LSL_Integer) (-2);
            if (quick_pay_buttons.Data.Length > 3)
                m_host.ParentEntity.RootChild.PayPrice[4] = (LSL_Integer) quick_pay_buttons.Data[3];
            else
                m_host.ParentEntity.RootChild.PayPrice[4] = (LSL_Integer) (-2);
        }
        public DateTime llParcelMediaCommandList(LSL_List commandList)
        {
            if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
                return DateTime.Now;

            // according to the docs, this command only works if script owner and land owner are the same
            // lets add estate owners and gods, too, and use the generic permission check.
            IParcelManagementModule parcelManagement = World.RequestModuleInterface<IParcelManagementModule>();
            if (parcelManagement != null)
            {
                ILandObject landObject = parcelManagement.GetLandObject(m_host.AbsolutePosition.X,
                                                                        m_host.AbsolutePosition.Y);
                if (landObject == null)
                    return DateTime.Now;
                if (!World.Permissions.CanEditParcel(m_host.OwnerID, landObject))
                    return DateTime.Now;

                bool update = false; // send a ParcelMediaUpdate (and possibly change the land's media URL)?
                byte loop = 0;

                LandData landData = landObject.LandData;
                string url = landData.MediaURL;
                string texture = landData.MediaID.ToString();
                bool autoAlign = landData.MediaAutoScale != 0;
                string mediaType = landData.MediaType;
                string description = landData.MediaDescription;
                int width = landData.MediaWidth;
                int height = landData.MediaHeight;
                float mediaLoopSet = landData.MediaLoopSet;

                ParcelMediaCommandEnum? commandToSend = null;
                float time = 0.0f; // default is from start

                IScenePresence presence = null;

                for (int i = 0; i < commandList.Data.Length; i++)
                {
                    int tmp = ((LSL_Integer) commandList.Data[i]).value;
                    ParcelMediaCommandEnum command = (ParcelMediaCommandEnum) tmp;
                    switch (command)
                    {
                        case ParcelMediaCommandEnum.Agent:
                            // we send only to one agent
                            if ((i + 1) < commandList.Length)
                            {
                                if (commandList.Data[i + 1] is LSL_String)
                                {
                                    UUID agentID;
                                    if (UUID.TryParse((LSL_String) commandList.Data[i + 1], out agentID))
                                    {
                                        presence = World.GetScenePresence(agentID);
                                    }
                                }
                                else ShoutError("The argument of PARCEL_MEDIA_COMMAND_AGENT must be a key");
                                ++i;
                            }
                            break;

                        case ParcelMediaCommandEnum.Loop:
                            loop = 1;
                            commandToSend = command;
                            update = true; //need to send the media update packet to set looping
                            break;

                        case ParcelMediaCommandEnum.LoopSet:
                            if ((i + 1) < commandList.Length)
                            {
                                if (commandList.Data[i + 1] is LSL_Float)
                                {
                                    mediaLoopSet = (float) ((LSL_Float) commandList.Data[i + 1]).value;
                                }
                                else ShoutError("The argument of PARCEL_MEDIA_COMMAND_LOOP_SET must be a float");
                                ++i;
                            }
                            commandToSend = command;
                            break;

                        case ParcelMediaCommandEnum.Play:
                            loop = 0;
                            commandToSend = command;
                            update = true; //need to send the media update packet to make sure it doesn't loop
                            break;

                        case ParcelMediaCommandEnum.Pause:
                        case ParcelMediaCommandEnum.Stop:
                        case ParcelMediaCommandEnum.Unload:
                            commandToSend = command;
                            break;

                        case ParcelMediaCommandEnum.Url:
                            if ((i + 1) < commandList.Length)
                            {
                                if (commandList.Data[i + 1] is LSL_String)
                                {
                                    url = (LSL_String) commandList.Data[i + 1];
                                    update = true;
                                }
                                else ShoutError("The argument of PARCEL_MEDIA_COMMAND_URL must be a string.");
                                ++i;
                            }
                            break;

                        case ParcelMediaCommandEnum.Texture:
                            if ((i + 1) < commandList.Length)
                            {
                                if (commandList.Data[i + 1] is LSL_String)
                                {
                                    texture = (LSL_String) commandList.Data[i + 1];
                                    update = true;
                                }
                                else
                                    ShoutError("The argument of PARCEL_MEDIA_COMMAND_TEXTURE must be a string or key.");
                                ++i;
                            }
                            break;

                        case ParcelMediaCommandEnum.Time:
                            if ((i + 1) < commandList.Length)
                            {
                                if (commandList.Data[i + 1] is LSL_Float)
                                {
                                    time = (float) (LSL_Float) commandList.Data[i + 1];
                                }
                                else ShoutError("The argument of PARCEL_MEDIA_COMMAND_TIME must be a float.");
                                ++i;
                            }
                            commandToSend = command;
                            break;

                        case ParcelMediaCommandEnum.AutoAlign:
                            if ((i + 1) < commandList.Length)
                            {
                                if (commandList.Data[i + 1] is LSL_Integer)
                                {
                                    autoAlign = (LSL_Integer) commandList.Data[i + 1];
                                    update = true;
                                }

                                else ShoutError("The argument of PARCEL_MEDIA_COMMAND_AUTO_ALIGN must be an integer.");
                                ++i;
                            }
                            break;

                        case ParcelMediaCommandEnum.Type:
                            if ((i + 1) < commandList.Length)
                            {
                                if (commandList.Data[i + 1] is LSL_String)
                                {
                                    mediaType = (LSL_String) commandList.Data[i + 1];
                                    update = true;
                                }
                                else ShoutError("The argument of PARCEL_MEDIA_COMMAND_TYPE must be a string.");
                                ++i;
                            }
                            break;

                        case ParcelMediaCommandEnum.Desc:
                            if ((i + 1) < commandList.Length)
                            {
                                if (commandList.Data[i + 1] is LSL_String)
                                {
                                    description = (LSL_String) commandList.Data[i + 1];
                                    update = true;
                                }
                                else ShoutError("The argument of PARCEL_MEDIA_COMMAND_DESC must be a string.");
                                ++i;
                            }
                            break;
                        case ParcelMediaCommandEnum.Size:
                            if ((i + 2) < commandList.Length)
                            {
                                if (commandList.Data[i + 1] is LSL_Integer)
                                {
                                    if (commandList.Data[i + 2] is LSL_Integer)
                                    {
                                        width = (LSL_Integer) commandList.Data[i + 1];
                                        height = (LSL_Integer) commandList.Data[i + 2];
                                        update = true;
                                    }
                                    else
                                        ShoutError(
                                            "The second argument of PARCEL_MEDIA_COMMAND_SIZE must be an integer.");
                                }
                                else ShoutError("The first argument of PARCEL_MEDIA_COMMAND_SIZE must be an integer.");
                                i += 2;
                            }
                            break;

                        default:
                            NotImplemented("llParcelMediaCommandList parameter not supported yet: " +
                                           Enum.Parse(typeof (ParcelMediaCommandEnum), commandList.Data[i].ToString()));
                            break;
                    } //end switch
                } //end for

                // if we didn't get a presence, we send to all and change the url
                // if we did get a presence, we only send to the agent specified, and *don't change the land settings*!

                // did something important change or do we only start/stop/pause?
                if (update)
                {
                    if (presence == null)
                    {
                        // we send to all
                        landData.MediaID = new UUID(texture);
                        landData.MediaAutoScale = autoAlign ? (byte) 1 : (byte) 0;
                        landData.MediaWidth = width;
                        landData.MediaHeight = height;
                        landData.MediaType = mediaType;
                        landData.MediaDescription = description;
                        landData.MediaLoop = loop == 1;
                        landData.MediaLoopSet = mediaLoopSet;

                        // do that one last, it will cause a ParcelPropertiesUpdate
                        landObject.SetMediaUrl(url);

                        // now send to all (non-child) agents
                        World.ForEachScenePresence(delegate(IScenePresence sp)
                                                       {
                                                           if (!sp.IsChildAgent &&
                                                               (sp.CurrentParcelUUID == landData.GlobalID))
                                                           {
                                                               sp.ControllingClient.SendParcelMediaUpdate(
                                                                   landData.MediaURL,
                                                                   landData.MediaID,
                                                                   landData.MediaAutoScale,
                                                                   mediaType,
                                                                   description,
                                                                   width, height,
                                                                   loop);
                                                           }
                                                       });
                    }
                    else if (!presence.IsChildAgent)
                    {
                        // we only send to one (root) agent
                        presence.ControllingClient.SendParcelMediaUpdate(url,
                                                                         new UUID(texture),
                                                                         autoAlign ? (byte) 1 : (byte) 0,
                                                                         mediaType,
                                                                         description,
                                                                         width, height,
                                                                         loop);
                    }
                }

                if (commandToSend != null)
                {
                    float ParamToSend = time;
                    if ((ParcelMediaCommandEnum) commandToSend == ParcelMediaCommandEnum.LoopSet)
                        ParamToSend = mediaLoopSet;

                    // the commandList contained a start/stop/... command, too
                    if (presence == null)
                    {
                        // send to all (non-child) agents
                        World.ForEachScenePresence(delegate(IScenePresence sp)
                                                       {
                                                           if (!sp.IsChildAgent)
                                                           {
                                                               sp.ControllingClient.SendParcelMediaCommand(
                                                                   landData.Flags,
                                                                   (ParcelMediaCommandEnum) commandToSend,
                                                                   ParamToSend);
                                                           }
                                                       });
                    }
                    else if (!presence.IsChildAgent)
                    {
                        presence.ControllingClient.SendParcelMediaCommand(landData.Flags,
                                                                          (ParcelMediaCommandEnum) commandToSend,
                                                                          ParamToSend);
                    }
                }
            }
            return PScriptSleep(2000);
        }
        public LSL_Integer llSetPrimMediaParams(LSL_Integer face, LSL_List rules)
        {
            ScriptSleep(1000);

            // LSL Spec http://wiki.secondlife.com/wiki/LlSetPrimMediaParams says to fail silently if face is invalid
            // Assuming silently fail means sending back LSL_STATUS_OK.  Ideally, need to check this.
            // Don't perform the media check directly
            if (face < 0 || face > m_host.GetNumberOfSides() - 1)
                return ScriptBaseClass.LSL_STATUS_OK;
            return SetPrimMediaParams(m_host, face, rules);
        }
        public void llLinkParticleSystem(int linknumber, LSL_List rules)
        {
            if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID)) return;

            List<ISceneChildEntity> parts = GetLinkParts(linknumber);

            foreach (var part in parts)
            {
                SetParticleSystem(part, rules);
            }
        }