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 '<' '>' 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); }
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); }
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); }
// <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); }