/// <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 <src> into the /// list designated by <dest> such that the first /// new element has the index specified by <index> /// </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); } }