From 1a47ff8094ee414a47aebd310826906d89428a09 Mon Sep 17 00:00:00 2001 From: Teravus Ovares Date: Fri, 30 May 2008 12:27:06 +0000 Subject: * This is Melanie's XEngine script engine. I've not tested this real well, however, it's confirmed to compile and OpenSimulator to run successfully without this script engine active. --- .../ScriptEngine/XEngine/AsyncCommandManager.cs | 270 + .../XEngine/AsyncCommandPlugins/Dataserver.cs | 127 + .../XEngine/AsyncCommandPlugins/Eventstream.cs | 76 + .../XEngine/AsyncCommandPlugins/HttpRequest.cs | 89 + .../XEngine/AsyncCommandPlugins/Listener.cs | 91 + .../XEngine/AsyncCommandPlugins/SensorRepeat.cs | 391 ++ .../XEngine/AsyncCommandPlugins/Timer.cs | 163 + .../XEngine/AsyncCommandPlugins/XmlRequest.cs | 115 + OpenSim/Region/ScriptEngine/XEngine/Compiler.cs | 515 ++ .../Region/ScriptEngine/XEngine/EventManager.cs | 293 + OpenSim/Region/ScriptEngine/XEngine/Executor.cs | 136 + .../Region/ScriptEngine/XEngine/ExecutorBase.cs | 181 + .../Region/ScriptEngine/XEngine/LSL2CSConverter.cs | 363 ++ .../ScriptEngine/XEngine/LSL_ScriptCommands.cs | 6474 ++++++++++++++++++++ .../ScriptEngine/XEngine/OSSL_ScriptCommands.cs | 553 ++ .../XEngine/Script/AssemblyResolver.cs | 65 + .../XEngine/Script/BuiltIn_Commands_BaseClass.cs | 2393 ++++++++ .../XEngine/Script/ILSL_ScriptCommands.cs | 653 ++ .../XEngine/Script/IOSSL_ScriptCommands.cs | 68 + .../Region/ScriptEngine/XEngine/Script/IScript.cs | 46 + .../ScriptEngine/XEngine/Script/LSL_Types.cs | 1411 +++++ OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 1435 +++++ 22 files changed, 15908 insertions(+) create mode 100644 OpenSim/Region/ScriptEngine/XEngine/AsyncCommandManager.cs create mode 100644 OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/Dataserver.cs create mode 100644 OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/Eventstream.cs create mode 100644 OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/HttpRequest.cs create mode 100644 OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/Listener.cs create mode 100644 OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/SensorRepeat.cs create mode 100644 OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/Timer.cs create mode 100644 OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/XmlRequest.cs create mode 100644 OpenSim/Region/ScriptEngine/XEngine/Compiler.cs create mode 100644 OpenSim/Region/ScriptEngine/XEngine/EventManager.cs create mode 100644 OpenSim/Region/ScriptEngine/XEngine/Executor.cs create mode 100644 OpenSim/Region/ScriptEngine/XEngine/ExecutorBase.cs create mode 100644 OpenSim/Region/ScriptEngine/XEngine/LSL2CSConverter.cs create mode 100644 OpenSim/Region/ScriptEngine/XEngine/LSL_ScriptCommands.cs create mode 100644 OpenSim/Region/ScriptEngine/XEngine/OSSL_ScriptCommands.cs create mode 100644 OpenSim/Region/ScriptEngine/XEngine/Script/AssemblyResolver.cs create mode 100644 OpenSim/Region/ScriptEngine/XEngine/Script/BuiltIn_Commands_BaseClass.cs create mode 100644 OpenSim/Region/ScriptEngine/XEngine/Script/ILSL_ScriptCommands.cs create mode 100644 OpenSim/Region/ScriptEngine/XEngine/Script/IOSSL_ScriptCommands.cs create mode 100644 OpenSim/Region/ScriptEngine/XEngine/Script/IScript.cs create mode 100644 OpenSim/Region/ScriptEngine/XEngine/Script/LSL_Types.cs create mode 100644 OpenSim/Region/ScriptEngine/XEngine/XEngine.cs (limited to 'OpenSim/Region/ScriptEngine/XEngine') diff --git a/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandManager.cs b/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandManager.cs new file mode 100644 index 0000000..4ec7916 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandManager.cs @@ -0,0 +1,270 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Threading; +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.ScriptEngine.XEngine.AsyncCommandPlugins; +using Timer=OpenSim.Region.ScriptEngine.XEngine.AsyncCommandPlugins.Timer; +using Dataserver=OpenSim.Region.ScriptEngine.XEngine.AsyncCommandPlugins.Dataserver; + +namespace OpenSim.Region.ScriptEngine.XEngine +{ + /// + /// Handles LSL commands that takes long time and returns an event, for example timers, HTTP requests, etc. + /// + public class AsyncCommandManager + { + private static Thread cmdHandlerThread; + private static int cmdHandlerThreadCycleSleepms; + + public XEngine m_ScriptEngine; + + public Dataserver m_Dataserver; + public Timer m_Timer; + public HttpRequest m_HttpRequest; + public Listener m_Listener; + public SensorRepeat m_SensorRepeat; + public XmlRequest m_XmlRequest; + + public AsyncCommandManager(XEngine _ScriptEngine) + { + m_ScriptEngine = _ScriptEngine; + ReadConfig(); + + // Create instances of all plugins + m_Dataserver = new Dataserver(this); + m_Timer = new Timer(this); + m_HttpRequest = new HttpRequest(this); + m_Listener = new Listener(this); + m_SensorRepeat = new SensorRepeat(this); + m_XmlRequest = new XmlRequest(this); + + StartThread(); + } + + private static void StartThread() + { + if (cmdHandlerThread == null) + { + // Start the thread that will be doing the work + cmdHandlerThread = new Thread(CmdHandlerThreadLoop); + cmdHandlerThread.Name = "AsyncLSLCmdHandlerThread"; + cmdHandlerThread.Priority = ThreadPriority.BelowNormal; + cmdHandlerThread.IsBackground = true; + cmdHandlerThread.Start(); + ThreadTracker.Add(cmdHandlerThread); + } + } + + public void ReadConfig() + { + cmdHandlerThreadCycleSleepms = m_ScriptEngine.ScriptConfigSource.GetInt("AsyncLLCommandLoopms", 100); + } + + ~AsyncCommandManager() + { + // Shut down thread + try + { + if (cmdHandlerThread != null) + { + if (cmdHandlerThread.IsAlive == true) + { + cmdHandlerThread.Abort(); + //cmdHandlerThread.Join(); + } + } + } + catch + { + } + } + + private static void CmdHandlerThreadLoop() + { + while (true) + { + try + { + while (true) + { + Thread.Sleep(cmdHandlerThreadCycleSleepms); + + foreach (XEngine xe in XEngine.ScriptEngines) + { + xe.m_ASYNCLSLCommandManager.DoOneCmdHandlerPass(); + } + } + } + catch + { + } + } + } + + internal void DoOneCmdHandlerPass() + { + // Check timers + m_Timer.CheckTimerEvents(); + // Check HttpRequests + m_HttpRequest.CheckHttpRequests(); + // Check XMLRPCRequests + m_XmlRequest.CheckXMLRPCRequests(); + // Check Listeners + m_Listener.CheckListeners(); + // Check Sensors + m_SensorRepeat.CheckSenseRepeaterEvents(); + // Check dataserver + m_Dataserver.ExpireRequests(); + } + + /// + /// Remove a specific script (and all its pending commands) + /// + /// + /// + public void RemoveScript(uint localID, LLUUID itemID) + { + // Remove a specific script + + // Remove dataserver events + m_Dataserver.RemoveEvents(localID, itemID); + + // Remove from: Timers + m_Timer.UnSetTimerEvents(localID, itemID); + + // Remove from: HttpRequest + IHttpRequests iHttpReq = + m_ScriptEngine.World.RequestModuleInterface(); + iHttpReq.StopHttpRequest(localID, itemID); + + IWorldComm comms = m_ScriptEngine.World.RequestModuleInterface(); + comms.DeleteListener(itemID); + + IXMLRPC xmlrpc = m_ScriptEngine.World.RequestModuleInterface(); + xmlrpc.DeleteChannels(itemID); + xmlrpc.CancelSRDRequests(itemID); + + // Remove Sensors + m_SensorRepeat.UnSetSenseRepeaterEvents(localID, itemID); + + } + + public Object[] GetSerializationData(LLUUID itemID) + { + List data = new List(); + + Object[] listeners=m_Listener.GetSerializationData(itemID); + if(listeners.Length > 0) + { + data.Add("listener"); + data.Add(listeners.Length); + data.AddRange(listeners); + } + + Object[] timers=m_Timer.GetSerializationData(itemID); + if(timers.Length > 0) + { + data.Add("timer"); + data.Add(timers.Length); + data.AddRange(timers); + } + + Object[] sensors=m_SensorRepeat.GetSerializationData(itemID); + if(sensors.Length > 0) + { + data.Add("sensor"); + data.Add(sensors.Length); + data.AddRange(sensors); + } + + return data.ToArray(); + } + + public void CreateFromData(uint localID, LLUUID itemID, LLUUID hostID, + Object[] data) + { + int idx=0; + int len; + + while(idx < data.Length) + { + string type = data[idx].ToString(); + len = (int)data[idx+1]; + idx+=2; + + if(len > 0) + { + Object[] item = new Object[len]; + Array.Copy(data, idx, item, 0, len); + + idx+=len; + + switch(type) + { + case "listener": + m_Listener.CreateFromData(localID, itemID, hostID, + item); + break; + case "timer": + m_Timer.CreateFromData(localID, itemID, hostID, item); + break; + case "sensor": + m_SensorRepeat.CreateFromData(localID, itemID, hostID, + item); + break; + } + } + } + } + + #region Check llRemoteData channels + + + #endregion + + #region Check llListeners + + + #endregion + + /// + /// If set to true then threads and stuff should try to make a graceful exit + /// + public bool PleaseShutdown + { + get { return _PleaseShutdown; } + set { _PleaseShutdown = value; } + } + private bool _PleaseShutdown = false; + } +} diff --git a/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/Dataserver.cs b/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/Dataserver.cs new file mode 100644 index 0000000..794a015 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/Dataserver.cs @@ -0,0 +1,127 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using libsecondlife; +using OpenSim.Region.ScriptEngine.XEngine.Script; + +namespace OpenSim.Region.ScriptEngine.XEngine.AsyncCommandPlugins +{ + public class Dataserver + { + public AsyncCommandManager m_CmdManager; + + private Dictionary DataserverRequests = + new Dictionary(); + + public Dataserver(AsyncCommandManager CmdManager) + { + m_CmdManager = CmdManager; + } + + private class DataserverRequest + { + public uint localID; + public LLUUID itemID; + + public LLUUID ID; + public string handle; + + public DateTime startTime; + } + + public LLUUID RegisterRequest(uint localID, LLUUID itemID, + string identifier) + { + lock(DataserverRequests) + { + if(DataserverRequests.ContainsKey(identifier)) + return LLUUID.Zero; + + DataserverRequest ds = new DataserverRequest(); + + ds.localID = localID; + ds.itemID = itemID; + + ds.ID = LLUUID.Random(); + ds.handle = identifier; + + ds.startTime = DateTime.Now; + + DataserverRequests[identifier]=ds; + + return ds.ID; + } + } + + public void DataserverReply(string identifier, string reply) + { + DataserverRequest ds; + + lock(DataserverRequests) + { + if(!DataserverRequests.ContainsKey(identifier)) + return; + + ds=DataserverRequests[identifier]; + DataserverRequests.Remove(identifier); + } + + m_CmdManager.m_ScriptEngine.PostObjectEvent(ds.localID, + new XEventParams( "dataserver", new Object[] + { new LSL_Types.LSLString(ds.ID.ToString()), + new LSL_Types.LSLString(reply)}, + new XDetectParams[0])); + } + + public void RemoveEvents(uint localID, LLUUID itemID) + { + lock(DataserverRequests) + { + foreach (DataserverRequest ds in new List(DataserverRequests.Values)) + { + if(ds.itemID == itemID) + DataserverRequests.Remove(ds.handle); + } + } + } + + public void ExpireRequests() + { + lock(DataserverRequests) + { + foreach (DataserverRequest ds in new List(DataserverRequests.Values)) + { + if(ds.startTime > DateTime.Now.AddSeconds(30)) + DataserverRequests.Remove(ds.handle); + } + } + } + } +} diff --git a/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/Eventstream.cs b/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/Eventstream.cs new file mode 100644 index 0000000..9112b9c --- /dev/null +++ b/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/Eventstream.cs @@ -0,0 +1,76 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using libsecondlife; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.ScriptEngine.XEngine.AsyncCommandPlugins +{ + public class Eventstream + { + public AsyncCommandManager m_CmdManager; + + private class Event + { + public uint LocalID; + public string EventName; + public Dictionary DetectParams; + } + + private Dictionary > m_Events = + new Dictionary >(); + + public Eventstream(AsyncCommandManager CmdManager) + { + m_CmdManager = CmdManager; + } + + public void AddObjectEvent(uint localID, string eventName, XDetectParams det) + { + SceneObjectPart part = m_CmdManager.m_ScriptEngine.World. + GetSceneObjectPart(localID); + + if(part == null) // Can't register events for non-prims + return; + + if(!part.ContainsScripts()) + return; + + } + + public void RemoveObjectEvent(uint localID, string eventName, LLUUID id) + { + } + + public void RemoveObjects(uint localID) + { + } + } +} diff --git a/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/HttpRequest.cs b/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/HttpRequest.cs new file mode 100644 index 0000000..977e3f9 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/HttpRequest.cs @@ -0,0 +1,89 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Modules.Scripting.HttpRequest; +using OpenSim.Region.ScriptEngine.XEngine.Script; + +namespace OpenSim.Region.ScriptEngine.XEngine.AsyncCommandPlugins +{ + public class HttpRequest + { + public AsyncCommandManager m_CmdManager; + + public HttpRequest(AsyncCommandManager CmdManager) + { + m_CmdManager = CmdManager; + } + + public void CheckHttpRequests() + { + if (m_CmdManager.m_ScriptEngine.World == null) + return; + + IHttpRequests iHttpReq = + m_CmdManager.m_ScriptEngine.World.RequestModuleInterface(); + + HttpRequestClass httpInfo = null; + + if (iHttpReq != null) + httpInfo = iHttpReq.GetNextCompletedRequest(); + + while (httpInfo != null) + { + //m_ScriptEngine.Log.Info("[AsyncLSL]:" + httpInfo.response_body + httpInfo.status); + + // Deliver data to prim's remote_data handler + // + // TODO: Returning null for metadata, since the lsl function + // only returns the byte for HTTP_BODY_TRUNCATED, which is not + // implemented here yet anyway. Should be fixed if/when maxsize + // is supported + + iHttpReq.RemoveCompletedRequest(httpInfo.reqID); + + object[] resobj = new object[] + { + new LSL_Types.LSLString(httpInfo.reqID.ToString()), + new LSL_Types.LSLInteger(httpInfo.status), + new LSL_Types.list(), + new LSL_Types.LSLString(httpInfo.response_body) + }; + + foreach (XEngine xe in XEngine.ScriptEngines) + { + if(xe.PostObjectEvent(httpInfo.localID, + new XEventParams("http_response", + resobj, new XDetectParams[0]))) + break; + } + httpInfo = iHttpReq.GetNextCompletedRequest(); + } + } + } +} diff --git a/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/Listener.cs b/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/Listener.cs new file mode 100644 index 0000000..1144c00 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/Listener.cs @@ -0,0 +1,91 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using libsecondlife; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Modules.Scripting.WorldComm; +using OpenSim.Region.ScriptEngine.XEngine.Script; + +namespace OpenSim.Region.ScriptEngine.XEngine.AsyncCommandPlugins +{ + public class Listener + { + // private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + public AsyncCommandManager m_CmdManager; + + public Listener(AsyncCommandManager CmdManager) + { + m_CmdManager = CmdManager; + } + + public void CheckListeners() + { + if (m_CmdManager.m_ScriptEngine.World == null) + return; + IWorldComm comms = m_CmdManager.m_ScriptEngine.World.RequestModuleInterface(); + + if (comms != null) + { + while (comms.HasMessages()) + { + ListenerInfo lInfo = comms.GetNextMessage(); + + //Deliver data to prim's listen handler + object[] resobj = new object[] + { + new LSL_Types.LSLInteger(lInfo.GetChannel()), + new LSL_Types.LSLString(lInfo.GetName()), + new LSL_Types.LSLString(lInfo.GetID().ToString()), + new LSL_Types.LSLString(lInfo.GetMessage()) + }; + + m_CmdManager.m_ScriptEngine.PostScriptEvent( + lInfo.GetItemID(), new XEventParams( + "listen", resobj, + new XDetectParams[0])); + } + } + } + + public Object[] GetSerializationData(LLUUID itemID) + { + IWorldComm comms = m_CmdManager.m_ScriptEngine.World.RequestModuleInterface(); + + return comms.GetSerializationData(itemID); + } + + public void CreateFromData(uint localID, LLUUID itemID, LLUUID hostID, + Object[] data) + { + IWorldComm comms = m_CmdManager.m_ScriptEngine.World.RequestModuleInterface(); + + comms.CreateFromData(localID, itemID, hostID, data); + } + } +} diff --git a/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/SensorRepeat.cs new file mode 100644 index 0000000..5a87bb0 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/SensorRepeat.cs @@ -0,0 +1,391 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Region.Environment.Scenes; +using OpenSim.Region.ScriptEngine.XEngine.Script; + +namespace OpenSim.Region.ScriptEngine.XEngine.AsyncCommandPlugins +{ + public class SensorRepeat + { + public AsyncCommandManager m_CmdManager; + + public SensorRepeat(AsyncCommandManager CmdManager) + { + m_CmdManager = CmdManager; + } + + public Dictionary> SenseEvents = + new Dictionary>(); + private Object SenseLock = new Object(); + + // + // SenseRepeater and Sensors + // + private class SenseRepeatClass + { + public uint localID; + public LLUUID itemID; + public double interval; + public DateTime next; + + public string name; + public LLUUID keyID; + public int type; + public double range; + public double arc; + public SceneObjectPart host; + } + + private List SenseRepeaters = new List(); + private object SenseRepeatListLock = new object(); + + public void SetSenseRepeatEvent(uint m_localID, LLUUID m_itemID, + string name, LLUUID keyID, int type, double range, double arc, double sec, SceneObjectPart host) + { + Console.WriteLine("SetSensorEvent"); + + // Always remove first, in case this is a re-set + UnSetSenseRepeaterEvents(m_localID, m_itemID); + if (sec == 0) // Disabling timer + return; + + // Add to timer + SenseRepeatClass ts = new SenseRepeatClass(); + ts.localID = m_localID; + ts.itemID = m_itemID; + ts.interval = sec; + ts.name = name; + ts.keyID = keyID; + ts.type = type; + ts.range = range; + ts.arc = arc; + ts.host = host; + + ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval); + lock (SenseRepeatListLock) + { + SenseRepeaters.Add(ts); + } + } + + public void UnSetSenseRepeaterEvents(uint m_localID, LLUUID m_itemID) + { + // Remove from timer + lock (SenseRepeatListLock) + { + List NewSensors = new List(); + foreach (SenseRepeatClass ts in SenseRepeaters) + { + if (ts.localID != m_localID && ts.itemID != m_itemID) + { + NewSensors.Add(ts); + } + } + SenseRepeaters.Clear(); + SenseRepeaters = NewSensors; + } + } + + public void CheckSenseRepeaterEvents() + { + // Nothing to do here? + if (SenseRepeaters.Count == 0) + return; + + lock (SenseRepeatListLock) + { + // Go through all timers + foreach (SenseRepeatClass ts in SenseRepeaters) + { + // Time has passed? + if (ts.next.ToUniversalTime() < DateTime.Now.ToUniversalTime()) + { + SensorSweep(ts); + // set next interval + ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval); + } + } + } // lock + } + + public void SenseOnce(uint m_localID, LLUUID m_itemID, + string name, LLUUID keyID, int type, + double range, double arc, SceneObjectPart host) + { + // Add to timer + SenseRepeatClass ts = new SenseRepeatClass(); + ts.localID = m_localID; + ts.itemID = m_itemID; + ts.interval = 0; + ts.name = name; + ts.keyID = keyID; + ts.type = type; + ts.range = range; + ts.arc = arc; + ts.host = host; + SensorSweep(ts); + } + + public LSL_Types.list GetSensorList(uint m_localID, LLUUID m_itemID) + { + lock (SenseLock) + { + Dictionary Obj = null; + if (!SenseEvents.TryGetValue(m_localID, out Obj)) + { + m_CmdManager.m_ScriptEngine.Log.Info("[AsyncLSL]: GetSensorList missing localID: " + m_localID); + return null; + } + lock (Obj) + { + // Get script + LSL_Types.list SenseList = null; + if (!Obj.TryGetValue(m_itemID, out SenseList)) + { + m_CmdManager.m_ScriptEngine.Log.Info("[AsyncLSL]: GetSensorList missing itemID: " + m_itemID); + return null; + } + return SenseList; + } + } + } + + private void SensorSweep(SenseRepeatClass ts) + { + //m_ScriptEngine.Log.Info("[AsyncLSL]:Enter SensorSweep"); + SceneObjectPart SensePoint = ts.host; + + if (SensePoint == null) + { + //m_ScriptEngine.Log.Info("[AsyncLSL]: Enter SensorSweep (SensePoint == null) for "+ts.itemID.ToString()); + return; + } + //m_ScriptEngine.Log.Info("[AsyncLSL]: Enter SensorSweep Scan"); + + LLVector3 sensorPos = SensePoint.AbsolutePosition; + LLVector3 regionPos = new LLVector3(m_CmdManager.m_ScriptEngine.World.RegionInfo.RegionLocX * Constants.RegionSize, m_CmdManager.m_ScriptEngine.World.RegionInfo.RegionLocY * Constants.RegionSize, 0); + LLVector3 fromRegionPos = sensorPos + regionPos; + + LLQuaternion q = SensePoint.RotationOffset; + LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W); + LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r); + double mag_fwd = LSL_Types.Vector3.Mag(forward_dir); + + // Here we should do some smart culling ... + // math seems quicker than strings so try that first + LSL_Types.list SensedObjects = new LSL_Types.list(); + LSL_Types.Vector3 ZeroVector = new LSL_Types.Vector3(0, 0, 0); + + foreach (EntityBase ent in m_CmdManager.m_ScriptEngine.World.Entities.Values) + { + LLVector3 toRegionPos = ent.AbsolutePosition + regionPos; + double dis = Math.Abs((double)Util.GetDistanceTo(toRegionPos, fromRegionPos)); + if (dis <= ts.range) + { + // In Range, is it the right Type ? + int objtype = 0; + + if (m_CmdManager.m_ScriptEngine.World.GetScenePresence(ent.UUID) != null) objtype |= 0x01; // actor + if (ent.Velocity.Equals(ZeroVector)) + objtype |= 0x04; // passive non-moving + else + objtype |= 0x02; // active moving + if (ent is IScript) objtype |= 0x08; // Scripted. It COULD have one hidden ... + + if (((ts.type & objtype) != 0) || ((ts.type & objtype) == ts.type)) + { + // docs claim AGENT|ACTIVE should find agent objects OR active objects + // so the bitwise AND with object type should be non-zero + + // Right type too, what about the other params , key and name ? + bool keep = true; + if (ts.arc < Math.PI) + { + // not omni-directional. Can you see it ? + // vec forward_dir = llRot2Fwd(llGetRot()) + // vec obj_dir = toRegionPos-fromRegionPos + // dot=dot(forward_dir,obj_dir) + // mag_fwd = mag(forward_dir) + // mag_obj = mag(obj_dir) + // ang = acos(dot /(mag_fwd*mag_obj)) + double ang_obj = 0; + try + { + LLVector3 diff = toRegionPos - fromRegionPos; + LSL_Types.Vector3 obj_dir = new LSL_Types.Vector3(diff.X, diff.Y, diff.Z); + double dot = LSL_Types.Vector3.Dot(forward_dir, obj_dir); + double mag_obj = LSL_Types.Vector3.Mag(obj_dir); + ang_obj = Math.Acos(dot / (mag_fwd * mag_obj)); + } + catch + { + } + + if (ang_obj > ts.arc) keep = false; + } + + if (keep && (ts.keyID != LLUUID.Zero) && (ts.keyID != ent.UUID)) + { + keep = false; + } + + if (keep && (ts.name.Length > 0)) + { + string avatarname=null; + string objectname=null; + string entname =ent.Name; + + // try avatar username surname + UserProfileData profile = m_CmdManager.m_ScriptEngine.World.CommsManager.UserService.GetUserProfile(ent.UUID); + if (profile != null) + { + avatarname = profile.FirstName + " " + profile.SurName; + } + // try an scene object + SceneObjectPart SOP = m_CmdManager.m_ScriptEngine.World.GetSceneObjectPart(ent.UUID); + if (SOP != null) + { + objectname = SOP.Name; + } + + if ((ts.name != entname) && (ts.name != avatarname) && (ts.name != objectname)) + { + keep = false; + } + } + + if (keep == true) SensedObjects.Add(ent.UUID); + } + } + } + //m_ScriptEngine.Log.Info("[AsyncLSL]: Enter SensorSweep SenseLock"); + + lock (SenseLock) + { + // Create object if it doesn't exist + if (SenseEvents.ContainsKey(ts.localID) == false) + { + SenseEvents.Add(ts.localID, new Dictionary()); + } + // clear if previous traces exist + Dictionary Obj; + SenseEvents.TryGetValue(ts.localID, out Obj); + if (Obj.ContainsKey(ts.itemID) == true) + Obj.Remove(ts.itemID); + + // note list may be zero length + Obj.Add(ts.itemID, SensedObjects); + + if (SensedObjects.Length == 0) + { + // send a "no_sensor" + // Add it to queue + m_CmdManager.m_ScriptEngine.PostScriptEvent(ts.itemID, + new XEventParams("no_sensor", new Object[0], + new XDetectParams[0])); + } + else + { + XDetectParams[] detect = + new XDetectParams[SensedObjects.Length]; + + int idx; + for(idx = 0 ; idx < SensedObjects.Length; idx++) + { + detect[idx].Key=(LLUUID)(SensedObjects.Data[idx]); + } + + m_CmdManager.m_ScriptEngine.PostScriptEvent(ts.itemID, + new XEventParams("sensor", + new Object[] { + new LSL_Types.LSLInteger(SensedObjects.Length) }, + detect)); + } + } + } + + public Object[] GetSerializationData(LLUUID itemID) + { + List data = new List(); + + foreach (SenseRepeatClass ts in SenseRepeaters) + { + if(ts.itemID == itemID) + { + data.Add(ts.interval); + data.Add(ts.name); + data.Add(ts.keyID); + data.Add(ts.type); + data.Add(ts.range); + data.Add(ts.arc); + } + } + return data.ToArray(); + } + + public void CreateFromData(uint localID, LLUUID itemID, LLUUID objectID, + Object[] data) + { + SceneObjectPart part = + m_CmdManager.m_ScriptEngine.World.GetSceneObjectPart( + objectID); + + if(part == null) + return; + + int idx=0; + + while(idx < data.Length) + { + SenseRepeatClass ts = new SenseRepeatClass(); + + ts.localID = localID; + ts.itemID = itemID; + + ts.interval = (double)data[idx]; + ts.name = (string)data[idx+1]; + ts.keyID = (LLUUID)data[idx+2]; + ts.type = (int)data[idx+3]; + ts.range = (double)data[idx+4]; + ts.arc = (double)data[idx+5]; + ts.host = part; + + ts.next = + DateTime.Now.ToUniversalTime().AddSeconds(ts.interval); + + SenseRepeaters.Add(ts); + idx += 6; + } + } + + } +} diff --git a/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/Timer.cs b/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/Timer.cs new file mode 100644 index 0000000..09a5818 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/Timer.cs @@ -0,0 +1,163 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using libsecondlife; + +namespace OpenSim.Region.ScriptEngine.XEngine.AsyncCommandPlugins +{ + public class Timer + { + public AsyncCommandManager m_CmdManager; + + public Timer(AsyncCommandManager CmdManager) + { + m_CmdManager = CmdManager; + } + + // + // TIMER + // + private class TimerClass + { + public uint localID; + public LLUUID itemID; + //public double interval; + public long interval; + //public DateTime next; + public long next; + } + + private List Timers = new List(); + private object TimerListLock = new object(); + + public void SetTimerEvent(uint m_localID, LLUUID m_itemID, double sec) + { + Console.WriteLine("SetTimerEvent"); + + // Always remove first, in case this is a re-set + UnSetTimerEvents(m_localID, m_itemID); + if (sec == 0) // Disabling timer + return; + + // Add to timer + TimerClass ts = new TimerClass(); + ts.localID = m_localID; + ts.itemID = m_itemID; + ts.interval = Convert.ToInt64(sec * 10000000); // How many 100 nanoseconds (ticks) should we wait + // 2193386136332921 ticks + // 219338613 seconds + + //ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval); + ts.next = DateTime.Now.Ticks + ts.interval; + lock (TimerListLock) + { + Timers.Add(ts); + } + } + + public void UnSetTimerEvents(uint m_localID, LLUUID m_itemID) + { + // Remove from timer + lock (TimerListLock) + { + foreach (TimerClass ts in new ArrayList(Timers)) + { + if (ts.localID == m_localID && ts.itemID == m_itemID) + Timers.Remove(ts); + } + } + } + + public void CheckTimerEvents() + { + // Nothing to do here? + if (Timers.Count == 0) + return; + + lock (TimerListLock) + { + // Go through all timers + foreach (TimerClass ts in Timers) + { + // Time has passed? + if (ts.next < DateTime.Now.Ticks) + { + // Console.WriteLine("Time has passed: Now: " + DateTime.Now.Ticks + ", Passed: " + ts.next); + // Add it to queue + m_CmdManager.m_ScriptEngine.PostScriptEvent(ts.itemID, + new XEventParams("timer", new Object[0], + new XDetectParams[0])); + // set next interval + + //ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval); + ts.next = DateTime.Now.Ticks + ts.interval; + } + } + } + } + + public Object[] GetSerializationData(LLUUID itemID) + { + List data = new List(); + + lock (TimerListLock) + { + foreach (TimerClass ts in Timers) + { + if(ts.itemID == itemID) + { + data.Add(ts.interval); + data.Add(ts.next-DateTime.Now.Ticks); + } + } + } + return data.ToArray(); + } + + public void CreateFromData(uint localID, LLUUID itemID, LLUUID objectID, + Object[] data) + { + int idx=0; + + while(idx < data.Length) + { + TimerClass ts = new TimerClass(); + + ts.localID = localID; + ts.itemID = itemID; + ts.interval = (long)data[idx]; + ts.next = DateTime.Now.Ticks + (long)data[idx+1]; + idx += 2; + + Timers.Add(ts); + } + } + } +} diff --git a/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/XmlRequest.cs b/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/XmlRequest.cs new file mode 100644 index 0000000..2714d11 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/XmlRequest.cs @@ -0,0 +1,115 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Modules.Scripting.XMLRPC; +using OpenSim.Region.ScriptEngine.XEngine.Script; + +namespace OpenSim.Region.ScriptEngine.XEngine.AsyncCommandPlugins +{ + public class XmlRequest + { + public AsyncCommandManager m_CmdManager; + + public XmlRequest(AsyncCommandManager CmdManager) + { + m_CmdManager = CmdManager; + } + + public void CheckXMLRPCRequests() + { + if (m_CmdManager.m_ScriptEngine.World == null) + return; + + IXMLRPC xmlrpc = m_CmdManager.m_ScriptEngine.World.RequestModuleInterface(); + + if (xmlrpc != null) + { + RPCRequestInfo rInfo = xmlrpc.GetNextCompletedRequest(); + + while (rInfo != null) + { + xmlrpc.RemoveCompletedRequest(rInfo.GetMessageID()); + + //Deliver data to prim's remote_data handler + object[] resobj = new object[] + { + new LSL_Types.LSLInteger(2), + new LSL_Types.LSLString( + rInfo.GetChannelKey().ToString()), + new LSL_Types.LSLString( + rInfo.GetMessageID().ToString()), + new LSL_Types.LSLString(String.Empty), + new LSL_Types.LSLInteger(rInfo.GetIntValue()), + new LSL_Types.LSLString(rInfo.GetStrVal()) + }; + + foreach (XEngine xe in XEngine.ScriptEngines) + { + if(xe.PostScriptEvent( + rInfo.GetItemID(), new XEventParams( + "remote_data", resobj, + new XDetectParams[0]))) + break; + } + + rInfo = xmlrpc.GetNextCompletedRequest(); + } + + SendRemoteDataRequest srdInfo = xmlrpc.GetNextCompletedSRDRequest(); + + while (srdInfo != null) + { + xmlrpc.RemoveCompletedSRDRequest(srdInfo.GetReqID()); + + //Deliver data to prim's remote_data handler + object[] resobj = new object[] + { + new LSL_Types.LSLInteger(3), + new LSL_Types.LSLString(srdInfo.channel.ToString()), + new LSL_Types.LSLString(srdInfo.GetReqID().ToString()), + new LSL_Types.LSLString(String.Empty), + new LSL_Types.LSLInteger(srdInfo.idata), + new LSL_Types.LSLString(srdInfo.sdata) + }; + + foreach (XEngine xe in XEngine.ScriptEngines) + { + if(xe.PostScriptEvent( + srdInfo.m_itemID, new XEventParams( + "remote_data", resobj, + new XDetectParams[0]))) + break; + } + + srdInfo = xmlrpc.GetNextCompletedSRDRequest(); + } + } + } + } +} diff --git a/OpenSim/Region/ScriptEngine/XEngine/Compiler.cs b/OpenSim/Region/ScriptEngine/XEngine/Compiler.cs new file mode 100644 index 0000000..980d9e6 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/XEngine/Compiler.cs @@ -0,0 +1,515 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.CodeDom.Compiler; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using Microsoft.CSharp; +using Microsoft.JScript; +using Microsoft.VisualBasic; +using OpenSim.Region.Environment.Interfaces; + +namespace OpenSim.Region.ScriptEngine.XEngine +{ + public class Compiler + { + private static readonly log4net.ILog m_log + = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + // * Uses "LSL2Converter" to convert LSL to C# if necessary. + // * Compiles C#-code into an assembly + // * Returns assembly name ready for AppDomain load. + // + // Assembly is compiled using LSL_BaseClass as base. Look at debug C# code file created when LSL script is compiled for full details. + // + + internal enum enumCompileType + { + lsl = 0, + cs = 1, + vb = 2, + js = 3 + } + + /// + /// This contains number of lines WE use for header when compiling script. User will get error in line x-LinesToRemoveOnError when error occurs. + /// + public int LinesToRemoveOnError = 3; + private enumCompileType DefaultCompileLanguage; + private bool WriteScriptSourceToDebugFile; + private bool CompileWithDebugInformation; + private Dictionary AllowedCompilers = new Dictionary(StringComparer.CurrentCultureIgnoreCase); + private Dictionary LanguageMapping = new Dictionary(StringComparer.CurrentCultureIgnoreCase); + + private string FilePrefix; + private string ScriptEnginesPath = "ScriptEngines"; + + private static LSL2CSConverter LSL_Converter = new LSL2CSConverter(); + private static CSharpCodeProvider CScodeProvider = new CSharpCodeProvider(); + private static VBCodeProvider VBcodeProvider = new VBCodeProvider(); + private static JScriptCodeProvider JScodeProvider = new JScriptCodeProvider(); + + private static int instanceID = new Random().Next(0, int.MaxValue); // Unique number to use on our compiled files + private static UInt64 scriptCompileCounter = 0; // And a counter + + public XEngine m_scriptEngine; + public Compiler(XEngine scriptEngine) + { + m_scriptEngine = scriptEngine; + ReadConfig(); + } + public bool in_startup = true; + public void ReadConfig() + { + + // Get some config + WriteScriptSourceToDebugFile = m_scriptEngine.ScriptConfigSource.GetBoolean("WriteScriptSourceToDebugFile", true); + CompileWithDebugInformation = m_scriptEngine.ScriptConfigSource.GetBoolean("CompileWithDebugInformation", true); + + // Get file prefix from scriptengine name and make it file system safe: + FilePrefix = m_scriptEngine.ScriptEngineName; + foreach (char c in Path.GetInvalidFileNameChars()) + { + FilePrefix = FilePrefix.Replace(c, '_'); + } + + // First time we start? Delete old files + if (in_startup) + { + in_startup = false; + DeleteOldFiles(); + } + + // Map name and enum type of our supported languages + LanguageMapping.Add(enumCompileType.cs.ToString(), enumCompileType.cs); + LanguageMapping.Add(enumCompileType.vb.ToString(), enumCompileType.vb); + LanguageMapping.Add(enumCompileType.lsl.ToString(), enumCompileType.lsl); + LanguageMapping.Add(enumCompileType.js.ToString(), enumCompileType.js); + + // Allowed compilers + string allowComp = m_scriptEngine.ScriptConfigSource.GetString("AllowedCompilers", "lsl,cs,vb,js"); + AllowedCompilers.Clear(); + +#if DEBUG + m_scriptEngine.Log.Debug("[" + m_scriptEngine.ScriptEngineName + "]: Allowed languages: " + allowComp); +#endif + + + foreach (string strl in allowComp.Split(',')) + { + string strlan = strl.Trim(" \t".ToCharArray()).ToLower(); + if (!LanguageMapping.ContainsKey(strlan)) + { + m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: Config error. Compiler is unable to recognize language type \"" + strlan + "\" specified in \"AllowedCompilers\"."); + } + else + { +#if DEBUG + //m_scriptEngine.Log.Debug("[" + m_scriptEngine.ScriptEngineName + "]: Config OK. Compiler recognized language type \"" + strlan + "\" specified in \"AllowedCompilers\"."); +#endif + } + AllowedCompilers.Add(strlan, true); + } + if (AllowedCompilers.Count == 0) + m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: Config error. Compiler could not recognize any language in \"AllowedCompilers\". Scripts will not be executed!"); + + // Default language + string defaultCompileLanguage = m_scriptEngine.ScriptConfigSource.GetString("DefaultCompileLanguage", "lsl").ToLower(); + + // Is this language recognized at all? + if (!LanguageMapping.ContainsKey(defaultCompileLanguage)) + { + m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: " + + "Config error. Default language \"" + defaultCompileLanguage + "\" specified in \"DefaultCompileLanguage\" is not recognized as a valid language. Changing default to: \"lsl\"."); + defaultCompileLanguage = "lsl"; + } + + // Is this language in allow-list? + if (!AllowedCompilers.ContainsKey(defaultCompileLanguage)) + { + m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: " + + "Config error. Default language \"" + defaultCompileLanguage + "\"specified in \"DefaultCompileLanguage\" is not in list of \"AllowedCompilers\". Scripts may not be executed!"); + } + else + { +#if DEBUG +// m_scriptEngine.Log.Debug("[" + m_scriptEngine.ScriptEngineName + "]: " + +// "Config OK. Default language \"" + defaultCompileLanguage + "\" specified in \"DefaultCompileLanguage\" is recognized as a valid language."); +#endif + // LANGUAGE IS IN ALLOW-LIST + DefaultCompileLanguage = LanguageMapping[defaultCompileLanguage]; + } + + // We now have an allow-list, a mapping list, and a default language + + } + + /// + /// Delete old script files + /// + private void DeleteOldFiles() + { + + // CREATE FOLDER IF IT DOESNT EXIST + if (!Directory.Exists(ScriptEnginesPath)) + { + try + { + Directory.CreateDirectory(ScriptEnginesPath); + } + catch (Exception ex) + { + m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: Exception trying to create ScriptEngine directory \"" + ScriptEnginesPath + "\": " + ex.ToString()); + } + } + + if (!Directory.Exists(Path.Combine(ScriptEnginesPath, + m_scriptEngine.World.RegionInfo.RegionID.ToString()))) + { + try + { + Directory.CreateDirectory(Path.Combine(ScriptEnginesPath, + m_scriptEngine.World.RegionInfo.RegionID.ToString())); + } + catch (Exception ex) + { + m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: Exception trying to create ScriptEngine directory \"" + Path.Combine(ScriptEnginesPath, + m_scriptEngine.World.RegionInfo.RegionID.ToString())+ "\": " + ex.ToString()); + } + } + + foreach (string file in Directory.GetFiles(Path.Combine(ScriptEnginesPath, + m_scriptEngine.World.RegionInfo.RegionID.ToString()))) + { + //m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: FILE FOUND: " + file); + + if (file.ToLower().StartsWith(FilePrefix + "_compiled_") || + file.ToLower().StartsWith(FilePrefix + "_source_")) + { + try + { + File.Delete(file); + } + catch (Exception ex) + { + m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: Exception trying delete old script file \"" + file + "\": " + ex.ToString()); + } + + } + } + + } + + ////private ICodeCompiler icc = codeProvider.CreateCompiler(); + //public string CompileFromFile(string LSOFileName) + //{ + // switch (Path.GetExtension(LSOFileName).ToLower()) + // { + // case ".txt": + // case ".lsl": + // Common.ScriptEngineBase.Common.SendToDebug("Source code is LSL, converting to CS"); + // return CompileFromLSLText(File.ReadAllText(LSOFileName)); + // case ".cs": + // Common.ScriptEngineBase.Common.SendToDebug("Source code is CS"); + // return CompileFromCSText(File.ReadAllText(LSOFileName)); + // default: + // throw new Exception("Unknown script type."); + // } + //} + + /// + /// Converts script from LSL to CS and calls CompileFromCSText + /// + /// LSL script + /// Filename to .dll assembly + public string PerformScriptCompile(string Script, string asset) + { + string OutFile = Path.Combine(ScriptEnginesPath, Path.Combine( + m_scriptEngine.World.RegionInfo.RegionID.ToString(), + FilePrefix + "_compiled_" + asset + ".dll")); +// string OutFile = Path.Combine(ScriptEnginesPath, +// FilePrefix + "_compiled_" + asset + ".dll"); + + if(File.Exists(OutFile)) + return OutFile; + + if (!Directory.Exists(ScriptEnginesPath)) + { + try + { + Directory.CreateDirectory(ScriptEnginesPath); + } + catch (Exception ex) + { + } + } + + if (!Directory.Exists(Path.Combine(ScriptEnginesPath, + m_scriptEngine.World.RegionInfo.RegionID.ToString()))) + { + try + { + Directory.CreateDirectory(ScriptEnginesPath); + } + catch (Exception ex) + { + } + } + + enumCompileType l = DefaultCompileLanguage; + + + if (Script.StartsWith("//c#", true, CultureInfo.InvariantCulture)) + l = enumCompileType.cs; + if (Script.StartsWith("//vb", true, CultureInfo.InvariantCulture)) + { + l = enumCompileType.vb; + // We need to remove //vb, it won't compile with that + + Script = Script.Substring(4, Script.Length - 4); + } + if (Script.StartsWith("//lsl", true, CultureInfo.InvariantCulture)) + l = enumCompileType.lsl; + + if (Script.StartsWith("//js", true, CultureInfo.InvariantCulture)) + l = enumCompileType.js; + + if (!AllowedCompilers.ContainsKey(l.ToString())) + { + // Not allowed to compile to this language! + string errtext = String.Empty; + errtext += "The compiler for language \"" + l.ToString() + "\" is not in list of allowed compilers. Script will not be executed!"; + throw new Exception(errtext); + } + + string compileScript = Script; + + if (l == enumCompileType.lsl) + { + // Its LSL, convert it to C# + compileScript = LSL_Converter.Convert(Script); + l = enumCompileType.cs; + } + + // Insert additional assemblies here + + //ADAM: Disabled for the moment until it's working right. + bool enableCommanderLSL = false; + + if (enableCommanderLSL == true && l == enumCompileType.cs) + { + foreach (KeyValuePair com + in m_scriptEngine.World.GetCommanders()) + { + compileScript = com.Value.GenerateRuntimeAPI() + compileScript; + } + } + + // End of insert + + + switch (l) + { + case enumCompileType.cs: + compileScript = CreateCSCompilerScript(compileScript); + break; + case enumCompileType.vb: + compileScript = CreateVBCompilerScript(compileScript); + break; + case enumCompileType.js: + compileScript = CreateJSCompilerScript(compileScript); + break; + } + +// m_log.Debug("[ScriptEngine.DotNetEngine]: Preparing to compile the following LSL to C# translated code"); +// m_log.Debug(""); +// m_log.Debug(compileScript); + + return CompileFromDotNetText(compileScript, l, asset); + } + + private static string CreateJSCompilerScript(string compileScript) + { + compileScript = String.Empty + + "import OpenSim.Region.ScriptEngine.XEngine.Script; import System.Collections.Generic;\r\n" + + "package SecondLife {\r\n" + + "class Script extends OpenSim.Region.ScriptEngine.XEngine.Script.BuiltIn_Commands_BaseClass { \r\n" + + compileScript + + "} }\r\n"; + return compileScript; + } + + private static string CreateCSCompilerScript(string compileScript) + { + + + compileScript = String.Empty + + "using OpenSim.Region.ScriptEngine.XEngine.Script; using System.Collections.Generic;\r\n" + + String.Empty + "namespace SecondLife { " + + String.Empty + "public class Script : OpenSim.Region.ScriptEngine.XEngine.Script.BuiltIn_Commands_BaseClass { \r\n" + + @"public Script() { } " + + compileScript + + "} }\r\n"; + return compileScript; + } + + private static string CreateVBCompilerScript(string compileScript) + { + compileScript = String.Empty + + "Imports OpenSim.Region.ScriptEngine.XEngine.Script: Imports System.Collections.Generic: " + + String.Empty + "NameSpace SecondLife:" + + String.Empty + "Public Class Script: Inherits OpenSim.Region.ScriptEngine.XEngine.Script.BuiltIn_Commands_BaseClass: " + + "\r\nPublic Sub New()\r\nEnd Sub: " + + compileScript + + ":End Class :End Namespace\r\n"; + return compileScript; + } + + /// + /// Compile .NET script to .Net assembly (.dll) + /// + /// CS script + /// Filename to .dll assembly + internal string CompileFromDotNetText(string Script, enumCompileType lang, string asset) + { + string ext = "." + lang.ToString(); + + // Output assembly name + scriptCompileCounter++; + string OutFile = Path.Combine(ScriptEnginesPath, Path.Combine( + m_scriptEngine.World.RegionInfo.RegionID.ToString(), + FilePrefix + "_compiled_" + asset + ".dll")); +#if DEBUG +// m_scriptEngine.Log.Debug("[" + m_scriptEngine.ScriptEngineName + "]: Starting compile of \"" + OutFile + "\"."); +#endif + try + { + File.Delete(OutFile); + } + catch (Exception e) // NOTLEGIT - Should be just catching FileIOException + { + //m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: Unable to delete old existring script-file before writing new. Compile aborted: " + e.ToString()); + throw new Exception("Unable to delete old existring script-file before writing new. Compile aborted: " + e.ToString()); + } + //string OutFile = Path.Combine("ScriptEngines", "SecondLife.Script.dll"); + + // DEBUG - write source to disk + if (WriteScriptSourceToDebugFile) + { + string srcFileName = FilePrefix + "_source_" + Path.GetFileNameWithoutExtension(OutFile) + ext; + try + { + File.WriteAllText( + Path.Combine("ScriptEngines", srcFileName), + Script); + } + catch (Exception ex) // NOTLEGIT - Should be just catching FileIOException + { + m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: Exception while trying to write script source to file \"" + srcFileName + "\": " + ex.ToString()); + } + } + + // Do actual compile + CompilerParameters parameters = new CompilerParameters(); + + parameters.IncludeDebugInformation = true; + + // Add all available assemblies +// foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies()) +// { +// Console.WriteLine("Adding assembly: " + asm.Location); +// parameters.ReferencedAssemblies.Add(asm.Location); +// } + + string rootPath = Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory); + string rootPathSE = Path.GetDirectoryName(GetType().Assembly.Location); + //Console.WriteLine("Assembly location: " + rootPath); + parameters.ReferencedAssemblies.Add(Path.Combine(rootPath, "OpenSim.Region.ScriptEngine.XEngine.Script.dll")); +// parameters.ReferencedAssemblies.Add(Path.Combine(rootPathSE, "OpenSim.Region.ScriptEngine.XEngine.dll")); + + //parameters.ReferencedAssemblies.Add("OpenSim.Region.Environment"); + parameters.GenerateExecutable = false; + parameters.OutputAssembly = OutFile; + parameters.IncludeDebugInformation = CompileWithDebugInformation; + //parameters.WarningLevel = 1; // Should be 4? + parameters.TreatWarningsAsErrors = false; + +//Console.WriteLine(Script); + CompilerResults results; + switch (lang) + { + case enumCompileType.vb: + results = VBcodeProvider.CompileAssemblyFromSource(parameters, Script); + break; + case enumCompileType.cs: + results = CScodeProvider.CompileAssemblyFromSource(parameters, Script); + break; + case enumCompileType.js: + results = JScodeProvider.CompileAssemblyFromSource(parameters, Script); + break; + default: + throw new Exception("Compiler is not able to recongnize language type \"" + lang.ToString() + "\""); + } + + // Check result + // Go through errors + + // + // WARNINGS AND ERRORS + // + if (results.Errors.Count > 0) + { + string errtext = String.Empty; + foreach (CompilerError CompErr in results.Errors) + { + errtext += "Line number " + (CompErr.Line - LinesToRemoveOnError) + + ", Error Number: " + CompErr.ErrorNumber + + ", '" + CompErr.ErrorText + "'\r\n"; + } + if (!File.Exists(OutFile)) + { + throw new Exception(errtext); + } + } + + + // + // NO ERRORS, BUT NO COMPILED FILE + // + if (!File.Exists(OutFile)) + { + string errtext = String.Empty; + errtext += "No compile error. But not able to locate compiled file."; + throw new Exception(errtext); + } + return OutFile; + } + } +} diff --git a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs new file mode 100644 index 0000000..734c837 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs @@ -0,0 +1,293 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Region.Environment.Modules.Avatar.Currency.SampleMoney; +using OpenSim.Region.Environment.Scenes; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.ScriptEngine.XEngine.Script; +using Axiom.Math; + +namespace OpenSim.Region.ScriptEngine.XEngine +{ + /// + /// Prepares events so they can be directly executed upon a script by EventQueueManager, then queues it. + /// + public class EventManager + { + private XEngine myScriptEngine; + + public EventManager(XEngine _ScriptEngine) + { + myScriptEngine = _ScriptEngine; + + myScriptEngine.Log.Info("[XEngine] Hooking up to server events"); + myScriptEngine.World.EventManager.OnObjectGrab += touch_start; + myScriptEngine.World.EventManager.OnObjectDeGrab += touch_end; + myScriptEngine.World.EventManager.OnScriptChangedEvent += changed; + myScriptEngine.World.EventManager.OnScriptAtTargetEvent += at_target; + myScriptEngine.World.EventManager.OnScriptNotAtTargetEvent += not_at_target; + myScriptEngine.World.EventManager.OnScriptControlEvent += control; + IMoneyModule money=myScriptEngine.World.RequestModuleInterface(); + if (money != null) + { + money.OnObjectPaid+=HandleObjectPaid; + } + } + + private void HandleObjectPaid(LLUUID objectID, LLUUID agentID, + int amount) + { + SceneObjectPart part = + myScriptEngine.World.GetSceneObjectPart(objectID); + + if (part != null) + { + money(part.LocalId, agentID, amount); + } + } + + public void touch_start(uint localID, LLVector3 offsetPos, + IClientAPI remoteClient) + { + // Add to queue for all scripts in ObjectID object + XDetectParams[] det = new XDetectParams[1]; + det[0].Key = remoteClient.AgentId; + + myScriptEngine.PostObjectEvent(localID, new XEventParams( + "touch_start", new Object[] { new LSL_Types.LSLInteger(1) }, + det)); + } + + public void touch(uint localID, LLVector3 offsetPos, + IClientAPI remoteClient) + { + // Add to queue for all scripts in ObjectID object + XDetectParams[] det = new XDetectParams[1]; + det[0].Key = remoteClient.AgentId; + det[0].OffsetPos = new LSL_Types.Vector3(offsetPos.X, + offsetPos.Y, + offsetPos.Z); + + myScriptEngine.PostObjectEvent(localID, new XEventParams( + "touch", new Object[] { new LSL_Types.LSLInteger(1) }, + det)); + } + + public void touch_end(uint localID, IClientAPI remoteClient) + { + // Add to queue for all scripts in ObjectID object + XDetectParams[] det = new XDetectParams[1]; + det[0].Key = remoteClient.AgentId; + + myScriptEngine.PostObjectEvent(localID, new XEventParams( + "touch_end", new Object[] { new LSL_Types.LSLInteger(1) }, + det)); + } + + public void changed(uint localID, uint change) + { + // Add to queue for all scripts in localID, Object pass change. + myScriptEngine.PostObjectEvent(localID, new XEventParams( + "changed",new object[] { new LSL_Types.LSLInteger(change) }, + new XDetectParams[0])); + } + + // state_entry: not processed here + // state_exit: not processed here + + public void money(uint localID, LLUUID agentID, int amount) + { + myScriptEngine.PostObjectEvent(localID, new XEventParams( + "money", new object[] { + new LSL_Types.LSLString(agentID.ToString()), + new LSL_Types.LSLInteger(amount) }, + new XDetectParams[0])); + } + + public void collision_start(uint localID, LLUUID itemID, + IClientAPI remoteClient) + { + // Add to queue for all scripts in ObjectID object + XDetectParams[] det = new XDetectParams[1]; + det[0].Key = remoteClient.AgentId; + + myScriptEngine.PostObjectEvent(localID, new XEventParams( + "collision_start", + new Object[] { new LSL_Types.LSLInteger(1) }, + det)); + } + + public void collision(uint localID, LLUUID itemID, + IClientAPI remoteClient) + { + // Add to queue for all scripts in ObjectID object + XDetectParams[] det = new XDetectParams[1]; + det[0].Key = remoteClient.AgentId; + + myScriptEngine.PostObjectEvent(localID, new XEventParams( + "collision", new Object[] { new LSL_Types.LSLInteger(1) }, + det)); + } + + public void collision_end(uint localID, LLUUID itemID, + IClientAPI remoteClient) + { + // Add to queue for all scripts in ObjectID object + XDetectParams[] det = new XDetectParams[1]; + det[0].Key = remoteClient.AgentId; + + myScriptEngine.PostObjectEvent(localID, new XEventParams( + "collision_end", + new Object[] { new LSL_Types.LSLInteger(1) }, + det)); + } + + public void land_collision_start(uint localID, LLUUID itemID) + { + myScriptEngine.PostObjectEvent(localID, new XEventParams( + "land_collision_start", + new object[0], + new XDetectParams[0])); + } + + public void land_collision(uint localID, LLUUID itemID) + { + myScriptEngine.PostObjectEvent(localID, new XEventParams( + "land_collision", + new object[0], + new XDetectParams[0])); + } + + public void land_collision_end(uint localID, LLUUID itemID) + { + myScriptEngine.PostObjectEvent(localID, new XEventParams( + "land_collision_end", + new object[0], + new XDetectParams[0])); + } + + // timer: not handled here + // listen: not handled here + + public void on_rez(uint localID, LLUUID itemID, int startParam) + { + myScriptEngine.PostObjectEvent(localID, new XEventParams( + "on_rez",new object[] { + new LSL_Types.LSLInteger(startParam)}, + new XDetectParams[0])); + } + + public void control(uint localID, LLUUID itemID, LLUUID agentID, uint held, uint change) + { + myScriptEngine.PostObjectEvent(localID, new XEventParams( + "control",new object[] { + new LSL_Types.LSLString(agentID.ToString()), + new LSL_Types.LSLInteger(held), + new LSL_Types.LSLInteger(change)}, + new XDetectParams[0])); + } + + public void email(uint localID, LLUUID itemID, string timeSent, + string address, string subject, string message, int numLeft) + { + myScriptEngine.PostObjectEvent(localID, new XEventParams( + "email",new object[] { + new LSL_Types.LSLString(timeSent), + new LSL_Types.LSLString(address), + new LSL_Types.LSLString(subject), + new LSL_Types.LSLString(message), + new LSL_Types.LSLInteger(numLeft)}, + new XDetectParams[0])); + } + + public void at_target(uint localID, uint handle, LLVector3 targetpos, + LLVector3 atpos) + { + myScriptEngine.PostObjectEvent(localID, new XEventParams( + "at_target", new object[] { + new LSL_Types.LSLInteger(handle), + new LSL_Types.Vector3(targetpos.X,targetpos.Y,targetpos.Z), + new LSL_Types.Vector3(atpos.X,atpos.Y,atpos.Z) }, + new XDetectParams[0])); + } + + public void not_at_target(uint localID) + { + myScriptEngine.PostObjectEvent(localID, new XEventParams( + "not_at_target",new object[0], + new XDetectParams[0])); + } + + public void at_rot_target(uint localID, LLUUID itemID) + { + myScriptEngine.PostObjectEvent(localID, new XEventParams( + "at_rot_target",new object[0], + new XDetectParams[0])); + } + + public void not_at_rot_target(uint localID, LLUUID itemID) + { + myScriptEngine.PostObjectEvent(localID, new XEventParams( + "not_at_rot_target",new object[0], + new XDetectParams[0])); + } + + // run_time_permissions: not handled here + + public void attach(uint localID, LLUUID itemID, LLUUID avatar) + { + myScriptEngine.PostObjectEvent(localID, new XEventParams( + "attach",new object[] { + new LSL_Types.LSLString(avatar.ToString()) }, + new XDetectParams[0])); + } + + // dataserver: not handled here + // link_message: not handled here + + public void moving_start(uint localID, LLUUID itemID) + { + myScriptEngine.PostObjectEvent(localID, new XEventParams( + "moving_start",new object[0], + new XDetectParams[0])); + } + + public void moving_end(uint localID, LLUUID itemID) + { + myScriptEngine.PostObjectEvent(localID, new XEventParams( + "moving_end",new object[0], + new XDetectParams[0])); + } + + // object_rez: not handled here + // remote_data: not handled here + // http_response: not handled here + } +} diff --git a/OpenSim/Region/ScriptEngine/XEngine/Executor.cs b/OpenSim/Region/ScriptEngine/XEngine/Executor.cs new file mode 100644 index 0000000..40075ec --- /dev/null +++ b/OpenSim/Region/ScriptEngine/XEngine/Executor.cs @@ -0,0 +1,136 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Reflection; +using OpenSim.Region.ScriptEngine.XEngine.Script; + +namespace OpenSim.Region.ScriptEngine.XEngine +{ + public class Executor : ExecutorBase + { + // Cache functions by keeping a reference to them in a dictionary + private Dictionary Events = new Dictionary(); + private Dictionary m_stateEvents = new Dictionary(); + + public Executor(IScript script) : base(script) + { + initEventFlags(); + } + + + protected override scriptEvents DoGetStateEventFlags() + { + //Console.WriteLine("Get event flags for " + m_Script.State); + + // Check to see if we've already computed the flags for this state + scriptEvents eventFlags = scriptEvents.None; + if (m_stateEvents.ContainsKey(m_Script.State)) + { + m_stateEvents.TryGetValue(m_Script.State, out eventFlags); + return eventFlags; + } + + Type type=m_Script.GetType(); + + // Fill in the events for this state, cache the results in the map + foreach (KeyValuePair kvp in m_eventFlagsMap) + { + string evname = m_Script.State + "_event_" + kvp.Key; + //Console.WriteLine("Trying event "+evname); + try + { + MethodInfo mi = type.GetMethod(evname); + if (mi != null) + { + //Console.WriteLine("Found handler for " + kvp.Key); + eventFlags |= kvp.Value; + } + } + catch(Exception e) + { + //Console.WriteLine("Exeption in GetMethod:\n"+e.ToString()); + } + } + + // Save the flags we just computed and return the result + if(eventFlags != 0) + m_stateEvents.Add(m_Script.State, eventFlags); + + //Console.WriteLine("Returning {0:x}", eventFlags); + return (eventFlags); + } + + protected override void DoExecuteEvent(string FunctionName, object[] args) + { + // IMPORTANT: Types and MemberInfo-derived objects require a LOT of memory. + // Instead use RuntimeTypeHandle, RuntimeFieldHandle and RunTimeHandle (IntPtr) instead! + + string EventName = m_Script.State + "_event_" + FunctionName; + +//#if DEBUG +// Console.WriteLine("ScriptEngine: Script event function name: " + EventName); +//#endif + + if (Events.ContainsKey(EventName) == false) + { + // Not found, create + Type type = m_Script.GetType(); + try + { + MethodInfo mi = type.GetMethod(EventName); + Events.Add(EventName, mi); + } + catch + { + Console.WriteLine("Event {0}not found", EventName); + // Event name not found, cache it as not found + Events.Add(EventName, null); + } + } + + // Get event + MethodInfo ev = null; + Events.TryGetValue(EventName, out ev); + + if (ev == null) // No event by that name! + { + //Console.WriteLine("ScriptEngine Can not find any event named: \String.Empty + EventName + "\String.Empty); + return; + } + +//cfk 2-7-08 dont need this right now and the default Linux build has DEBUG defined +#if DEBUG + //Console.WriteLine("ScriptEngine: Executing function name: " + EventName); +#endif + // Found + ev.Invoke(m_Script, args); + + } + } +} diff --git a/OpenSim/Region/ScriptEngine/XEngine/ExecutorBase.cs b/OpenSim/Region/ScriptEngine/XEngine/ExecutorBase.cs new file mode 100644 index 0000000..3775372 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/XEngine/ExecutorBase.cs @@ -0,0 +1,181 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Runtime.Remoting.Lifetime; +using OpenSim.Region.ScriptEngine.XEngine.Script; + +namespace OpenSim.Region.ScriptEngine.XEngine +{ + public abstract class ExecutorBase : MarshalByRefObject + { + /// + /// Contains the script to execute functions in. + /// + protected IScript m_Script; + + protected Dictionary m_eventFlagsMap = new Dictionary(); + + [Flags] + public enum scriptEvents : int + { + None = 0, + attach = 1, + collision = 15, + collision_end = 32, + collision_start = 64, + control = 128, + dataserver = 256, + email = 512, + http_response = 1024, + land_collision = 2048, + land_collision_end = 4096, + land_collision_start = 8192, + at_target = 16384, + listen = 32768, + money = 65536, + moving_end = 131072, + moving_start = 262144, + not_at_rot_target = 524288, + not_at_target = 1048576, + remote_data = 8388608, + run_time_permissions = 268435456, + state_entry = 1073741824, + state_exit = 2, + timer = 4, + touch = 8, + touch_end = 536870912, + touch_start = 2097152, + object_rez = 4194304 + } + + /// + /// Create a new instance of ExecutorBase + /// + /// + public ExecutorBase(IScript Script) + { + m_Script = Script; + initEventFlags(); + } + + /// + /// Make sure our object does not timeout when in AppDomain. (Called by ILease base class) + /// + /// + public override Object InitializeLifetimeService() + { + //Console.WriteLine("Executor: InitializeLifetimeService()"); + // return null; + ILease lease = (ILease)base.InitializeLifetimeService(); + + if (lease.CurrentState == LeaseState.Initial) + { + lease.InitialLeaseTime = TimeSpan.Zero; // TimeSpan.FromMinutes(1); + // lease.SponsorshipTimeout = TimeSpan.FromMinutes(2); + // lease.RenewOnCallTime = TimeSpan.FromSeconds(2); + } + return lease; + } + + /// + /// Get current AppDomain + /// + /// Current AppDomain + public AppDomain GetAppDomain() + { + return AppDomain.CurrentDomain; + } + + /// + /// Execute a specific function/event in script. + /// + /// Name of function to execute + /// Arguments to pass to function + public void ExecuteEvent(string FunctionName, object[] args) + { + DoExecuteEvent(FunctionName, args); + } + + protected abstract void DoExecuteEvent(string FunctionName, object[] args); + + /// + /// Compute the events handled by the current state of the script + /// + /// state mask + public scriptEvents GetStateEventFlags() + { + return DoGetStateEventFlags(); + } + + protected abstract scriptEvents DoGetStateEventFlags(); + + protected void initEventFlags() + { + // Initialize the table if it hasn't already been done + if (m_eventFlagsMap.Count > 0) + { + return; + } + + m_eventFlagsMap.Add("attach", scriptEvents.attach); + // m_eventFlagsMap.Add("at_rot_target",(long)scriptEvents.at_rot_target); + m_eventFlagsMap.Add("at_target", scriptEvents.at_target); + // m_eventFlagsMap.Add("changed",(long)scriptEvents.changed); + m_eventFlagsMap.Add("collision", scriptEvents.collision); + m_eventFlagsMap.Add("collision_end", scriptEvents.collision_end); + m_eventFlagsMap.Add("collision_start", scriptEvents.collision_start); + m_eventFlagsMap.Add("control", scriptEvents.control); + m_eventFlagsMap.Add("dataserver", scriptEvents.dataserver); + m_eventFlagsMap.Add("email", scriptEvents.email); + m_eventFlagsMap.Add("http_response", scriptEvents.http_response); + m_eventFlagsMap.Add("land_collision", scriptEvents.land_collision); + m_eventFlagsMap.Add("land_collision_end", scriptEvents.land_collision_end); + m_eventFlagsMap.Add("land_collision_start", scriptEvents.land_collision_start); + // m_eventFlagsMap.Add("link_message",scriptEvents.link_message); + m_eventFlagsMap.Add("listen", scriptEvents.listen); + m_eventFlagsMap.Add("money", scriptEvents.money); + m_eventFlagsMap.Add("moving_end", scriptEvents.moving_end); + m_eventFlagsMap.Add("moving_start", scriptEvents.moving_start); + m_eventFlagsMap.Add("not_at_rot_target", scriptEvents.not_at_rot_target); + m_eventFlagsMap.Add("not_at_target", scriptEvents.not_at_target); + // m_eventFlagsMap.Add("no_sensor",(long)scriptEvents.no_sensor); + // m_eventFlagsMap.Add("on_rez",(long)scriptEvents.on_rez); + m_eventFlagsMap.Add("remote_data", scriptEvents.remote_data); + m_eventFlagsMap.Add("run_time_permissions", scriptEvents.run_time_permissions); + // m_eventFlagsMap.Add("sensor",(long)scriptEvents.sensor); + m_eventFlagsMap.Add("state_entry", scriptEvents.state_entry); + m_eventFlagsMap.Add("state_exit", scriptEvents.state_exit); + m_eventFlagsMap.Add("timer", scriptEvents.timer); + m_eventFlagsMap.Add("touch", scriptEvents.touch); + m_eventFlagsMap.Add("touch_end", scriptEvents.touch_end); + m_eventFlagsMap.Add("touch_start", scriptEvents.touch_start); + m_eventFlagsMap.Add("object_rez", scriptEvents.object_rez); + } + } +} diff --git a/OpenSim/Region/ScriptEngine/XEngine/LSL2CSConverter.cs b/OpenSim/Region/ScriptEngine/XEngine/LSL2CSConverter.cs new file mode 100644 index 0000000..9c59108 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/XEngine/LSL2CSConverter.cs @@ -0,0 +1,363 @@ +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using System; +using System.Collections.Generic; +using System.Text.RegularExpressions; + +namespace OpenSim.Region.ScriptEngine.XEngine +{ + public class LSL2CSConverter + { + // Uses regex to convert LSL code to C# code. + + //private Regex rnw = new Regex(@"[a-zA-Z0-9_\-]", RegexOptions.Compiled); + private Dictionary dataTypes = new Dictionary(); + private Dictionary quotes = new Dictionary(); + // c Style + private Regex cstylecomments = new Regex(@"/\*(.|[\r\n])*?\*/", RegexOptions.Compiled | RegexOptions.Multiline); + // c# one liners + private Regex nonCommentFwsl = new Regex("\"[a-zA-Z0-9.,:/\\n ]+//[^\"+]+([\\\\\\\"+]+)?(\\s+)?[\"+](\\s+)?(;)?", RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); + private Regex conelinecomments = new Regex(@"[^:].?([\/]{2}[^\n]*)|([\n]{1,}[\/]{2}[^\n]*)", RegexOptions.Compiled | RegexOptions.Multiline); + // ([^\"])((?:[a-zA-Z])\.[a-zA-Z].?)([^\"]) + + // value we're looking for: (?:[a-zA-Z])\.[a-zA-Z] + public LSL2CSConverter() + { + // Only the types we need to convert + dataTypes.Add("void", "void"); + dataTypes.Add("integer", "LSL_Types.LSLInteger"); + dataTypes.Add("float", "double"); + dataTypes.Add("string", "LSL_Types.LSLString"); + dataTypes.Add("key", "LSL_Types.LSLString"); + dataTypes.Add("vector", "LSL_Types.Vector3"); + dataTypes.Add("rotation", "LSL_Types.Quaternion"); + dataTypes.Add("list", "LSL_Types.list"); + dataTypes.Add("null", "null"); + } + + public string Convert(string Script) + { + quotes.Clear(); + string Return = String.Empty; + Script = " \r\n" + Script; + + // + // Prepare script for processing + // + + // Clean up linebreaks + Script = Regex.Replace(Script, @"\r\n", "\n"); + Script = Regex.Replace(Script, @"\n", "\r\n"); + + // QUOTE REPLACEMENT + // temporarily replace quotes so we can work our magic on the script without + // always considering if we are inside our outside quotes's + // TODO: Does this work on half-quotes in strings? ;) + string _Script = String.Empty; + string C; + bool in_quote = false; + bool quote_replaced = false; + string quote_replacement_string = "Q_U_O_T_E_REPLACEMENT_"; + string quote = String.Empty; + bool last_was_escape = false; + int quote_replaced_count = 0; + + string removefwnoncomments = nonCommentFwsl.Replace(Script, "\"\";"); + + string removecomments = conelinecomments.Replace(removefwnoncomments, ""); + removecomments = cstylecomments.Replace(removecomments, ""); + string[] localscript = removecomments.Split('"'); + string checkscript = String.Empty; + bool flip = true; + + for (int p = 0; p < localscript.Length; p++) + { + //if (localscript[p].Length >= 1) + //{ + if (!localscript[p].EndsWith(@"\")) + { + flip = !flip; + //System.Console.WriteLine("Flip:" + flip.ToString() + " - " + localscript[p] + " ! " + localscript[p].EndsWith(@"\").ToString()); + } + //} + //else + //{ + // flip = !flip; + // System.Console.WriteLine("Flip:" + flip.ToString() + " - " + localscript[p]); + //} + if (!flip) + checkscript += localscript[p]; + } + + //System.Console.WriteLine("SCRIPT:" + checkscript); + + // checks for alpha.alpha way of referring to objects in C# + // ignores alpha.x alpha.y, alpha.z for refering to vector components + Match SecurityM; + + // BROKEN: this check is very wrong. It block's any url in strings. + SecurityM = Regex.Match(checkscript, @"(?:[a-zA-Z])\.(?:[a-wA-Z]|[a-zA-Z][a-zA-Z])", RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); + + if (SecurityM.Success) + throw new Exception("CS0103: 'The . symbol cannot be used in LSL except in float values or vector components'. Detected around: " + SecurityM.Captures[0].Value); + + SecurityM = Regex.Match(checkscript, @"typeof\s", RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); + if (SecurityM.Success) + throw new Exception("CS0103: 'The object.typeof method isn't allowed in LSL'"); + + SecurityM = Regex.Match(checkscript, @"GetType\(", RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); + if (SecurityM.Success) + throw new Exception("CS0103: 'The object.GetType method isn't allowed in LSL'"); + + for (int p = 0; p < Script.Length; p++) + { + C = Script.Substring(p, 1); + while (true) + { + // found " and last was not \ so this is not an escaped \" + if (C == "\"" && last_was_escape == false) + { + // Toggle inside/outside quote + in_quote = !in_quote; + if (in_quote) + { + quote_replaced_count++; + } + else + { + if (quote == String.Empty) + { + // We didn't replace quote, probably because of empty string? + _Script += quote_replacement_string + + quote_replaced_count.ToString().PadLeft(5, "0".ToCharArray()[0]); + } + // We just left a quote + quotes.Add( + quote_replacement_string + + quote_replaced_count.ToString().PadLeft(5, "0".ToCharArray()[0]), quote); + quote = String.Empty; + } + break; + } + + if (!in_quote) + { + // We are not inside a quote + quote_replaced = false; + } + else + { + // We are inside a quote + if (!quote_replaced) + { + // Replace quote + _Script += quote_replacement_string + + quote_replaced_count.ToString().PadLeft(5, "0".ToCharArray()[0]); + quote_replaced = true; + } + quote += C; + break; + } + _Script += C; + break; + } + last_was_escape = false; + if (C == @"\") + { + last_was_escape = true; + } + } + Script = _Script; + // + // END OF QUOTE REPLACEMENT + // + + // + // PROCESS STATES + // Remove state definitions and add state names to start of each event within state + // + int ilevel = 0; + int lastlevel = 0; + string ret = String.Empty; + string cache = String.Empty; + bool in_state = false; + string current_statename = String.Empty; + for (int p = 0; p < Script.Length; p++) + { + C = Script.Substring(p, 1); + while (true) + { + // inc / dec level + if (C == @"{") + ilevel++; + if (C == @"}") + ilevel--; + if (ilevel < 0) + ilevel = 0; + cache += C; + + // if level == 0, add to return + if (ilevel == 1 && lastlevel == 0) + { + // 0 => 1: Get last + Match m = + //Regex.Match(cache, @"(?![a-zA-Z_]+)\s*([a-zA-Z_]+)[^a-zA-Z_\(\)]*{", + Regex.Match(cache, @"(?![a-zA-Z_]+)\s*(state\s+)?(?[a-zA-Z_][a-zA-Z_0-9]*)[^a-zA-Z_0-9\(\)]*{", + + RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); + + in_state = false; + if (m.Success) + { + // Go back to level 0, this is not a state + in_state = true; + current_statename = m.Groups["statename"].Captures[0].Value; + //Console.WriteLine("Current statename: " + current_statename); + cache = + //@"(?(?![a-zA-Z_]+)\s*)" + @"([a-zA-Z_]+)(?[^a-zA-Z_\(\)]*){", + Regex.Replace(cache, + @"(?(?![a-zA-Z_]+)\s*)" + @"(state\s+)?([a-zA-Z_][a-zA-Z_0-9]*)(?[^a-zA-Z_0-9\(\)]*){", + "${s1}${s2}", + RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.IgnoreCase); + } + ret += cache; + cache = String.Empty; + } + if (ilevel == 0 && lastlevel == 1) + { + // 1 => 0: Remove last } + if (in_state == true) + { + cache = cache.Remove(cache.Length - 1, 1); + //cache = Regex.Replace(cache, "}$", String.Empty, RegexOptions.Multiline | RegexOptions.Singleline); + + //Replace function names + // void dataserver(key query_id, string data) { + //cache = Regex.Replace(cache, @"([^a-zA-Z_]\s*)((?!if|switch|for)[a-zA-Z_]+\s*\([^\)]*\)[^{]*{)", "$1" + "" + "$2", RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); + //Console.WriteLine("Replacing using statename: " + current_statename); + cache = + Regex.Replace(cache, + @"^(\s*)((?!(if|switch|for|while)[^a-zA-Z0-9_])[a-zA-Z0-9_]*\s*\([^\)]*\)[^;]*\{)", + @"$1public " + current_statename + "_event_$2", + RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.IgnoreCase); + } + + ret += cache; + cache = String.Empty; + in_state = true; + current_statename = String.Empty; + } + + break; + } + lastlevel = ilevel; + } + ret += cache; + cache = String.Empty; + + Script = ret; + ret = String.Empty; + + foreach (string key in dataTypes.Keys) + { + string val; + dataTypes.TryGetValue(key, out val); + + // Replace CAST - (integer) with (int) + Script = + Regex.Replace(Script, @"\(" + key + @"\)", @"(" + val + ")", + RegexOptions.Compiled | RegexOptions.Multiline); + // Replace return types and function variables - integer a() and f(integer a, integer a) + Script = + Regex.Replace(Script, @"(^|;|}|[\(,])(\s*)" + key + @"(\s+)", @"$1$2" + val + "$3", + RegexOptions.Compiled | RegexOptions.Multiline); + Script = + Regex.Replace(Script, @"(^|;|}|[\(,])(\s*)" + key + @"(\s*)[,]", @"$1$2" + val + "$3,", + RegexOptions.Compiled | RegexOptions.Multiline); + } + + // Add "void" in front of functions that needs it + Script = + Regex.Replace(Script, + @"^(\s*public\s+)?((?!(if|switch|for)[^a-zA-Z0-9_])[a-zA-Z0-9_]*\s*\([^\)]*\)[^;]*\{)", + @"$1void $2", RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); + + // Replace and + Script = + Regex.Replace(Script, @"<([^,>;]*,[^,>;]*,[^,>;]*,[^,>;]*)>", @"new LSL_Types.Quaternion($1)", + RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); + Script = + Regex.Replace(Script, @"<([^,>;)]*,[^,>;]*,[^,>;]*)>", @"new LSL_Types.Vector3($1)", + RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); + + // Replace List []'s + Script = + Regex.Replace(Script, @"\[([^\]]*)\]", @"new LSL_Types.list($1)", + RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); + + // Replace (string) to .ToString() // + Script = + Regex.Replace(Script, @"\(string\)\s*([a-zA-Z0-9_.]+(\s*\([^\)]*\))?)", @"$1.ToString()", + RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); + Script = + Regex.Replace(Script, @"\((float|int)\)\s*([a-zA-Z0-9_.]+(\s*\([^\)]*\))?)", @"$1.Parse($2)", + RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); + + // Replace "state STATENAME" with "state("statename")" + Script = + Regex.Replace(Script, @"(state)\s+([^;\n\r]+)(;[\r\n\s])", "$1(\"$2\")$3", + RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.IgnoreCase); + + // REPLACE BACK QUOTES + foreach (string key in quotes.Keys) + { + string val; + quotes.TryGetValue(key, out val); + Script = Script.Replace(key, "\"" + val + "\""); + } + + //System.Console.WriteLine(Script); + Return = String.Empty;// + + //"using OpenSim.Region.ScriptEngine.Common; using System.Collections.Generic;"; + + //Return += String.Empty + + // "namespace SecondLife { "; + //Return += String.Empty + + // //"[Serializable] " + + // "public class Script : OpenSim.Region.ScriptEngine.Common.LSL_BaseClass { "; + //Return += @"public Script() { } "; + Return += Script; + //Return += "} }\r\n"; + + quotes.Clear(); + + return Return; + } + } +} diff --git a/OpenSim/Region/ScriptEngine/XEngine/LSL_ScriptCommands.cs b/OpenSim/Region/ScriptEngine/XEngine/LSL_ScriptCommands.cs new file mode 100644 index 0000000..ca209b6 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/XEngine/LSL_ScriptCommands.cs @@ -0,0 +1,6474 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Runtime.Remoting.Lifetime; +using System.Text; +using System.Threading; +using Axiom.Math; +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Region.Environment; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Modules.Avatar.Currency.SampleMoney; +using OpenSim.Region.Environment.Modules.World.Land; +using OpenSim.Region.Environment.Scenes; +using OpenSim.Region.ScriptEngine.XEngine; +using OpenSim.Region.ScriptEngine.XEngine.Script; + + +namespace OpenSim.Region.ScriptEngine.XEngine +{ + /// + /// Contains all LSL ll-functions. This class will be in Default AppDomain. + /// + public class LSL_ScriptCommands : MarshalByRefObject, ILSL_ScriptCommands + { + // private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + internal XEngine m_ScriptEngine; + internal XScriptInstance m_Instance; + internal SceneObjectPart m_host; + internal uint m_localID; + internal LLUUID m_itemID; + internal bool throwErrorOnNotImplemented = true; + + public LSL_ScriptCommands(XEngine ScriptEngine, XScriptInstance instance, SceneObjectPart host, uint localID, LLUUID itemID) + { + m_ScriptEngine = ScriptEngine; + m_Instance = instance; + m_host = host; + m_localID = localID; + m_itemID = itemID; + + //m_log.Info(ScriptEngineName, "LSL_BaseClass.Start() called. Hosted by [" + m_host.Name + ":" + m_host.UUID + "@" + m_host.AbsolutePosition + "]"); + } + + private DateTime m_timer = DateTime.Now; + private string m_state = "default"; + private bool m_waitingForScriptAnswer=false; + + + public string State + { + get { return m_Instance.State; } + set { m_Instance.State = value; } + } + + public void state(string newState) + { + m_Instance.SetState(newState); + } + + // Object never expires + public override Object InitializeLifetimeService() + { + //Console.WriteLine("LSL_BuiltIn_Commands: InitializeLifetimeService()"); + // return null; + ILease lease = (ILease)base.InitializeLifetimeService(); + + if (lease.CurrentState == LeaseState.Initial) + { + lease.InitialLeaseTime = TimeSpan.Zero; // TimeSpan.FromMinutes(1); + // lease.SponsorshipTimeout = TimeSpan.FromMinutes(2); + // lease.RenewOnCallTime = TimeSpan.FromSeconds(2); + } + return lease; + } + + public Scene World + { + get { return m_ScriptEngine.World; } + } + + public void llSay(int channelID, string text) + { + m_host.AddScriptLPS(1); + + if(text.Length > 1023) + text=text.Substring(0, 1023); + + World.SimChat(Helpers.StringToField(text), + ChatTypeEnum.Say, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID, false); + + IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface(); + wComm.DeliverMessage(ChatTypeEnum.Say, channelID, m_host.Name, m_host.UUID, text); + } + + // Extension commands use this: + public ICommander GetCommander(string name) + { + return World.GetCommander(name); + } + + private LLUUID InventorySelf() + { + LLUUID invItemID=new LLUUID(); + + foreach (KeyValuePair inv in m_host.TaskInventory) + { + if (inv.Value.Type == 10 && inv.Value.ItemID == m_itemID) + { + invItemID=inv.Key; + break; + } + } + + return invItemID; + } + + private LLUUID InventoryKey(string name, int type) + { + m_host.AddScriptLPS(1); + foreach (KeyValuePair inv in m_host.TaskInventory) + { + if (inv.Value.Name == name) + { + if (inv.Value.Type != type) + return LLUUID.Zero; + + return inv.Value.AssetID.ToString(); + } + } + return LLUUID.Zero; + } + + private LLUUID InventoryKey(string name) + { + m_host.AddScriptLPS(1); + foreach (KeyValuePair inv in m_host.TaskInventory) + { + if (inv.Value.Name == name) + { + return inv.Value.AssetID.ToString(); + } + } + return LLUUID.Zero; + } + + public void osSetRegionWaterHeight(double height) + { + m_host.AddScriptLPS(1); + //Check to make sure that the script's owner is the estate manager/master + //World.Permissions.GenericEstatePermission( + if (World.ExternalChecks.ExternalChecksCanBeGodLike(m_host.OwnerID)) + { + World.EventManager.TriggerRequestChangeWaterHeight((float)height); + } + } + + //These are the implementations of the various ll-functions used by the LSL scripts. + //starting out, we use the System.Math library for trig functions. - ckrinke 8-14-07 + public double llSin(double f) + { + m_host.AddScriptLPS(1); + return (double)Math.Sin(f); + } + + public double llCos(double f) + { + m_host.AddScriptLPS(1); + return (double)Math.Cos(f); + } + + public double llTan(double f) + { + m_host.AddScriptLPS(1); + return (double)Math.Tan(f); + } + + public double llAtan2(double x, double y) + { + m_host.AddScriptLPS(1); + return (double)Math.Atan2(y, x); + } + + public double llSqrt(double f) + { + m_host.AddScriptLPS(1); + return (double)Math.Sqrt(f); + } + + public double llPow(double fbase, double fexponent) + { + m_host.AddScriptLPS(1); + return (double)Math.Pow(fbase, fexponent); + } + + public LSL_Types.LSLInteger llAbs(int i) + { + m_host.AddScriptLPS(1); + return (int)Math.Abs(i); + } + + public double llFabs(double f) + { + m_host.AddScriptLPS(1); + return (double)Math.Abs(f); + } + + public double llFrand(double mag) + { + m_host.AddScriptLPS(1); + lock (Util.RandomClass) + { + return Util.RandomClass.NextDouble() * mag; + } + } + + public LSL_Types.LSLInteger llFloor(double f) + { + m_host.AddScriptLPS(1); + return (int)Math.Floor(f); + } + + public LSL_Types.LSLInteger llCeil(double f) + { + m_host.AddScriptLPS(1); + return (int)Math.Ceiling(f); + } + + // Xantor 01/May/2008 fixed midpointrounding (2.5 becomes 3.0 instead of 2.0, default = ToEven) + public LSL_Types.LSLInteger llRound(double f) + { + m_host.AddScriptLPS(1); + return (int)Math.Round(f, MidpointRounding.AwayFromZero); + } + + //This next group are vector operations involving squaring and square root. ckrinke + public double llVecMag(LSL_Types.Vector3 v) + { + m_host.AddScriptLPS(1); + return LSL_Types.Vector3.Mag(v); + } + + public LSL_Types.Vector3 llVecNorm(LSL_Types.Vector3 v) + { + m_host.AddScriptLPS(1); + double mag = LSL_Types.Vector3.Mag(v); + LSL_Types.Vector3 nor = new LSL_Types.Vector3(); + nor.x = v.x / mag; + nor.y = v.y / mag; + nor.z = v.z / mag; + return nor; + } + + public double llVecDist(LSL_Types.Vector3 a, LSL_Types.Vector3 b) + { + m_host.AddScriptLPS(1); + double dx = a.x - b.x; + double dy = a.y - b.y; + double dz = a.z - b.z; + return Math.Sqrt(dx * dx + dy * dy + dz * dz); + } + + //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke + + // Utility function for llRot2Euler + + // normalize an angle between 0 - 2*PI (0 and 360 degrees) + private double NormalizeAngle(double angle) + { + angle = angle % (Math.PI * 2); + if (angle < 0) angle = angle + Math.PI * 2; + return angle; + } + + + // Old implementation of llRot2Euler, now normalized + + public LSL_Types.Vector3 llRot2Euler(LSL_Types.Quaternion r) + { + m_host.AddScriptLPS(1); + //This implementation is from http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions. ckrinke + LSL_Types.Quaternion t = new LSL_Types.Quaternion(r.x * r.x, r.y * r.y, r.z * r.z, r.s * r.s); + double m = (t.x + t.y + t.z + t.s); + if (m == 0) return new LSL_Types.Vector3(); + double n = 2 * (r.y * r.s + r.x * r.z); + double p = m * m - n * n; + if (p > 0) + return new LSL_Types.Vector3(NormalizeAngle(Math.Atan2(2.0 * (r.x * r.s - r.y * r.z), (-t.x - t.y + t.z + t.s))), + NormalizeAngle(Math.Atan2(n, Math.Sqrt(p))), + NormalizeAngle(Math.Atan2(2.0 * (r.z * r.s - r.x * r.y), (t.x - t.y - t.z + t.s)))); + else if (n > 0) + return new LSL_Types.Vector3(0.0, Math.PI / 2, NormalizeAngle(Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z))); + else + return new LSL_Types.Vector3(0.0, -Math.PI / 2, NormalizeAngle(Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z))); + } + + + // Xantor's newer llEuler2Rot() *try the second* inverted quaternions (-x,-y,-z,w) as LL seems to like + // New and improved, now actually works as described. Prim rotates as expected as does llRot2Euler. + + /* From wiki: + The Euler angle vector (in radians) is converted to a rotation by doing the rotations around the 3 axes + in Z, Y, X order. So llEuler2Rot(<1.0, 2.0, 3.0> * DEG_TO_RAD) generates a rotation by taking the zero rotation, + a vector pointing along the X axis, first rotating it 3 degrees around the global Z axis, then rotating the resulting + vector 2 degrees around the global Y axis, and finally rotating that 1 degree around the global X axis. + */ + + public LSL_Types.Quaternion llEuler2Rot(LSL_Types.Vector3 v) + { + m_host.AddScriptLPS(1); + + double x,y,z,s,s_i; + + double cosX = Math.Cos(v.x); + double cosY = Math.Cos(v.y); + double cosZ = Math.Cos(v.z); + double sinX = Math.Sin(v.x); + double sinY = Math.Sin(v.y); + double sinZ = Math.Sin(v.z); + + s = Math.Sqrt(cosY * cosZ - sinX * sinY * sinZ + cosX * cosZ + cosX * cosY + 1.0f) * 0.5f; + if (Math.Abs(s) < 0.00001) // null rotation + { + x = 0.0f; + y = 1.0f; + z = 0.0f; + } + else + { + s_i = 1.0f / (4.0f * s); + x = - (-sinX * cosY - cosX * sinY * sinZ - sinX * cosZ) * s_i; + y = - (-cosX * sinY * cosZ + sinX * sinZ - sinY) * s_i; + z = - (-cosY * sinZ - sinX * sinY * cosZ - cosX * sinZ) * s_i; + } + return new LSL_Types.Quaternion(x, y, z, s); + } + + + public LSL_Types.Quaternion llAxes2Rot(LSL_Types.Vector3 fwd, LSL_Types.Vector3 left, LSL_Types.Vector3 up) + { + m_host.AddScriptLPS(1); + NotImplemented("llAxes2Rot"); + return new LSL_Types.Quaternion(); + } + + public LSL_Types.Vector3 llRot2Fwd(LSL_Types.Quaternion r) + { + m_host.AddScriptLPS(1); + return (new LSL_Types.Vector3(1,0,0) * r); + } + + public LSL_Types.Vector3 llRot2Left(LSL_Types.Quaternion r) + { + m_host.AddScriptLPS(1); + return (new LSL_Types.Vector3(0, 1, 0) * r); + } + + public LSL_Types.Vector3 llRot2Up(LSL_Types.Quaternion r) + { + m_host.AddScriptLPS(1); + return (new LSL_Types.Vector3(0, 0, 1) * r); + } + public LSL_Types.Quaternion llRotBetween(LSL_Types.Vector3 a, LSL_Types.Vector3 b) + { + //A and B should both be normalized + m_host.AddScriptLPS(1); + double dotProduct = LSL_Types.Vector3.Dot(a, b); + LSL_Types.Vector3 crossProduct = LSL_Types.Vector3.Cross(a, b); + double magProduct = LSL_Types.Vector3.Mag(a) * LSL_Types.Vector3.Mag(b); + double angle = Math.Acos(dotProduct / magProduct); + LSL_Types.Vector3 axis = LSL_Types.Vector3.Norm(crossProduct); + double s = Math.Sin(angle / 2); + + return new LSL_Types.Quaternion(axis.x * s, axis.y * s, axis.z * s, (float)Math.Cos(angle / 2)); + } + public void llWhisper(int channelID, string text) + { + m_host.AddScriptLPS(1); + + if(text.Length > 1023) + text=text.Substring(0, 1023); + + World.SimChat(Helpers.StringToField(text), + ChatTypeEnum.Whisper, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID, false); + + IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface(); + wComm.DeliverMessage(ChatTypeEnum.Whisper, channelID, m_host.Name, m_host.UUID, text); + } + + public void llShout(int channelID, string text) + { + m_host.AddScriptLPS(1); + + if(text.Length > 1023) + text=text.Substring(0, 1023); + + World.SimChat(Helpers.StringToField(text), + ChatTypeEnum.Shout, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID, true); + + IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface(); + wComm.DeliverMessage(ChatTypeEnum.Shout, channelID, m_host.Name, m_host.UUID, text); + } + + public void llRegionSay(int channelID, string text) + { + if (channelID == 0) + { + LSLError("Cannot use llRegionSay() on channel 0"); + return; + } + + + if(text.Length > 1023) + text=text.Substring(0, 1023); + + m_host.AddScriptLPS(1); + + IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface(); + wComm.DeliverMessage(ChatTypeEnum.Region, channelID, m_host.Name, m_host.UUID, text); + } + + public LSL_Types.LSLInteger llListen(int channelID, string name, string ID, string msg) + { + m_host.AddScriptLPS(1); + LLUUID keyID; + LLUUID.TryParse(ID, out keyID); + IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface(); + return wComm.Listen(m_localID, m_itemID, m_host.UUID, channelID, name, keyID, msg); + } + + public void llListenControl(int number, int active) + { + m_host.AddScriptLPS(1); + IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface(); + wComm.ListenControl(m_itemID, number, active); + } + + public void llListenRemove(int number) + { + m_host.AddScriptLPS(1); + IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface(); + wComm.ListenRemove(m_itemID, number); + } + + public void llSensor(string name, string id, int type, double range, double arc) + { + m_host.AddScriptLPS(1); + LLUUID keyID = LLUUID.Zero; + LLUUID.TryParse(id, out keyID); + + m_ScriptEngine.m_ASYNCLSLCommandManager.m_SensorRepeat.SenseOnce(m_localID, m_itemID, name, keyID, type, range, arc, m_host); + } + + public void llSensorRepeat(string name, string id, int type, double range, double arc, double rate) + { + m_host.AddScriptLPS(1); + LLUUID keyID = LLUUID.Zero; + LLUUID.TryParse(id, out keyID); + + m_ScriptEngine.m_ASYNCLSLCommandManager.m_SensorRepeat.SetSenseRepeatEvent(m_localID, m_itemID, name, keyID, type, range, arc, rate, m_host); + } + + public void llSensorRemove() + { + m_host.AddScriptLPS(1); + m_ScriptEngine.m_ASYNCLSLCommandManager.m_SensorRepeat.UnSetSenseRepeaterEvents(m_localID, m_itemID); + } + + public string resolveName(LLUUID objecUUID) + { + // try avatar username surname + UserProfileData profile = World.CommsManager.UserService.GetUserProfile(objecUUID); + if (profile != null) + { + string avatarname = profile.FirstName + " " + profile.SurName; + return avatarname; + } + // try an scene object + SceneObjectPart SOP = World.GetSceneObjectPart(objecUUID); + if (SOP != null) + { + string objectname = SOP.Name; + return objectname; + } + + EntityBase SensedObject; + lock (World.Entities) + { + World.Entities.TryGetValue(objecUUID, out SensedObject); + } + + if (SensedObject == null) + return String.Empty; + return SensedObject.Name; + + } + + public string llDetectedName(int number) + { + m_host.AddScriptLPS(1); + LLUUID sensedUUID = m_ScriptEngine.GetDetectID(m_itemID, number); + if(sensedUUID != null) + return resolveName(sensedUUID); + return String.Empty; + } + + public LLUUID uuidDetectedKey(int number) + { + return m_ScriptEngine.GetDetectID(m_itemID, number); + } + + public EntityBase entityDetectedKey(int number) + { + LLUUID sensedUUID = m_ScriptEngine.GetDetectID(m_itemID, number); + if(sensedUUID != null) + { + EntityBase SensedObject = null; + lock (World.Entities) + { + World.Entities.TryGetValue(sensedUUID, out SensedObject); + } + return SensedObject; + } + return null; + } + + public string llDetectedKey(int number) + { + m_host.AddScriptLPS(1); + LLUUID SensedUUID = uuidDetectedKey(number); + if (SensedUUID == LLUUID.Zero) + return String.Empty; + + return SensedUUID.ToString(); + } + + public string llDetectedOwner(int number) + { + // returns UUID of owner of object detected + m_host.AddScriptLPS(1); + EntityBase SensedObject = entityDetectedKey(number); + if (SensedObject ==null) + return String.Empty; + LLUUID SensedUUID = uuidDetectedKey(number); + if (World.GetScenePresence(SensedUUID) == null) + { + // sensed object is not an avatar + // so get the owner of the sensed object + SceneObjectPart SOP = World.GetSceneObjectPart(SensedUUID); + if (SOP != null) { return SOP.ObjectOwner.ToString(); } + } + else + { + // sensed object is an avatar, and so must be its own owner + return SensedUUID.ToString(); + } + + + return String.Empty; + + } + + public LSL_Types.LSLInteger llDetectedType(int number) + { + m_host.AddScriptLPS(1); + EntityBase SensedObject = entityDetectedKey(number); + if (SensedObject == null) + return 0; + int mask = 0; + + LLUUID SensedUUID = uuidDetectedKey(number); + LSL_Types.Vector3 ZeroVector = new LSL_Types.Vector3(0, 0, 0); + + if (World.GetScenePresence(SensedUUID) != null) mask |= 0x01; // actor + if (SensedObject.Velocity.Equals(ZeroVector)) + mask |= 0x04; // passive non-moving + else + mask |= 0x02; // active moving + if (SensedObject is IScript) mask |= 0x08; // Scripted. It COULD have one hidden ... + return mask; + + } + + public LSL_Types.Vector3 llDetectedPos(int number) + { + m_host.AddScriptLPS(1); + EntityBase SensedObject = entityDetectedKey(number); + if (SensedObject == null) + return new LSL_Types.Vector3(0, 0, 0); + + return new LSL_Types.Vector3(SensedObject.AbsolutePosition.X,SensedObject.AbsolutePosition.Y,SensedObject.AbsolutePosition.Z); + } + + public LSL_Types.Vector3 llDetectedVel(int number) + { + m_host.AddScriptLPS(1); + EntityBase SensedObject = entityDetectedKey(number); + if (SensedObject == null) + return new LSL_Types.Vector3(0, 0, 0); + + return new LSL_Types.Vector3(SensedObject.Velocity.X, SensedObject.Velocity.Y, SensedObject.Velocity.Z); + // return new LSL_Types.Vector3(); + } + + public LSL_Types.Vector3 llDetectedGrab(int number) + { + m_host.AddScriptLPS(1); + XDetectParams parms = m_ScriptEngine.GetDetectParams(m_itemID, number); + + return parms.OffsetPos; + } + + public LSL_Types.Quaternion llDetectedRot(int number) + { + m_host.AddScriptLPS(1); + EntityBase SensedObject = entityDetectedKey(number); + if (SensedObject == null) + return new LSL_Types.Quaternion(); + + return new LSL_Types.Quaternion(SensedObject.Rotation.x, SensedObject.Rotation.y, SensedObject.Rotation.z, SensedObject.Rotation.w); + } + + public LSL_Types.LSLInteger llDetectedGroup(int number) + { + m_host.AddScriptLPS(1); + NotImplemented("llDetectedGroup"); + return 0; + } + + public LSL_Types.LSLInteger llDetectedLinkNumber(int number) + { + m_host.AddScriptLPS(1); + NotImplemented("llDetectedLinkNumber"); + return 0; + } + + public void llDie() + { + m_host.AddScriptLPS(1); + World.DeleteSceneObject(m_host.ParentGroup); + } + + public double llGround(LSL_Types.Vector3 offset) + { + m_host.AddScriptLPS(1); + int x = (int)(m_host.AbsolutePosition.X + offset.x); + int y = (int)(m_host.AbsolutePosition.Y + offset.y); + return World.GetLandHeight(x, y); + } + + public double llCloud(LSL_Types.Vector3 offset) + { + m_host.AddScriptLPS(1); + NotImplemented("llCloud"); + return 0; + } + + public LSL_Types.Vector3 llWind(LSL_Types.Vector3 offset) + { + m_host.AddScriptLPS(1); + NotImplemented("llWind"); + return new LSL_Types.Vector3(); + } + + public void llSetStatus(int status, int value) + { + m_host.AddScriptLPS(1); + + int statusrotationaxis = 0; + + if ((status & BuiltIn_Commands_BaseClass.STATUS_PHYSICS) == BuiltIn_Commands_BaseClass.STATUS_PHYSICS) + { + if (value == 1) + m_host.ScriptSetPhysicsStatus(true); + else + m_host.ScriptSetPhysicsStatus(false); + + } + if ((status & BuiltIn_Commands_BaseClass.STATUS_PHANTOM) == BuiltIn_Commands_BaseClass.STATUS_PHANTOM) + { + if (value == 1) + m_host.ScriptSetPhantomStatus(true); + else + m_host.ScriptSetPhantomStatus(false); + } + if ((status & BuiltIn_Commands_BaseClass.STATUS_CAST_SHADOWS) == BuiltIn_Commands_BaseClass.STATUS_CAST_SHADOWS) + { + m_host.AddFlag(LLObject.ObjectFlags.CastShadows); + } + if ((status & BuiltIn_Commands_BaseClass.STATUS_ROTATE_X) == BuiltIn_Commands_BaseClass.STATUS_ROTATE_X) + { + statusrotationaxis |= BuiltIn_Commands_BaseClass.STATUS_ROTATE_X; + + } + if ((status & BuiltIn_Commands_BaseClass.STATUS_ROTATE_Y) == BuiltIn_Commands_BaseClass.STATUS_ROTATE_Y) + { + statusrotationaxis |= BuiltIn_Commands_BaseClass.STATUS_ROTATE_Y; + } + if ((status & BuiltIn_Commands_BaseClass.STATUS_ROTATE_Z) == BuiltIn_Commands_BaseClass.STATUS_ROTATE_Z) + { + statusrotationaxis |= BuiltIn_Commands_BaseClass.STATUS_ROTATE_Z; + } + if ((status & BuiltIn_Commands_BaseClass.STATUS_BLOCK_GRAB) == BuiltIn_Commands_BaseClass.STATUS_BLOCK_GRAB) + { + NotImplemented("llSetStatus - STATUS_BLOCK_GRAB"); + } + if ((status & BuiltIn_Commands_BaseClass.STATUS_DIE_AT_EDGE) == BuiltIn_Commands_BaseClass.STATUS_DIE_AT_EDGE) + { + if (value == 1) + m_host.SetDieAtEdge(true); + else + m_host.SetDieAtEdge(false); + } + if ((status & BuiltIn_Commands_BaseClass.STATUS_RETURN_AT_EDGE) == BuiltIn_Commands_BaseClass.STATUS_RETURN_AT_EDGE) + { + NotImplemented("llSetStatus - STATUS_RETURN_AT_EDGE"); + } + if ((status & BuiltIn_Commands_BaseClass.STATUS_SANDBOX) == BuiltIn_Commands_BaseClass.STATUS_SANDBOX) + { + NotImplemented("llSetStatus - STATUS_SANDBOX"); + } + if (statusrotationaxis != 0) + { + m_host.SetAxisRotation(statusrotationaxis, value); + + } + } + + public LSL_Types.LSLInteger llGetStatus(int status) + { + m_host.AddScriptLPS(1); + // Console.WriteLine(m_host.UUID.ToString() + " status is " + m_host.GetEffectiveObjectFlags().ToString()); + switch (status) + { + case BuiltIn_Commands_BaseClass.STATUS_PHYSICS: + if ((m_host.GetEffectiveObjectFlags() & (uint)LLObject.ObjectFlags.Physics) == (uint)LLObject.ObjectFlags.Physics) + { + return 1; + } + return 0; + case BuiltIn_Commands_BaseClass.STATUS_PHANTOM: + if ((m_host.GetEffectiveObjectFlags() & (uint)LLObject.ObjectFlags.Phantom) == (uint)LLObject.ObjectFlags.Phantom) + { + return 1; + } + return 0; + case BuiltIn_Commands_BaseClass.STATUS_CAST_SHADOWS: + if ((m_host.GetEffectiveObjectFlags() & (uint)LLObject.ObjectFlags.CastShadows) == (uint)LLObject.ObjectFlags.CastShadows) + { + return 1; + } + return 0; + case BuiltIn_Commands_BaseClass.STATUS_BLOCK_GRAB: + NotImplemented("llGetStatus - STATUS_BLOCK_GRAB"); + return 0; + case BuiltIn_Commands_BaseClass.STATUS_DIE_AT_EDGE: + + if (m_host.GetDieAtEdge()) + return 1; + else + return 0; + + case BuiltIn_Commands_BaseClass.STATUS_RETURN_AT_EDGE: + NotImplemented("llGetStatus - STATUS_RETURN_AT_EDGE"); + return 0; + case BuiltIn_Commands_BaseClass.STATUS_ROTATE_X: + NotImplemented("llGetStatus - STATUS_ROTATE_X"); + return 0; + case BuiltIn_Commands_BaseClass.STATUS_ROTATE_Y: + NotImplemented("llGetStatus - STATUS_ROTATE_Y"); + return 0; + case BuiltIn_Commands_BaseClass.STATUS_ROTATE_Z: + NotImplemented("llGetStatus - STATUS_ROTATE_Z"); + return 0; + case BuiltIn_Commands_BaseClass.STATUS_SANDBOX: + NotImplemented("llGetStatus - STATUS_SANDBOX"); + return 0; + } + return 0; + } + + public void llSetScale(LSL_Types.Vector3 scale) + { + m_host.AddScriptLPS(1); + SetScale(m_host, scale); + } + + private void SetScale(SceneObjectPart part, LSL_Types.Vector3 scale) + { + // TODO: this needs to trigger a persistance save as well + LLVector3 tmp = part.Scale; + tmp.X = (float)scale.x; + tmp.Y = (float)scale.y; + tmp.Z = (float)scale.z; + part.Scale = tmp; + part.SendFullUpdateToAllClients(); + } + + public LSL_Types.Vector3 llGetScale() + { + m_host.AddScriptLPS(1); + return new LSL_Types.Vector3(m_host.Scale.X, m_host.Scale.Y, m_host.Scale.Z); + } + + public void llSetColor(LSL_Types.Vector3 color, int face) + { + m_host.AddScriptLPS(1); + + SetColor(m_host, color, face); + } + + private void SetColor(SceneObjectPart part, LSL_Types.Vector3 color, int face) + { + LLObject.TextureEntry tex = part.Shape.Textures; + LLColor texcolor; + if (face > -1) + { + texcolor = tex.CreateFace((uint)face).RGBA; + texcolor.R = (float)Math.Abs(color.x - 1); + texcolor.G = (float)Math.Abs(color.y - 1); + texcolor.B = (float)Math.Abs(color.z - 1); + tex.FaceTextures[face].RGBA = texcolor; + part.UpdateTexture(tex); + return; + } + else if (face == -1) + { + for (uint i = 0; i < 32; i++) + { + if (tex.FaceTextures[i] != null) + { + texcolor = tex.FaceTextures[i].RGBA; + texcolor.R = (float)Math.Abs(color.x - 1); + texcolor.G = (float)Math.Abs(color.y - 1); + texcolor.B = (float)Math.Abs(color.z - 1); + tex.FaceTextures[i].RGBA = texcolor; + } + texcolor = tex.DefaultTexture.RGBA; + texcolor.R = (float)Math.Abs(color.x - 1); + texcolor.G = (float)Math.Abs(color.y - 1); + texcolor.B = (float)Math.Abs(color.z - 1); + tex.DefaultTexture.RGBA = texcolor; + } + part.UpdateTexture(tex); + return; + } + } + + public double llGetAlpha(int face) + { + m_host.AddScriptLPS(1); + LLObject.TextureEntry tex = m_host.Shape.Textures; + if (face == -1) // TMP: Until we can determine number of sides, ALL_SIDES (-1) will return default color + { + return (double)((tex.DefaultTexture.RGBA.A * 255) / 255); + } + if (face > -1) + { + return (double)((tex.GetFace((uint)face).RGBA.A * 255) / 255); + } + return 0; + } + + public void llSetAlpha(double alpha, int face) + { + m_host.AddScriptLPS(1); + + SetAlpha(m_host, alpha, face); + } + + private void SetAlpha(SceneObjectPart part, double alpha, int face) + { + LLObject.TextureEntry tex = part.Shape.Textures; + LLColor texcolor; + if (face > -1) + { + texcolor = tex.CreateFace((uint)face).RGBA; + texcolor.A = (float)Math.Abs(alpha - 1); + tex.FaceTextures[face].RGBA = texcolor; + part.UpdateTexture(tex); + return; + } + else if (face == -1) + { + for (int i = 0; i < 32; i++) + { + if (tex.FaceTextures[i] != null) + { + texcolor = tex.FaceTextures[i].RGBA; + texcolor.A = (float)Math.Abs(alpha - 1); + tex.FaceTextures[i].RGBA = texcolor; + } + } + texcolor = tex.DefaultTexture.RGBA; + texcolor.A = (float)Math.Abs(alpha - 1); + tex.DefaultTexture.RGBA = texcolor; + part.UpdateTexture(tex); + return; + } + } + + public LSL_Types.Vector3 llGetColor(int face) + { + m_host.AddScriptLPS(1); + LLObject.TextureEntry tex = m_host.Shape.Textures; + LLColor texcolor; + LSL_Types.Vector3 rgb; + if (face == -1) // TMP: Until we can determine number of sides, ALL_SIDES (-1) will return default color + { + texcolor = tex.DefaultTexture.RGBA; + rgb.x = (255 - (texcolor.R * 255)) / 255; + rgb.y = (255 - (texcolor.G * 255)) / 255; + rgb.z = (255 - (texcolor.B * 255)) / 255; + return rgb; + } + if (face > -1) + { + texcolor = tex.GetFace((uint)face).RGBA; + rgb.x = (255 - (texcolor.R * 255)) / 255; + rgb.y = (255 - (texcolor.G * 255)) / 255; + rgb.z = (255 - (texcolor.B * 255)) / 255; + return rgb; + } + else + { + return new LSL_Types.Vector3(); + } + } + + public void llSetTexture(string texture, int face) + { + m_host.AddScriptLPS(1); + SetTexture(m_host, texture, face); + } + + private void SetTexture(SceneObjectPart part, string texture, int face) + { + LLUUID textureID=new LLUUID(); + + if (!LLUUID.TryParse(texture, out textureID)) + { + textureID=InventoryKey(texture, (int)AssetType.Texture); + } + + if (textureID == LLUUID.Zero) + return; + + LLObject.TextureEntry tex = part.Shape.Textures; + + if (face > -1) + { + LLObject.TextureEntryFace texface = tex.CreateFace((uint)face); + texface.TextureID = textureID; + tex.FaceTextures[face] = texface; + part.UpdateTexture(tex); + return; + } + else if (face == -1) + { + for (uint i = 0; i < 32; i++) + { + if (tex.FaceTextures[i] != null) + { + tex.FaceTextures[i].TextureID = textureID; + } + } + tex.DefaultTexture.TextureID = textureID; + part.UpdateTexture(tex); + return; + } + } + + public void llScaleTexture(double u, double v, int face) + { + m_host.AddScriptLPS(1); + + ScaleTexture(m_host, u, v, face); + } + + private void ScaleTexture(SceneObjectPart part, double u, double v, int face) + { + LLObject.TextureEntry tex = part.Shape.Textures; + if (face > -1) + { + LLObject.TextureEntryFace texface = tex.CreateFace((uint)face); + texface.RepeatU = (float)u; + texface.RepeatV = (float)v; + tex.FaceTextures[face] = texface; + part.UpdateTexture(tex); + return; + } + if (face == -1) + { + for (int i = 0; i < 32; i++) + { + if (tex.FaceTextures[i] != null) + { + tex.FaceTextures[i].RepeatU = (float)u; + tex.FaceTextures[i].RepeatV = (float)v; + } + } + tex.DefaultTexture.RepeatU = (float)u; + tex.DefaultTexture.RepeatV = (float)v; + part.UpdateTexture(tex); + return; + } + } + + public void llOffsetTexture(double u, double v, int face) + { + m_host.AddScriptLPS(1); + OffsetTexture(m_host, u, v, face); + } + + private void OffsetTexture(SceneObjectPart part, double u, double v, int face) + { + LLObject.TextureEntry tex = part.Shape.Textures; + if (face > -1) + { + LLObject.TextureEntryFace texface = tex.CreateFace((uint)face); + texface.OffsetU = (float)u; + texface.OffsetV = (float)v; + tex.FaceTextures[face] = texface; + part.UpdateTexture(tex); + return; + } + if (face == -1) + { + for (int i = 0; i < 32; i++) + { + if (tex.FaceTextures[i] != null) + { + tex.FaceTextures[i].OffsetU = (float)u; + tex.FaceTextures[i].OffsetV = (float)v; + } + } + tex.DefaultTexture.OffsetU = (float)u; + tex.DefaultTexture.OffsetV = (float)v; + part.UpdateTexture(tex); + return; + } + } + + public void llRotateTexture(double rotation, int face) + { + m_host.AddScriptLPS(1); + RotateTexture(m_host, rotation, face); + } + + private void RotateTexture(SceneObjectPart part, double rotation, int face) + { + LLObject.TextureEntry tex = part.Shape.Textures; + if (face > -1) + { + LLObject.TextureEntryFace texface = tex.CreateFace((uint)face); + texface.Rotation = (float)rotation; + tex.FaceTextures[face] = texface; + part.UpdateTexture(tex); + return; + } + if (face == -1) + { + for (int i = 0; i < 32; i++) + { + if (tex.FaceTextures[i] != null) + { + tex.FaceTextures[i].Rotation = (float)rotation; + } + } + tex.DefaultTexture.Rotation = (float)rotation; + part.UpdateTexture(tex); + return; + } + } + + public string llGetTexture(int face) + { + m_host.AddScriptLPS(1); + LLObject.TextureEntry tex = m_host.Shape.Textures; + if (face == -1) + { + face = 0; + } + if (face > -1) + { + LLObject.TextureEntryFace texface; + texface = tex.GetFace((uint)face); + return texface.TextureID.ToString(); + } + else + { + return String.Empty; + } + } + + public void llSetPos(LSL_Types.Vector3 pos) + { + m_host.AddScriptLPS(1); + + SetPos(m_host, pos); + } + + private void SetPos(SceneObjectPart part, LSL_Types.Vector3 pos) + { + if (part.ParentID != 0) + { + part.UpdateOffSet(new LLVector3((float)pos.x, (float)pos.y, (float)pos.z)); + } + else + { + part.UpdateGroupPosition(new LLVector3((float)pos.x, (float)pos.y, (float)pos.z)); + } + } + + public LSL_Types.Vector3 llGetPos() + { + m_host.AddScriptLPS(1); + return new LSL_Types.Vector3(m_host.AbsolutePosition.X, + m_host.AbsolutePosition.Y, + m_host.AbsolutePosition.Z); + } + + public LSL_Types.Vector3 llGetLocalPos() + { + m_host.AddScriptLPS(1); + if (m_host.ParentID != 0) + { + return new LSL_Types.Vector3(m_host.OffsetPosition.X, + m_host.OffsetPosition.Y, + m_host.OffsetPosition.Z); + } + else + { + return new LSL_Types.Vector3(m_host.AbsolutePosition.X, + m_host.AbsolutePosition.Y, + m_host.AbsolutePosition.Z); + } + } + + public void llSetRot(LSL_Types.Quaternion rot) + { + m_host.AddScriptLPS(1); + + SetRot(m_host, rot); + } + + private void SetRot(SceneObjectPart part, LSL_Types.Quaternion rot) + { + part.UpdateRotation(new LLQuaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s)); + // Update rotation does not move the object in the physics scene if it's a linkset. + part.ParentGroup.AbsolutePosition = part.ParentGroup.AbsolutePosition; + } + + public LSL_Types.Quaternion llGetRot() + { + m_host.AddScriptLPS(1); + LLQuaternion q = m_host.RotationOffset; + return new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W); + } + + public LSL_Types.Quaternion llGetLocalRot() + { + m_host.AddScriptLPS(1); + return new LSL_Types.Quaternion(m_host.RotationOffset.X, m_host.RotationOffset.Y, m_host.RotationOffset.Z, m_host.RotationOffset.W); + } + + public void llSetForce(LSL_Types.Vector3 force, int local) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetForce"); + } + + public LSL_Types.Vector3 llGetForce() + { + m_host.AddScriptLPS(1); + NotImplemented("llGetForce"); + return new LSL_Types.Vector3(); + } + + public LSL_Types.LSLInteger llTarget(LSL_Types.Vector3 position, double range) + { + m_host.AddScriptLPS(1); + return m_host.registerTargetWaypoint(new LLVector3((float)position.x, (float)position.y, (float)position.z), (float)range); + + } + + public void llTargetRemove(int number) + { + m_host.AddScriptLPS(1); + m_host.unregisterTargetWaypoint(number); + } + + public LSL_Types.LSLInteger llRotTarget(LSL_Types.Quaternion rot, double error) + { + m_host.AddScriptLPS(1); + NotImplemented("llRotTarget"); + return 0; + } + + public void llRotTargetRemove(int number) + { + m_host.AddScriptLPS(1); + NotImplemented("llRotTargetRemove"); + } + + public void llMoveToTarget(LSL_Types.Vector3 target, double tau) + { + m_host.AddScriptLPS(1); + m_host.MoveToTarget(new LLVector3((float)target.x, (float)target.y, (float)target.z), (float)tau); + } + + public void llStopMoveToTarget() + { + m_host.AddScriptLPS(1); + m_host.StopMoveToTarget(); + } + + public void llApplyImpulse(LSL_Types.Vector3 force, int local) + { + m_host.AddScriptLPS(1); + //No energy force yet + + if (force.x > 20000) + force.x = 20000; + if (force.y > 20000) + force.y = 20000; + if (force.z > 20000) + force.z = 20000; + + if (local == 1) + { + m_host.ApplyImpulse(new LLVector3((float)force.x, (float)force.y, (float)force.z), true); + } + else + { + + m_host.ApplyImpulse(new LLVector3((float)force.x,(float)force.y,(float)force.z), false); + } + } + + public void llApplyRotationalImpulse(LSL_Types.Vector3 force, int local) + { + m_host.AddScriptLPS(1); + NotImplemented("llApplyRotationalImpulse"); + } + + public void llSetTorque(LSL_Types.Vector3 torque, int local) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetTorque"); + } + + public LSL_Types.Vector3 llGetTorque() + { + m_host.AddScriptLPS(1); + NotImplemented("llGetTorque"); + return new LSL_Types.Vector3(); + } + + public void llSetForceAndTorque(LSL_Types.Vector3 force, LSL_Types.Vector3 torque, int local) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetForceAndTorque"); + } + + public LSL_Types.Vector3 llGetVel() + { + m_host.AddScriptLPS(1); + return new LSL_Types.Vector3(m_host.Velocity.X, m_host.Velocity.Y, m_host.Velocity.Z); + } + + public LSL_Types.Vector3 llGetAccel() + { + m_host.AddScriptLPS(1); + return new LSL_Types.Vector3(m_host.Acceleration.X, m_host.Acceleration.Y, m_host.Acceleration.Z); + } + + public LSL_Types.Vector3 llGetOmega() + { + m_host.AddScriptLPS(1); + return new LSL_Types.Vector3(m_host.RotationalVelocity.X, m_host.RotationalVelocity.Y, m_host.RotationalVelocity.Z); + } + + public double llGetTimeOfDay() + { + m_host.AddScriptLPS(1); + NotImplemented("llGetTimeOfDay"); + return 0; + } + + public double llGetWallclock() + { + m_host.AddScriptLPS(1); + return DateTime.Now.TimeOfDay.TotalSeconds; + } + + public double llGetTime() + { + m_host.AddScriptLPS(1); + TimeSpan ScriptTime = DateTime.Now - m_timer; + return (double)((ScriptTime.TotalMilliseconds / 1000)*World.TimeDilation); + } + + public void llResetTime() + { + m_host.AddScriptLPS(1); + m_timer = DateTime.Now; + } + + public double llGetAndResetTime() + { + m_host.AddScriptLPS(1); + TimeSpan ScriptTime = DateTime.Now - m_timer; + m_timer = DateTime.Now; + return (double)((ScriptTime.TotalMilliseconds / 1000)*World.TimeDilation); + } + + public void llSound() + { + m_host.AddScriptLPS(1); + // This function has been deprecated + // see http://www.lslwiki.net/lslwiki/wakka.php?wakka=llSound + Deprecated("llSound"); + } + + public void llPlaySound(string sound, double volume) + { + m_host.AddScriptLPS(1); + m_host.SendSound(sound, volume, false, 0); + } + + public void llLoopSound(string sound, double volume) + { + m_host.AddScriptLPS(1); + m_host.SendSound(sound, volume, false, 1); + } + + public void llLoopSoundMaster(string sound, double volume) + { + m_host.AddScriptLPS(1); + NotImplemented("llLoopSoundMaster"); + } + + public void llLoopSoundSlave(string sound, double volume) + { + m_host.AddScriptLPS(1); + NotImplemented("llLoopSoundSlave"); + } + + public void llPlaySoundSlave(string sound, double volume) + { + m_host.AddScriptLPS(1); + NotImplemented("llPlaySoundSlave"); + } + + public void llTriggerSound(string sound, double volume) + { + m_host.AddScriptLPS(1); + m_host.SendSound(sound, volume, true, 0); + } + + public void llStopSound() + { + m_host.AddScriptLPS(1); + m_host.SendSound(LLUUID.Zero.ToString(), 1.0, false, 2); + } + + public void llPreloadSound(string sound) + { + m_host.AddScriptLPS(1); + m_host.PreloadSound(sound); + } + + /// + /// Return a portion of the designated string bounded by + /// inclusive indices (start and end). As usual, the negative + /// indices, and the tolerance for out-of-bound values, makes + /// this more complicated than it might otherwise seem. + /// + + public string llGetSubString(string src, int start, int end) + { + + m_host.AddScriptLPS(1); + + // Normalize indices (if negative). + // After normlaization they may still be + // negative, but that is now relative to + // the start, rather than the end, of the + // sequence. + + if (start < 0) + { + start = src.Length+start; + } + if (end < 0) + { + end = src.Length+end; + } + + // Conventional substring + if (start <= end) + { + // Implies both bounds are out-of-range. + if (end < 0 || start >= src.Length) + { + return String.Empty; + } + // If end is positive, then it directly + // corresponds to the lengt of the substring + // needed (plus one of course). BUT, it + // must be within bounds. + if (end >= src.Length) + { + end = src.Length-1; + } + + if (start < 0) + { + return src.Substring(0,end+1); + } + // Both indices are positive + return src.Substring(start, (end+1) - start); + } + + // Inverted substring (end < start) + else + { + // Implies both indices are below the + // lower bound. In the inverted case, that + // means the entire string will be returned + // unchanged. + if (start < 0) + { + return src; + } + // If both indices are greater than the upper + // bound the result may seem initially counter + // intuitive. + if (end >= src.Length) + { + return src; + } + + if (end < 0) + { + if (start < src.Length) + { + return src.Substring(start); + } + else + { + return String.Empty; + } + } + else + { + if (start < src.Length) + { + return src.Substring(0,end+1) + src.Substring(start); + } + else + { + return src.Substring(0,end+1); + } + } + } + } + + /// + /// Delete substring removes the specified substring bounded + /// by the inclusive indices start and end. Indices may be + /// negative (indicating end-relative) and may be inverted, + /// i.e. end < start. + /// + + public string llDeleteSubString(string src, int start, int end) + { + + m_host.AddScriptLPS(1); + + // Normalize indices (if negative). + // After normlaization they may still be + // negative, but that is now relative to + // the start, rather than the end, of the + // sequence. + if (start < 0) + { + start = src.Length+start; + } + if (end < 0) + { + end = src.Length+end; + } + // Conventionally delimited substring + if (start <= end) + { + // If both bounds are outside of the existing + // string, then return unchanges. + if (end < 0 || start >= src.Length) + { + return src; + } + // At least one bound is in-range, so we + // need to clip the out-of-bound argument. + if (start < 0) + { + start = 0; + } + + if (end >= src.Length) + { + end = src.Length-1; + } + + return src.Remove(start,end-start+1); + } + // Inverted substring + else + { + // In this case, out of bounds means that + // the existing string is part of the cut. + if (start < 0 || end >= src.Length) + { + return String.Empty; + } + + if (end > 0) + { + if (start < src.Length) + { + return src.Remove(start).Remove(0,end+1); + } + else + { + return src.Remove(0,end+1); + } + } + else + { + if (start < src.Length) + { + return src.Remove(start); + } + else + { + return src; + } + } + } + } + + /// + /// Insert string inserts the specified string identified by src + /// at the index indicated by index. Index may be negative, in + /// which case it is end-relative. The index may exceed either + /// string bound, with the result being a concatenation. + /// + + public string llInsertString(string dest, int index, string src) + { + + m_host.AddScriptLPS(1); + + // Normalize indices (if negative). + // After normlaization they may still be + // negative, but that is now relative to + // the start, rather than the end, of the + // sequence. + if (index < 0) + { + index = dest.Length+index; + + // Negative now means it is less than the lower + // bound of the string. + + if (index < 0) + { + return src+dest; + } + + } + + if (index >= dest.Length) + { + return dest+src; + } + + // The index is in bounds. + // In this case the index refers to the index that will + // be assigned to the first character of the inserted string. + // So unlike the other string operations, we do not add one + // to get the correct string length. + return dest.Substring(0,index)+src+dest.Substring(index); + + } + + public string llToUpper(string src) + { + m_host.AddScriptLPS(1); + return src.ToUpper(); + } + + public string llToLower(string src) + { + m_host.AddScriptLPS(1); + return src.ToLower(); + } + + public LSL_Types.LSLInteger llGiveMoney(string destination, int amount) + { + LLUUID invItemID=InventorySelf(); + if (invItemID == LLUUID.Zero) + return 0; + + m_host.AddScriptLPS(1); + + if (m_host.TaskInventory[invItemID].PermsGranter == LLUUID.Zero) + return 0; + + if ((m_host.TaskInventory[invItemID].PermsMask & BuiltIn_Commands_BaseClass.PERMISSION_DEBIT) == 0) + { + LSLError("No permissions to give money"); + return 0; + } + + LLUUID toID=new LLUUID(); + + if (!LLUUID.TryParse(destination, out toID)) + { + LSLError("Bad key in llGiveMoney"); + return 0; + } + + IMoneyModule money=World.RequestModuleInterface(); + + if (money == null) + { + NotImplemented("llGiveMoney"); + return 0; + } + + bool result=money.ObjectGiveMoney(m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount); + + if (result) + return 1; + + return 0; + } + + public void llMakeExplosion() + { + m_host.AddScriptLPS(1); + NotImplemented("llMakeExplosion"); + } + + public void llMakeFountain() + { + m_host.AddScriptLPS(1); + NotImplemented("llMakeFountain"); + } + + public void llMakeSmoke() + { + m_host.AddScriptLPS(1); + NotImplemented("llMakeSmoke"); + } + + public void llMakeFire() + { + m_host.AddScriptLPS(1); + NotImplemented("llMakeFire"); + } + + public void llRezObject(string inventory, LSL_Types.Vector3 pos, LSL_Types.Vector3 vel, LSL_Types.Quaternion rot, int param) + { + m_host.AddScriptLPS(1); + //NotImplemented("llRezObject"); + bool found = false; + + // Instead of using return;, I'm using continue; because in our TaskInventory implementation + // it's possible to have two items with the same task inventory name. + // this is an easter egg of sorts. + + foreach (KeyValuePair inv in m_host.TaskInventory) + { + if (inv.Value.Name == inventory) + { + // make sure we're an object. + if (inv.Value.InvType != (int)InventoryType.Object) + { + llSay(0, "Unable to create requested object. Object is missing from database."); + continue; + } + + LLVector3 llpos = new LLVector3((float)pos.x, (float)pos.y, (float)pos.z); + + // test if we're further away then 10m + if (Util.GetDistanceTo(llpos, m_host.AbsolutePosition) > 10) + return; // wiki says, if it's further away then 10m, silently fail. + + LLVector3 llvel = new LLVector3((float)vel.x, (float)vel.y, (float)vel.z); + + // need the magnitude later + float velmag = (float)Util.GetMagnitude(llvel); + + SceneObjectGroup new_group = World.RezObject(inv.Value, llpos, new LLQuaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s), llvel, param); + + // If either of these are null, then there was an unknown error. + if (new_group == null) + continue; + if (new_group.RootPart == null) + continue; + + // objects rezzed with this method are die_at_edge by default. + new_group.RootPart.SetDieAtEdge(true); + + m_ScriptEngine.PostScriptEvent(m_itemID, new XEventParams( + "object_rez", new Object[] { + new LSL_Types.LSLString( + new_group.RootPart.UUID.ToString()) }, + new XDetectParams[0])); + + float groupmass = new_group.GetMass(); + + //Recoil. + llApplyImpulse(new LSL_Types.Vector3(llvel.X * groupmass, llvel.Y * groupmass, llvel.Z * groupmass), 0); + found = true; + //script delay + System.Threading.Thread.Sleep((int)((groupmass * velmag) / 10)); + break; + } + } + if (!found) + llSay(0, "Could not find object " + inventory); + } + + public void llLookAt(LSL_Types.Vector3 target, double strength, double damping) + { + m_host.AddScriptLPS(1); + NotImplemented("llLookAt"); + } + + public void llStopLookAt() + { + m_host.AddScriptLPS(1); + NotImplemented("llStopLookAt"); + } + + public void llSetTimerEvent(double sec) + { + m_host.AddScriptLPS(1); + // Setting timer repeat + m_ScriptEngine.m_ASYNCLSLCommandManager.m_Timer.SetTimerEvent(m_localID, m_itemID, sec); + } + + public void llSleep(double sec) + { + m_host.AddScriptLPS(1); + Thread.Sleep((int)(sec * 1000)); + } + + public double llGetMass() + { + m_host.AddScriptLPS(1); + return m_host.GetMass(); + } + + public void llCollisionFilter(string name, string id, int accept) + { + m_host.AddScriptLPS(1); + NotImplemented("llCollisionFilter"); + } + + public void llTakeControls(int controls, int accept, int pass_on) + { + if (!m_host.TaskInventory.ContainsKey(InventorySelf())) + { + return; + } + + if (m_host.TaskInventory[InventorySelf()].PermsGranter != LLUUID.Zero) + { + ScenePresence presence = World.GetScenePresence(m_host.TaskInventory[InventorySelf()].PermsGranter); + + if (presence != null) + { + if ((m_host.TaskInventory[InventorySelf()].PermsMask & BuiltIn_Commands_BaseClass.PERMISSION_TAKE_CONTROLS) != 0) + { + presence.RegisterControlEventsToScript(controls, accept, pass_on, m_localID, m_itemID); + + } + } + } + + m_host.AddScriptLPS(1); + //NotImplemented("llTakeControls"); + } + + public void llReleaseControls() + { + m_host.AddScriptLPS(1); + + if (!m_host.TaskInventory.ContainsKey(InventorySelf())) + { + return; + } + + if (m_host.TaskInventory[InventorySelf()].PermsGranter != LLUUID.Zero) + { + ScenePresence presence = World.GetScenePresence(m_host.TaskInventory[InventorySelf()].PermsGranter); + + if (presence != null) + { + if ((m_host.TaskInventory[InventorySelf()].PermsMask & BuiltIn_Commands_BaseClass.PERMISSION_TAKE_CONTROLS) != 0) + { + // Unregister controls from Presence + presence.UnRegisterControlEventsToScript(m_localID, m_itemID); + // Remove Take Control permission. + m_host.TaskInventory[InventorySelf()].PermsMask &= ~BuiltIn_Commands_BaseClass.PERMISSION_TAKE_CONTROLS; + } + } + } + } + + public void llAttachToAvatar(int attachment) + { + m_host.AddScriptLPS(1); + NotImplemented("llAttachToAvatar"); + } + + public void llDetachFromAvatar() + { + m_host.AddScriptLPS(1); + NotImplemented("llDetachFromAvatar"); + } + + public void llTakeCamera() + { + m_host.AddScriptLPS(1); + NotImplemented("llTakeCamera"); + } + + public void llReleaseCamera() + { + m_host.AddScriptLPS(1); + NotImplemented("llReleaseCamera"); + } + + public string llGetOwner() + { + m_host.AddScriptLPS(1); + + return m_host.ObjectOwner.ToString(); + } + + public void llInstantMessage(string user, string message) + { + m_host.AddScriptLPS(1); + + // We may be able to use ClientView.SendInstantMessage here, but we need a client instance. + // InstantMessageModule.OnInstantMessage searches through a list of scenes for a client matching the toAgent, + // but I don't think we have a list of scenes available from here. + // (We also don't want to duplicate the code in OnInstantMessage if we can avoid it.) + + // user is a UUID + + // TODO: figure out values for client, fromSession, and imSessionID + // client.SendInstantMessage(m_host.UUID, fromSession, message, user, imSessionID, m_host.Name, AgentManager.InstantMessageDialog.MessageFromAgent, (uint)Util.UnixTimeSinceEpoch()); + LLUUID friendTransactionID = LLUUID.Random(); + + //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID); + + GridInstantMessage msg = new GridInstantMessage(); + msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.UUID; + msg.fromAgentSession = new Guid(friendTransactionID.ToString());// fromAgentSession.UUID; + msg.toAgentID = new Guid(user); // toAgentID.UUID; + msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here + Console.WriteLine("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message); + Console.WriteLine("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString()); + msg.timestamp = (uint)Util.UnixTimeSinceEpoch();// timestamp; + //if (client != null) + //{ + msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName; + //} + //else + //{ + // msg.fromAgentName = "(hippos)";// Added for posterity. This means that we can't figure out who sent it + //} + msg.message = message; + msg.dialog = (byte)19; // messgage from script ??? // dialog; + msg.fromGroup = false;// fromGroup; + msg.offline = (byte)0; //offline; + msg.ParentEstateID = 0; //ParentEstateID; + msg.Position = new sLLVector3();// new sLLVector3(m_host.AbsolutePosition); + msg.RegionID = World.RegionInfo.RegionID.UUID;//RegionID.UUID; + msg.binaryBucket = new byte[0];// binaryBucket; + World.TriggerGridInstantMessage(msg, InstantMessageReceiver.IMModule); + // NotImplemented("llInstantMessage"); + } + + public void llEmail(string address, string subject, string message) + { + m_host.AddScriptLPS(1); + NotImplemented("llEmail"); + } + + public void llGetNextEmail(string address, string subject) + { + m_host.AddScriptLPS(1); + NotImplemented("llGetNextEmail"); + } + + public string llGetKey() + { + m_host.AddScriptLPS(1); + return m_host.UUID.ToString(); + } + + public void llSetBuoyancy(double buoyancy) + { + m_host.AddScriptLPS(1); + if (m_host.ParentGroup != null) + { + if (m_host.ParentGroup.RootPart != null) + { + m_host.ParentGroup.RootPart.SetBuoyancy((float)buoyancy); + } + } + } + + + + public void llSetHoverHeight(double height, int water, double tau) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetHoverHeight"); + } + + public void llStopHover() + { + m_host.AddScriptLPS(1); + NotImplemented("llStopHover"); + } + + public void llMinEventDelay(double delay) + { + m_host.AddScriptLPS(1); + NotImplemented("llMinEventDelay"); + } + + public void llSoundPreload() + { + m_host.AddScriptLPS(1); + NotImplemented("llSoundPreload"); + } + + public void llRotLookAt(LSL_Types.Quaternion target, double strength, double damping) + { + m_host.AddScriptLPS(1); + NotImplemented("llRotLookAt"); + } + + public LSL_Types.LSLInteger llStringLength(string str) + { + m_host.AddScriptLPS(1); + if (str.Length > 0) + { + return str.Length; + } + else + { + return 0; + } + } + + public void llStartAnimation(string anim) + { + m_host.AddScriptLPS(1); + + LLUUID invItemID=InventorySelf(); + if (invItemID == LLUUID.Zero) + return; + + if (m_host.TaskInventory[invItemID].PermsGranter == LLUUID.Zero) + return; + + if ((m_host.TaskInventory[invItemID].PermsMask & BuiltIn_Commands_BaseClass.PERMISSION_TRIGGER_ANIMATION) != 0) + { + ScenePresence presence = World.GetScenePresence(m_host.TaskInventory[invItemID].PermsGranter); + + if (presence != null) + { + // Do NOT try to parse LLUUID, animations cannot be triggered by ID + LLUUID animID=InventoryKey(anim, (int)AssetType.Animation); + if (animID == LLUUID.Zero) + presence.AddAnimation(anim); + else + presence.AddAnimation(animID); + } + } + } + + public void llStopAnimation(string anim) + { + m_host.AddScriptLPS(1); + + LLUUID invItemID=InventorySelf(); + if (invItemID == LLUUID.Zero) + return; + + if (m_host.TaskInventory[invItemID].PermsGranter == LLUUID.Zero) + return; + + if ((m_host.TaskInventory[invItemID].PermsMask & BuiltIn_Commands_BaseClass.PERMISSION_TRIGGER_ANIMATION) != 0) + { + LLUUID animID = new LLUUID(); + + if (!LLUUID.TryParse(anim, out animID)) + { + animID=InventoryKey(anim); + } + + if (animID == LLUUID.Zero) + return; + + ScenePresence presence = World.GetScenePresence(m_host.TaskInventory[invItemID].PermsGranter); + + if (presence != null) + { + if (animID == LLUUID.Zero) + presence.RemoveAnimation(anim); + else + presence.RemoveAnimation(animID); + } + } + } + + public void llPointAt() + { + m_host.AddScriptLPS(1); + NotImplemented("llPointAt"); + } + + public void llStopPointAt() + { + m_host.AddScriptLPS(1); + NotImplemented("llStopPointAt"); + } + + public void llTargetOmega(LSL_Types.Vector3 axis, double spinrate, double gain) + { + m_host.AddScriptLPS(1); + m_host.RotationalVelocity = new LLVector3((float)(axis.x * spinrate), (float)(axis.y * spinrate), (float)(axis.z * spinrate)); + m_host.AngularVelocity = new LLVector3((float)(axis.x * spinrate), (float)(axis.y * spinrate), (float)(axis.z * spinrate)); + m_host.ScheduleTerseUpdate(); + m_host.SendTerseUpdateToAllClients(); + } + + public LSL_Types.LSLInteger llGetStartParameter() + { + m_host.AddScriptLPS(1); + // NotImplemented("llGetStartParameter"); + return m_host.ParentGroup.StartParameter; + } + + public void llGodLikeRezObject(string inventory, LSL_Types.Vector3 pos) + { + m_host.AddScriptLPS(1); + NotImplemented("llGodLikeRezObject"); + } + + public void llRequestPermissions(string agent, int perm) + { + LLUUID agentID=new LLUUID(); + + if (!LLUUID.TryParse(agent, out agentID)) + return; + + LLUUID invItemID=InventorySelf(); + + if (invItemID == LLUUID.Zero) + return; // Not in a prim? How?? + + if (agentID == LLUUID.Zero || perm == 0) // Releasing permissions + { + m_host.TaskInventory[invItemID].PermsGranter=LLUUID.Zero; + m_host.TaskInventory[invItemID].PermsMask=0; + + m_ScriptEngine.PostScriptEvent(m_itemID, new XEventParams( + "run_time_permissions", new Object[] { + new LSL_Types.LSLInteger(0) }, + new XDetectParams[0])); + + return; + } + + m_host.AddScriptLPS(1); + + if (m_host.ParentGroup.RootPart.m_IsAttachment && agent == m_host.ParentGroup.RootPart.m_attachedAvatar) + { + // When attached, certain permissions are implicit if requested from owner + int implicitPerms = BuiltIn_Commands_BaseClass.PERMISSION_TAKE_CONTROLS | + BuiltIn_Commands_BaseClass.PERMISSION_TRIGGER_ANIMATION | + BuiltIn_Commands_BaseClass.PERMISSION_ATTACH; + + if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms + { + m_host.TaskInventory[invItemID].PermsGranter=agentID; + m_host.TaskInventory[invItemID].PermsMask=perm; + + m_ScriptEngine.PostScriptEvent(m_itemID, new XEventParams( + "run_time_permissions", new Object[] { + new LSL_Types.LSLInteger(perm) }, + new XDetectParams[0])); + + return; + } + } + else if (m_host.m_sitTargetAvatar == agentID) // Sitting avatar + { + // When agent is sitting, certain permissions are implicit if requested from sitting agent + int implicitPerms = BuiltIn_Commands_BaseClass.PERMISSION_TRIGGER_ANIMATION | + BuiltIn_Commands_BaseClass.PERMISSION_TRACK_CAMERA; + + if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms + { + m_host.TaskInventory[invItemID].PermsGranter=agentID; + m_host.TaskInventory[invItemID].PermsMask=perm; + + m_ScriptEngine.PostScriptEvent(m_itemID, new XEventParams( + "run_time_permissions", new Object[] { + new LSL_Types.LSLInteger(perm) }, + new XDetectParams[0])); + + return; + } + } + + ScenePresence presence = World.GetScenePresence(agentID); + + if (presence != null) + { + string ownerName=resolveName(m_host.ParentGroup.RootPart.OwnerID); + if (ownerName == String.Empty) + ownerName="(hippos)"; + + if (!m_waitingForScriptAnswer) + { + m_host.TaskInventory[invItemID].PermsGranter=agentID; + m_host.TaskInventory[invItemID].PermsMask=0; + presence.ControllingClient.OnScriptAnswer+=handleScriptAnswer; + m_waitingForScriptAnswer=true; + } + + presence.ControllingClient.SendScriptQuestion(m_host.UUID, m_host.ParentGroup.RootPart.Name, ownerName, invItemID, perm); + return; + } + + // Requested agent is not in range, refuse perms + m_ScriptEngine.PostScriptEvent(m_itemID, new XEventParams( + "run_time_permissions", new Object[] { + new LSL_Types.LSLInteger(0) }, + new XDetectParams[0])); + } + + void handleScriptAnswer(IClientAPI client, LLUUID taskID, LLUUID itemID, int answer) + { + if (taskID != m_host.UUID) + return; + + LLUUID invItemID=InventorySelf(); + + if (invItemID == LLUUID.Zero) + return; + + client.OnScriptAnswer-=handleScriptAnswer; + m_waitingForScriptAnswer=false; + + m_host.TaskInventory[invItemID].PermsMask=answer; + m_ScriptEngine.PostScriptEvent(m_itemID, new XEventParams( + "run_time_permissions", new Object[] { + new LSL_Types.LSLInteger(answer) }, + new XDetectParams[0])); + } + + public string llGetPermissionsKey() + { + m_host.AddScriptLPS(1); + + foreach (TaskInventoryItem item in m_host.TaskInventory.Values) + { + if (item.Type == 10 && item.ItemID == m_itemID) + { + return item.PermsGranter.ToString(); + } + } + + return LLUUID.Zero.ToString(); + } + + public LSL_Types.LSLInteger llGetPermissions() + { + m_host.AddScriptLPS(1); + + foreach (TaskInventoryItem item in m_host.TaskInventory.Values) + { + if (item.Type == 10 && item.ItemID == m_itemID) + { + return item.PermsMask; + } + } + + return 0; + } + + public LSL_Types.LSLInteger llGetLinkNumber() + { + m_host.AddScriptLPS(1); + + if (m_host.ParentGroup.Children.Count > 0) + { + return m_host.LinkNum + 1; + } + else + { + return 0; + } + } + + public void llSetLinkColor(int linknumber, LSL_Types.Vector3 color, int face) + { + m_host.AddScriptLPS(1); + SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknumber); + if (linknumber > -1) + { + LLObject.TextureEntry tex = part.Shape.Textures; + LLColor texcolor; + if (face > -1) + { + texcolor = tex.CreateFace((uint)face).RGBA; + texcolor.R = (float)Math.Abs(color.x - 1); + texcolor.G = (float)Math.Abs(color.y - 1); + texcolor.B = (float)Math.Abs(color.z - 1); + tex.FaceTextures[face].RGBA = texcolor; + part.UpdateTexture(tex); + return; + } + else if (face == -1) + { + texcolor = tex.DefaultTexture.RGBA; + texcolor.R = (float)Math.Abs(color.x - 1); + texcolor.G = (float)Math.Abs(color.y - 1); + texcolor.B = (float)Math.Abs(color.z - 1); + tex.DefaultTexture.RGBA = texcolor; + for (uint i = 0; i < 32; i++) + { + if (tex.FaceTextures[i] != null) + { + texcolor = tex.FaceTextures[i].RGBA; + texcolor.R = (float)Math.Abs(color.x - 1); + texcolor.G = (float)Math.Abs(color.y - 1); + texcolor.B = (float)Math.Abs(color.z - 1); + tex.FaceTextures[i].RGBA = texcolor; + } + } + texcolor = tex.DefaultTexture.RGBA; + texcolor.R = (float)Math.Abs(color.x - 1); + texcolor.G = (float)Math.Abs(color.y - 1); + texcolor.B = (float)Math.Abs(color.z - 1); + tex.DefaultTexture.RGBA = texcolor; + part.UpdateTexture(tex); + return; + } + return; + } + else if (linknumber == -1) + { + int num = m_host.ParentGroup.PrimCount; + for (int w = 0; w < num; w++) + { + linknumber = w; + part = m_host.ParentGroup.GetLinkNumPart(linknumber); + LLObject.TextureEntry tex = part.Shape.Textures; + LLColor texcolor; + if (face > -1) + { + texcolor = tex.CreateFace((uint)face).RGBA; + texcolor.R = (float)Math.Abs(color.x - 1); + texcolor.G = (float)Math.Abs(color.y - 1); + texcolor.B = (float)Math.Abs(color.z - 1); + tex.FaceTextures[face].RGBA = texcolor; + part.UpdateTexture(tex); + } + else if (face == -1) + { + texcolor = tex.DefaultTexture.RGBA; + texcolor.R = (float)Math.Abs(color.x - 1); + texcolor.G = (float)Math.Abs(color.y - 1); + texcolor.B = (float)Math.Abs(color.z - 1); + tex.DefaultTexture.RGBA = texcolor; + for (uint i = 0; i < 32; i++) + { + if (tex.FaceTextures[i] != null) + { + texcolor = tex.FaceTextures[i].RGBA; + texcolor.R = (float)Math.Abs(color.x - 1); + texcolor.G = (float)Math.Abs(color.y - 1); + texcolor.B = (float)Math.Abs(color.z - 1); + tex.FaceTextures[i].RGBA = texcolor; + } + } + texcolor = tex.DefaultTexture.RGBA; + texcolor.R = (float)Math.Abs(color.x - 1); + texcolor.G = (float)Math.Abs(color.y - 1); + texcolor.B = (float)Math.Abs(color.z - 1); + tex.DefaultTexture.RGBA = texcolor; + part.UpdateTexture(tex); + } + } + return; + } + } + + public void llCreateLink(string target, int parent) + { + m_host.AddScriptLPS(1); + NotImplemented("llCreateLink"); + } + + public void llBreakLink(int linknum) + { + m_host.AddScriptLPS(1); + NotImplemented("llBreakLink"); + } + + public void llBreakAllLinks() + { + m_host.AddScriptLPS(1); + NotImplemented("llBreakAllLinks"); + } + + public string llGetLinkKey(int linknum) + { + m_host.AddScriptLPS(1); + SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum); + if (part != null) + { + return part.UUID.ToString(); + } + else + { + return LLUUID.Zero.ToString(); + } + } + + public string llGetLinkName(int linknum) + { + m_host.AddScriptLPS(1); + SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum); + if (part != null) + { + return part.Name; + } + else + { + return LLUUID.Zero.ToString(); + } + } + + public LSL_Types.LSLInteger llGetInventoryNumber(int type) + { + m_host.AddScriptLPS(1); + int count = 0; + foreach (KeyValuePair inv in m_host.TaskInventory) + { + if (inv.Value.Type == type || type == -1) + { + count = count + 1; + } + } + return count; + } + + public string llGetInventoryName(int type, int number) + { + m_host.AddScriptLPS(1); + ArrayList keys = new ArrayList(); + foreach (KeyValuePair inv in m_host.TaskInventory) + { + if (inv.Value.Type == type || type == -1) + { + keys.Add(inv.Value.Name); + } + } + if (keys.Count == 0) + { + return String.Empty; + } + keys.Sort(); + if (keys.Count > number) + { + return (string)keys[number]; + } + return String.Empty; + } + + public void llSetScriptState(string name, int run) + { + LLUUID item; + + m_host.AddScriptLPS(1); + + // These functions are supposed to be robust, + // so get the state one step at a time. + + if ((item = ScriptByName(name)) != LLUUID.Zero) + { + m_ScriptEngine.SetScriptState(item, run == 0 ? false : true); + } + else + { + ShoutError("llSetScriptState: script "+name+" not found"); + } + } + + public double llGetEnergy() + { + m_host.AddScriptLPS(1); + // TODO: figure out real energy value + return 1.0f; + } + + public void llGiveInventory(string destination, string inventory) + { + m_host.AddScriptLPS(1); + NotImplemented("llGiveInventory"); + } + + public void llRemoveInventory(string item) + { + m_host.AddScriptLPS(1); + NotImplemented("llRemoveInventory"); + } + + public void llSetText(string text, LSL_Types.Vector3 color, double alpha) + { + m_host.AddScriptLPS(1); + Vector3 av3 = new Vector3((float)color.x, (float)color.y, (float)color.z); + m_host.SetText(text, av3, alpha); + } + + public double llWater(LSL_Types.Vector3 offset) + { + m_host.AddScriptLPS(1); + return World.RegionInfo.EstateSettings.waterHeight; + } + + public void llPassTouches(int pass) + { + m_host.AddScriptLPS(1); + NotImplemented("llPassTouches"); + } + + public string llRequestAgentData(string id, int data) + { + m_host.AddScriptLPS(1); + + UserProfileData userProfile = + World.CommsManager.UserService.GetUserProfile(id); + + string reply = String.Empty; + + switch(data) + { + case 1: // DATA_ONLINE (0|1) + // TODO: implement fetching of this information +// if(userProfile.CurrentAgent.AgentOnline) +// reply = "1"; +// else + reply = "0"; + break; + case 2: // DATA_NAME (First Last) + reply = userProfile.FirstName+" "+userProfile.SurName; + break; + case 3: // DATA_BORN (YYYY-MM-DD) + DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0); + born = born.AddSeconds(userProfile.Created); + reply = born.ToString("yyyy-MM-dd"); + break; + case 4: // DATA_RATING (0,0,0,0,0,0) + reply = "0,0,0,0,0,0"; + break; + case 8: // DATA_PAYINFO (0|1|2|3) + reply = "0"; + break; + default: + return LLUUID.Zero.ToString(); // Raise no event + } + + LLUUID rq = LLUUID.Random(); + + LLUUID tid = m_ScriptEngine.m_ASYNCLSLCommandManager. + m_Dataserver.RegisterRequest(m_localID, + m_itemID, rq.ToString()); + + m_ScriptEngine.m_ASYNCLSLCommandManager. + m_Dataserver.DataserverReply(rq.ToString(), reply); + + return tid.ToString(); + } + + public string llRequestInventoryData(string name) + { + m_host.AddScriptLPS(1); + + foreach (TaskInventoryItem item in m_host.TaskInventory.Values) + { + if (item.Type == 3 && item.Name == name) + { + LLUUID tid = m_ScriptEngine.m_ASYNCLSLCommandManager. + m_Dataserver.RegisterRequest(m_localID, + m_itemID, item.AssetID.ToString()); + + LLVector3 region = new LLVector3( + World.RegionInfo.RegionLocX * Constants.RegionSize, + World.RegionInfo.RegionLocY * Constants.RegionSize, + 0); + + World.AssetCache.GetAsset(item.AssetID, + delegate(LLUUID i, AssetBase a) + { + AssetLandmark lm = new AssetLandmark(a); + + region += lm.Position; + + string reply = region.ToString(); + + m_ScriptEngine.m_ASYNCLSLCommandManager. + m_Dataserver.DataserverReply(i.ToString(), + reply); + }, false); + + return tid.ToString(); + } + } + + return String.Empty; + } + + public void llSetDamage(double damage) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetDamage"); + } + + public void llTeleportAgentHome(string agent) + { + m_host.AddScriptLPS(1); + NotImplemented("llTeleportAgentHome"); + } + + public void llModifyLand(int action, int brush) + { + m_host.AddScriptLPS(1); + World.ExternalChecks.ExternalChecksCanTerraformLand(m_host.OwnerID, new LLVector3(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y, 0)); + } + + public void llCollisionSound(string impact_sound, double impact_volume) + { + m_host.AddScriptLPS(1); + NotImplemented("llCollisionSound"); + } + + public void llCollisionSprite(string impact_sprite) + { + m_host.AddScriptLPS(1); + NotImplemented("llCollisionSprite"); + } + + public string llGetAnimation(string id) + { + m_host.AddScriptLPS(1); + NotImplemented("llGetAnimation"); + return String.Empty; + } + + public void llResetScript() + { + m_host.AddScriptLPS(1); + m_ScriptEngine.ResetScript(m_itemID); + } + + public void llMessageLinked(int linknum, int num, string msg, string id) + { + + m_host.AddScriptLPS(1); + + uint partLocalID; + LLUUID partItemID; + + switch ((int)linknum) + { + + case (int)BuiltIn_Commands_BaseClass.LINK_ROOT: + + SceneObjectPart part = m_host.ParentGroup.RootPart; + + foreach (TaskInventoryItem item in part.TaskInventory.Values) + { + if (item.Type == 10) + { + partLocalID = part.LocalId; + partItemID = item.ItemID; + + object[] resobj = new object[] + { + new LSL_Types.LSLInteger(m_host.LinkNum + 1), new LSL_Types.LSLInteger(num), new LSL_Types.LSLString(msg), new LSL_Types.LSLString(id) + }; + + m_ScriptEngine.PostScriptEvent(partItemID, + new XEventParams("link_message", + resobj, new XDetectParams[0])); + } + } + + break; + + case (int)BuiltIn_Commands_BaseClass.LINK_SET: + + Console.WriteLine("LINK_SET"); + + foreach (SceneObjectPart partInst in m_host.ParentGroup.GetParts()) + { + + foreach (TaskInventoryItem item in partInst.TaskInventory.Values) + { + if (item.Type == 10) + { + partLocalID = partInst.LocalId; + partItemID = item.ItemID; + Object[] resobj = new object[] + { + new LSL_Types.LSLInteger(m_host.LinkNum + 1), new LSL_Types.LSLInteger(num), new LSL_Types.LSLString(msg), new LSL_Types.LSLString(id) + }; + + m_ScriptEngine.PostScriptEvent(partItemID, + new XEventParams("link_message", + resobj, new XDetectParams[0])); + } + } + } + + break; + + case (int)BuiltIn_Commands_BaseClass.LINK_ALL_OTHERS: + + foreach (SceneObjectPart partInst in m_host.ParentGroup.GetParts()) + { + + if (partInst.LocalId != m_host.LocalId) + { + + foreach (TaskInventoryItem item in partInst.TaskInventory.Values) + { + if (item.Type == 10) + { + partLocalID = partInst.LocalId; + partItemID = item.ItemID; + Object[] resobj = new object[] + { + new LSL_Types.LSLInteger(m_host.LinkNum + 1), new LSL_Types.LSLInteger(num), new LSL_Types.LSLString(msg), new LSL_Types.LSLString(id) + }; + + m_ScriptEngine.PostScriptEvent(partItemID, + new XEventParams("link_message", + resobj, new XDetectParams[0])); + } + } + + } + } + + break; + + case (int)BuiltIn_Commands_BaseClass.LINK_ALL_CHILDREN: + + foreach (SceneObjectPart partInst in m_host.ParentGroup.GetParts()) + { + + if (partInst.LocalId != m_host.ParentGroup.RootPart.LocalId) + { + + foreach (TaskInventoryItem item in partInst.TaskInventory.Values) + { + if (item.Type == 10) + { + partLocalID = partInst.LocalId; + partItemID = item.ItemID; + Object[] resobj = new object[] + { + new LSL_Types.LSLInteger(m_host.LinkNum + 1), new LSL_Types.LSLInteger(num), new LSL_Types.LSLString(msg), new LSL_Types.LSLString(id) + }; + + m_ScriptEngine.PostScriptEvent(partItemID, + new XEventParams("link_message", + resobj, new XDetectParams[0])); + } + } + + } + } + + break; + + case (int)BuiltIn_Commands_BaseClass.LINK_THIS: + + foreach (TaskInventoryItem item in m_host.TaskInventory.Values) + { + if (item.Type == 10) + { + partItemID = item.ItemID; + + object[] resobj = new object[] + { + new LSL_Types.LSLInteger(m_host.LinkNum + 1), new LSL_Types.LSLInteger(num), new LSL_Types.LSLString(msg), new LSL_Types.LSLString(id) + }; + + m_ScriptEngine.PostScriptEvent(partItemID, + new XEventParams("link_message", + resobj, new XDetectParams[0])); + } + } + + break; + + default: + + foreach (SceneObjectPart partInst in m_host.ParentGroup.GetParts()) + { + + if ((partInst.LinkNum + 1) == linknum) + { + + foreach (TaskInventoryItem item in partInst.TaskInventory.Values) + { + if (item.Type == 10) + { + partLocalID = partInst.LocalId; + partItemID = item.ItemID; + Object[] resObjDef = new object[] + { + new LSL_Types.LSLInteger(m_host.LinkNum + 1), new LSL_Types.LSLInteger(num), new LSL_Types.LSLString(msg), new LSL_Types.LSLString(id) + }; + + m_ScriptEngine.PostScriptEvent(partItemID, + new XEventParams("link_message", + resObjDef, new XDetectParams[0])); + } + } + + } + } + + break; + + } + + } + + public void llPushObject(string target, LSL_Types.Vector3 impulse, LSL_Types.Vector3 ang_impulse, int local) + { + m_host.AddScriptLPS(1); + NotImplemented("llPushObject"); + } + + public void llPassCollisions(int pass) + { + m_host.AddScriptLPS(1); + NotImplemented("llPassCollisions"); + } + + public string llGetScriptName() + { + + string result = String.Empty; + + m_host.AddScriptLPS(1); + + foreach (TaskInventoryItem item in m_host.TaskInventory.Values) + { + if (item.Type == 10 && item.ItemID == m_itemID) + { + result = item.Name!=null?item.Name:String.Empty; + break; + } + } + + return result; + + } + + public LSL_Types.LSLInteger llGetNumberOfSides() + { + m_host.AddScriptLPS(1); + NotImplemented("llGetNumberOfSides"); + return 0; + } + + + /* The new / changed functions were tested with the following LSL script: + + default + { + state_entry() + { + rotation rot = llEuler2Rot(<0,70,0> * DEG_TO_RAD); + + llOwnerSay("to get here, we rotate over: "+ (string) llRot2Axis(rot)); + llOwnerSay("and we rotate for: "+ (llRot2Angle(rot) * RAD_TO_DEG)); + + // convert back and forth between quaternion <-> vector and angle + + rotation newrot = llAxisAngle2Rot(llRot2Axis(rot),llRot2Angle(rot)); + + llOwnerSay("Old rotation was: "+(string) rot); + llOwnerSay("re-converted rotation is: "+(string) newrot); + + llSetRot(rot); // to check the parameters in the prim + } + } + */ + + + + // Xantor 29/apr/2008 + // Returns rotation described by rotating angle radians about axis. + // q = cos(a/2) + i (x * sin(a/2)) + j (y * sin(a/2)) + k (z * sin(a/2)) + public LSL_Types.Quaternion llAxisAngle2Rot(LSL_Types.Vector3 axis, double angle) + { + m_host.AddScriptLPS(1); + + double x, y, z, s, t; + + s = Math.Cos(angle / 2); + t = Math.Sin(angle / 2); // temp value to avoid 2 more sin() calcs + x = axis.x * t; + y = axis.y * t; + z = axis.z * t; + + return new LSL_Types.Quaternion(x,y,z,s); + // NotImplemented("llAxisAngle2Rot"); + } + + + // Xantor 29/apr/2008 + // converts a Quaternion to X,Y,Z axis rotations + public LSL_Types.Vector3 llRot2Axis(LSL_Types.Quaternion rot) + { + m_host.AddScriptLPS(1); + double x,y,z; + + if (rot.s > 1) // normalization needed + { + double length = Math.Sqrt(rot.x * rot.x + rot.y * rot.y + + rot.z * rot.z + rot.s * rot.s); + + rot.x /= length; + rot.y /= length; + rot.z /= length; + rot.s /= length; + + } + + double angle = 2 * Math.Acos(rot.s); + double s = Math.Sqrt(1 - rot.s * rot.s); + if (s < 0.001) + { + x = 1; + y = z = 0; + } + else + { + x = rot.x / s; // normalise axis + y = rot.y / s; + z = rot.z / s; + } + + + return new LSL_Types.Vector3(x,y,z); + + +// NotImplemented("llRot2Axis"); + } + + + // Returns the angle of a quaternion (see llRot2Axis for the axis) + public double llRot2Angle(LSL_Types.Quaternion rot) + { + m_host.AddScriptLPS(1); + + if (rot.s > 1) // normalization needed + { + double length = Math.Sqrt(rot.x * rot.x + rot.y * rot.y + + rot.z * rot.z + rot.s * rot.s); + + rot.x /= length; + rot.y /= length; + rot.z /= length; + rot.s /= length; + + } + + double angle = 2 * Math.Acos(rot.s); + + return angle; + +// NotImplemented("llRot2Angle"); + } + + public double llAcos(double val) + { + m_host.AddScriptLPS(1); + return (double)Math.Acos(val); + } + + public double llAsin(double val) + { + m_host.AddScriptLPS(1); + return (double)Math.Asin(val); + } + + // Xantor 30/apr/2008 + public double llAngleBetween(LSL_Types.Quaternion a, LSL_Types.Quaternion b) + { + m_host.AddScriptLPS(1); + + return (double) Math.Acos(a.x * b.x + a.y * b.y + a.z * b.z + a.s * b.s) * 2; +// NotImplemented("llAngleBetween"); + } + + public string llGetInventoryKey(string name) + { + m_host.AddScriptLPS(1); + foreach (KeyValuePair inv in m_host.TaskInventory) + { + if (inv.Value.Name == name) + { + if ((inv.Value.OwnerMask & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) + { + return inv.Value.AssetID.ToString(); + } + else + { + return LLUUID.Zero.ToString(); + } + } + } + return LLUUID.Zero.ToString(); + } + + public void llAllowInventoryDrop(int add) + { + m_host.AddScriptLPS(1); + NotImplemented("llAllowInventoryDrop"); + } + + public LSL_Types.Vector3 llGetSunDirection() + { + m_host.AddScriptLPS(1); + + LSL_Types.Vector3 SunDoubleVector3; + LLVector3 SunFloatVector3; + + // sunPosition estate setting is set in OpenSim.Region.Environment.Modules.SunModule + // have to convert from LLVector3 (float) to LSL_Types.Vector3 (double) + SunFloatVector3 = World.RegionInfo.EstateSettings.sunPosition; + SunDoubleVector3.x = (double)SunFloatVector3.X; + SunDoubleVector3.y = (double)SunFloatVector3.Y; + SunDoubleVector3.z = (double)SunFloatVector3.Z; + + return SunDoubleVector3; + } + + public LSL_Types.Vector3 llGetTextureOffset(int face) + { + m_host.AddScriptLPS(1); + LLObject.TextureEntry tex = m_host.Shape.Textures; + LSL_Types.Vector3 offset; + if (face == -1) + { + face = 0; + } + offset.x = tex.GetFace((uint)face).OffsetU; + offset.y = tex.GetFace((uint)face).OffsetV; + offset.z = 0.0; + return offset; + } + + public LSL_Types.Vector3 llGetTextureScale(int side) + { + m_host.AddScriptLPS(1); + LLObject.TextureEntry tex = m_host.Shape.Textures; + LSL_Types.Vector3 scale; + if (side == -1) + { + side = 0; + } + scale.x = tex.GetFace((uint)side).RepeatU; + scale.y = tex.GetFace((uint)side).RepeatV; + scale.z = 0.0; + return scale; + } + + public double llGetTextureRot(int face) + { + m_host.AddScriptLPS(1); + LLObject.TextureEntry tex = m_host.Shape.Textures; + if (face == -1) + { + face = 0; + } + return tex.GetFace((uint)face).Rotation; + } + + public LSL_Types.LSLInteger llSubStringIndex(string source, string pattern) + { + m_host.AddScriptLPS(1); + return source.IndexOf(pattern); + } + + public string llGetOwnerKey(string id) + { + m_host.AddScriptLPS(1); + LLUUID key = new LLUUID(); + if (LLUUID.TryParse(id, out key)) + { + return World.GetSceneObjectPart(World.Entities[key].LocalId).OwnerID.ToString(); + } + else + { + return LLUUID.Zero.ToString(); + } + } + + public LSL_Types.Vector3 llGetCenterOfMass() + { + m_host.AddScriptLPS(1); + NotImplemented("llGetCenterOfMass"); + return new LSL_Types.Vector3(); + } + + public LSL_Types.list llListSort(LSL_Types.list src, int stride, int ascending) + { + m_host.AddScriptLPS(1); + return src.Sort(stride, ascending); + } + + public LSL_Types.LSLInteger llGetListLength(LSL_Types.list src) + { + m_host.AddScriptLPS(1); + return src.Length; + } + + public LSL_Types.LSLInteger llList2Integer(LSL_Types.list src, int index) + { + m_host.AddScriptLPS(1); + if (index < 0) + { + index = src.Length + index; + } + if (index >= src.Length) + { + return 0; + } + try + { + return Convert.ToInt32(src.Data[index]); + } + catch (FormatException) + { + return 0; + } + } + + public double osList2Double(LSL_Types.list src, int index) + { + m_host.AddScriptLPS(1); + if (index < 0) + { + index = src.Length + index; + } + if (index >= src.Length) + { + return 0.0; + } + return Convert.ToDouble(src.Data[index]); + } + + public double llList2Float(LSL_Types.list src, int index) + { + m_host.AddScriptLPS(1); + if (index < 0) + { + index = src.Length + index; + } + if (index >= src.Length) + { + return 0.0; + } + try + { + return Convert.ToDouble(src.Data[index]); + } + catch (FormatException) + { + return 0.0; + } + } + + public string llList2String(LSL_Types.list src, int index) + { + m_host.AddScriptLPS(1); + if (index < 0) + { + index = src.Length + index; + } + if (index >= src.Length) + { + return String.Empty; + } + return src.Data[index].ToString(); + } + + public string llList2Key(LSL_Types.list src, int index) + { + m_host.AddScriptLPS(1); + if (index < 0) + { + index = src.Length + index; + } + if (index >= src.Length) + { + return ""; + } + return src.Data[index].ToString(); + } + + public LSL_Types.Vector3 llList2Vector(LSL_Types.list src, int index) + { + m_host.AddScriptLPS(1); + if (index < 0) + { + index = src.Length + index; + } + if (index >= src.Length) + { + return new LSL_Types.Vector3(0, 0, 0); + } + if (src.Data[index].GetType() == typeof(LSL_Types.Vector3)) + { + return (LSL_Types.Vector3)src.Data[index]; + } + else + { + return new LSL_Types.Vector3(src.Data[index].ToString()); + } + } + + public LSL_Types.Quaternion llList2Rot(LSL_Types.list src, int index) + { + m_host.AddScriptLPS(1); + if (index < 0) + { + index = src.Length + index; + } + if (index >= src.Length) + { + return new LSL_Types.Quaternion(0, 0, 0, 1); + } + if (src.Data[index].GetType() == typeof(LSL_Types.Quaternion)) + { + return (LSL_Types.Quaternion)src.Data[index]; + } + else + { + return new LSL_Types.Quaternion(src.Data[index].ToString()); + } + } + + public LSL_Types.list llList2List(LSL_Types.list src, int start, int end) + { + m_host.AddScriptLPS(1); + return src.GetSublist(start, end); + } + + public LSL_Types.list llDeleteSubList(LSL_Types.list src, int start, int end) + { + return src.DeleteSublist(end, start); + } + + public LSL_Types.LSLInteger llGetListEntryType(LSL_Types.list src, int index) + { + m_host.AddScriptLPS(1); + if (index < 0) + { + index = src.Length + index; + } + if (index >= src.Length) + { + return 0; + } + + if (src.Data[index] is Int32) + return 1; + if (src.Data[index] is Double) + return 2; + if (src.Data[index] is String) + { + LLUUID tuuid; + if (LLUUID.TryParse(src.Data[index].ToString(), out tuuid)) + { + return 3; + } + else + { + return 4; + } + } + if (src.Data[index] is LSL_Types.Vector3) + return 5; + if (src.Data[index] is LSL_Types.Quaternion) + return 6; + if (src.Data[index] is LSL_Types.list) + return 7; + return 0; + + } + + /// + /// Process the supplied list and return the + /// content of the list formatted as a comma + /// separated list. There is a space after + /// each comma. + /// + + public string llList2CSV(LSL_Types.list src) + { + + string ret = String.Empty; + int x = 0; + + m_host.AddScriptLPS(1); + + if (src.Data.Length > 0) + { + ret = src.Data[x++].ToString(); + for (; x < src.Data.Length; x++) + { + ret += ", "+src.Data[x].ToString(); + } + } + + return ret; + } + + /// + /// 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. + /// + + public LSL_Types.list llCSV2List(string src) + { + + LSL_Types.list result = new LSL_Types.list(); + int parens = 0; + int start = 0; + int length = 0; + + m_host.AddScriptLPS(1); + + 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(src.Substring(start,length).Trim()); + start += length+1; + length = 0; + } else + length++; + break; + default : + length++; + break; + } + } + + result.Add(src.Substring(start,length).Trim()); + + return result; + + } + + /// + /// Randomizes the list, be arbitrarily reordering + /// sublists of stride elements. As the stride approaches + /// the size of the list, the options become very + /// limited. + /// + /// + /// This could take a while for very large list + /// sizes. + /// + + public LSL_Types.list llListRandomize(LSL_Types.list src, int stride) + { + + LSL_Types.list result; + Random rand = new Random(); + + int chunkk; + int[] chunks; + int index1; + int index2; + int tmp; + + m_host.AddScriptLPS(1); + + 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) + { + chunkk = src.Length/stride; + + chunks = new int[chunkk]; + + for (int i = 0; i < chunkk; i++) + chunks[i] = i; + + for (int i = 0; i < chunkk - 1; i++) + { + // randomly select 2 chunks + index1 = rand.Next(rand.Next(65536)); + index1 = index1%chunkk; + index2 = rand.Next(rand.Next(65536)); + index2 = index2%chunkk; + + // and swap their relative positions + tmp = chunks[index1]; + chunks[index1] = chunks[index2]; + chunks[index2] = tmp; + } + + // Construct the randomized list + + result = new LSL_Types.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_Types.list(array); + } + + return result; + + } + + /// + /// 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. + /// + + public LSL_Types.list llList2ListStrided(LSL_Types.list src, int start, int end, int stride) + { + + LSL_Types.list result = new LSL_Types.list(); + int[] si = new int[2]; + int[] ei = new int[2]; + bool twopass = false; + + m_host.AddScriptLPS(1); + + // 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; + + // 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) + stride = 1; + + 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]); + } + } + } + + return result; + } + + public LSL_Types.Vector3 llGetRegionCorner() + { + m_host.AddScriptLPS(1); + return new LSL_Types.Vector3(World.RegionInfo.RegionLocX * Constants.RegionSize, World.RegionInfo.RegionLocY * Constants.RegionSize, 0); + } + + /// + /// Insert the list identified by into the + /// list designated by such that the first + /// new element has the index specified by + /// + + public LSL_Types.list llListInsertList(LSL_Types.list dest, LSL_Types.list src, int index) + { + + LSL_Types.list pref = null; + LSL_Types.list suff = null; + + m_host.AddScriptLPS(1); + + 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; + } + else + { + return pref + src; + } + } + else + { + if (index < dest.Length) + { + suff = dest.GetSublist(index,-1); + return src + suff; + } + else + { + return src; + } + } + + } + + /// + /// Returns the index of the first occurrence of test + /// in src. + /// + + public LSL_Types.LSLInteger llListFindList(LSL_Types.list src, LSL_Types.list test) + { + + int index = -1; + int length = src.Length - test.Length + 1; + + m_host.AddScriptLPS(1); + + // 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])) + { + int j; + for (j = 1; j < test.Length; j++) + if (!src.Data[i+j].Equals(test.Data[j])) + break; + if (j == test.Length) + { + index = i; + break; + } + } + } + } + + return index; + + } + + public string llGetObjectName() + { + m_host.AddScriptLPS(1); + return m_host.Name!=null?m_host.Name:String.Empty; + } + + public void llSetObjectName(string name) + { + m_host.AddScriptLPS(1); + m_host.Name = name!=null?name:String.Empty; + } + + public string llGetDate() + { + m_host.AddScriptLPS(1); + DateTime date = DateTime.Now.ToUniversalTime(); + string result = date.ToString("yyyy-MM-dd"); + return result; + } + + public LSL_Types.LSLInteger llEdgeOfWorld(LSL_Types.Vector3 pos, LSL_Types.Vector3 dir) + { + m_host.AddScriptLPS(1); + NotImplemented("llEdgeOfWorld"); + return 0; + } + + public LSL_Types.LSLInteger llGetAgentInfo(string id) + { + m_host.AddScriptLPS(1); + NotImplemented("llGetAgentInfo"); + return 0; + } + + public void llAdjustSoundVolume(double volume) + { + m_host.AddScriptLPS(1); + m_host.AdjustSoundGain(volume); + } + + public void llSetSoundQueueing(int queue) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetSoundQueueing"); + } + + public void llSetSoundRadius(double radius) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetSoundRadius"); + } + + public string llKey2Name(string id) + { + m_host.AddScriptLPS(1); + LLUUID key = new LLUUID(); + if (LLUUID.TryParse(id,out key)) + { + ScenePresence presence = World.GetScenePresence(key); + + if (presence != null) + { + return presence.Name; + } + + if (World.GetSceneObjectPart(key) != null) + { + return World.GetSceneObjectPart(key).Name; + } + } + return String.Empty; + } + + + + public void llSetTextureAnim(int mode, int face, int sizex, int sizey, double start, double length, double rate) + { + m_host.AddScriptLPS(1); + Primitive.TextureAnimation pTexAnim = new Primitive.TextureAnimation(); + pTexAnim.Flags =(uint) mode; + + //ALL_SIDES + if (face == -1) + face = 255; + + pTexAnim.Face = (uint)face; + pTexAnim.Length = (float)length; + pTexAnim.Rate = (float)rate; + pTexAnim.SizeX = (uint)sizex; + pTexAnim.SizeY = (uint)sizey; + pTexAnim.Start = (float)start; + + m_host.AddTextureAnimation(pTexAnim); + m_host.SendFullUpdateToAllClients(); + } + + public void llTriggerSoundLimited(string sound, double volume, LSL_Types.Vector3 top_north_east, + LSL_Types.Vector3 bottom_south_west) + { + m_host.AddScriptLPS(1); + NotImplemented("llTriggerSoundLimited"); + } + + public void llEjectFromLand(string pest) + { + m_host.AddScriptLPS(1); + NotImplemented("llEjectFromLand"); + } + + public LSL_Types.list llParseString2List(string str, LSL_Types.list separators, LSL_Types.list spacers) + { + m_host.AddScriptLPS(1); + LSL_Types.list ret = new LSL_Types.list(); + object[] delimiters = new object[separators.Length + spacers.Length]; + separators.Data.CopyTo(delimiters, 0); + spacers.Data.CopyTo(delimiters, separators.Length); + bool dfound = false; + do + { + dfound = false; + int cindex = -1; + string cdeli = ""; + for (int i = 0; i < delimiters.Length; i++) + { + int index = str.IndexOf(delimiters[i].ToString()); + bool found = index != -1; + if (found) + { + if ((cindex > index) || (cindex == -1)) + { + cindex = index; + cdeli = (string)delimiters[i]; + } + dfound = dfound || found; + } + } + if (cindex != -1) + { + if (cindex > 0) + { + ret.Add(str.Substring(0, cindex)); + if (spacers.Contains(cdeli)) + { + ret.Add(cdeli); + } + } + if (cindex == 0 && spacers.Contains(cdeli)) + { + ret.Add(cdeli); + } + str = str.Substring(cindex + cdeli.Length); + } + } while (dfound); + if (str != "") + { + ret.Add(str); + } + return ret; + } + + public LSL_Types.LSLInteger llOverMyLand(string id) + { + + m_host.AddScriptLPS(1); + LLUUID key = new LLUUID(); + if (LLUUID.TryParse(id,out key)) + { + SceneObjectPart obj = new SceneObjectPart(); + obj = World.GetSceneObjectPart(World.Entities[key].LocalId); + if (obj.OwnerID == World.GetLandOwner(obj.AbsolutePosition.X, obj.AbsolutePosition.Y)) + { + return 1; + } + else + { + return 0; + } + } + else + { + return 0; + } + } + + public string llGetLandOwnerAt(LSL_Types.Vector3 pos) + { + m_host.AddScriptLPS(1); + return World.GetLandOwner((float)pos.x, (float)pos.y).ToString(); + } + + public LSL_Types.Vector3 llGetAgentSize(string id) + { + m_host.AddScriptLPS(1); + NotImplemented("llGetAgentSize"); + return new LSL_Types.Vector3(); + } + + public LSL_Types.LSLInteger llSameGroup(string agent) + { + m_host.AddScriptLPS(1); + NotImplemented("llSameGroup"); + return 0; + } + + public void llUnSit(string id) + { + m_host.AddScriptLPS(1); + + LLUUID key = new LLUUID(); + if (LLUUID.TryParse(id, out key)) + { + ScenePresence av = World.GetScenePresence(key); + + if (av != null) + { + if (llAvatarOnSitTarget() == id) + { + // if the avatar is sitting on this object, then + // we can unsit them. We don't want random scripts unsitting random people + // Lets avoid the popcorn avatar scenario. + av.StandUp(); + } + else + { + // If the object owner also owns the parcel + // or + // if the land is group owned and the object is group owned by the same group + // or + // if the object is owned by a person with estate access. + + ILandObject parcel = World.LandChannel.GetLandObject(av.AbsolutePosition.X, av.AbsolutePosition.Y); + if (parcel != null) + { + if (m_host.ObjectOwner == parcel.landData.ownerID || + (m_host.OwnerID == m_host.GroupID && m_host.GroupID == parcel.landData.groupID + && parcel.landData.isGroupOwned) || World.ExternalChecks.ExternalChecksCanBeGodLike(m_host.OwnerID)) + { + av.StandUp(); + } + } + } + } + + } + + } + + public LSL_Types.Vector3 llGroundSlope(LSL_Types.Vector3 offset) + { + m_host.AddScriptLPS(1); + NotImplemented("llGroundSlope"); + return new LSL_Types.Vector3(); + } + + public LSL_Types.Vector3 llGroundNormal(LSL_Types.Vector3 offset) + { + m_host.AddScriptLPS(1); + NotImplemented("llGroundNormal"); + return new LSL_Types.Vector3(); + } + + public LSL_Types.Vector3 llGroundContour(LSL_Types.Vector3 offset) + { + m_host.AddScriptLPS(1); + NotImplemented("llGroundContour"); + return new LSL_Types.Vector3(); + } + + public LSL_Types.LSLInteger llGetAttached() + { + m_host.AddScriptLPS(1); + NotImplemented("llGetAttached"); + return 0; + } + + public LSL_Types.LSLInteger llGetFreeMemory() + { + m_host.AddScriptLPS(1); + NotImplemented("llGetFreeMemory"); + return 0; + } + + public string llGetRegionName() + { + m_host.AddScriptLPS(1); + return World.RegionInfo.RegionName; + } + + public double llGetRegionTimeDilation() + { + m_host.AddScriptLPS(1); + return (double)World.TimeDilation; + } + + public double llGetRegionFPS() + { + m_host.AddScriptLPS(1); + //TODO: return actual FPS + return 10.0f; + } + + /* particle system rules should be coming into this routine as doubles, that is + rule[0] should be an integer from this list and rule[1] should be the arg + for the same integer. wiki.secondlife.com has most of this mapping, but some + came from http://www.caligari-designs.com/p4u2 + + We iterate through the list for 'Count' elements, incrementing by two for each + iteration and set the members of Primitive.ParticleSystem, one at a time. + */ + + public enum PrimitiveRule : int + { + PSYS_PART_FLAGS = 0, + PSYS_PART_START_COLOR = 1, + PSYS_PART_START_ALPHA = 2, + PSYS_PART_END_COLOR = 3, + PSYS_PART_END_ALPHA = 4, + PSYS_PART_START_SCALE = 5, + PSYS_PART_END_SCALE = 6, + PSYS_PART_MAX_AGE = 7, + PSYS_SRC_ACCEL = 8, + PSYS_SRC_PATTERN = 9, + PSYS_SRC_TEXTURE = 12, + PSYS_SRC_BURST_RATE = 13, + PSYS_SRC_BURST_PART_COUNT = 15, + PSYS_SRC_BURST_RADIUS = 16, + PSYS_SRC_BURST_SPEED_MIN = 17, + PSYS_SRC_BURST_SPEED_MAX = 18, + PSYS_SRC_MAX_AGE = 19, + PSYS_SRC_TARGET_KEY = 20, + PSYS_SRC_OMEGA = 21, + PSYS_SRC_ANGLE_BEGIN = 22, + PSYS_SRC_ANGLE_END = 23 + } + + internal Primitive.ParticleSystem.ParticleDataFlags ConvertUINTtoFlags(uint flags) + { + Primitive.ParticleSystem.ParticleDataFlags returnval = Primitive.ParticleSystem.ParticleDataFlags.None; + + return returnval; + } + + + public void llParticleSystem(LSL_Types.list rules) + { + m_host.AddScriptLPS(1); + Primitive.ParticleSystem prules = new Primitive.ParticleSystem(); + LSL_Types.Vector3 tempv = new LSL_Types.Vector3(); + + float tempf = 0; + + for (int i = 0; i < rules.Length; i += 2) + { + switch ((int)rules.Data[i]) + { + case (int)BuiltIn_Commands_BaseClass.PSYS_PART_FLAGS: + prules.PartDataFlags = (Primitive.ParticleSystem.ParticleDataFlags)((uint)Convert.ToInt32(rules.Data[i + 1].ToString())); + break; + + case (int)BuiltIn_Commands_BaseClass.PSYS_PART_START_COLOR: + tempv = (LSL_Types.Vector3)rules.Data[i + 1]; + prules.PartStartColor.R = (float)tempv.x; + prules.PartStartColor.G = (float)tempv.y; + prules.PartStartColor.B = (float)tempv.z; + break; + + case (int)BuiltIn_Commands_BaseClass.PSYS_PART_START_ALPHA: + tempf = Convert.ToSingle(rules.Data[i + 1].ToString()); + prules.PartStartColor.A = (float)tempf; + break; + + case (int)BuiltIn_Commands_BaseClass.PSYS_PART_END_COLOR: + tempv = (LSL_Types.Vector3)rules.Data[i + 1]; + //prules.PartEndColor = new LLColor(tempv.x,tempv.y,tempv.z,1); + + prules.PartEndColor.R = (float)tempv.x; + prules.PartEndColor.G = (float)tempv.y; + prules.PartEndColor.B = (float)tempv.z; + break; + + case (int)BuiltIn_Commands_BaseClass.PSYS_PART_END_ALPHA: + tempf = Convert.ToSingle(rules.Data[i + 1].ToString()); + prules.PartEndColor.A = (float)tempf; + break; + + case (int)BuiltIn_Commands_BaseClass.PSYS_PART_START_SCALE: + tempv = (LSL_Types.Vector3)rules.Data[i + 1]; + prules.PartStartScaleX = (float)tempv.x; + prules.PartStartScaleY = (float)tempv.y; + break; + + case (int)BuiltIn_Commands_BaseClass.PSYS_PART_END_SCALE: + tempv = (LSL_Types.Vector3)rules.Data[i + 1]; + prules.PartEndScaleX = (float)tempv.x; + prules.PartEndScaleY = (float)tempv.y; + break; + + case (int)BuiltIn_Commands_BaseClass.PSYS_PART_MAX_AGE: + tempf = Convert.ToSingle(rules.Data[i + 1].ToString()); + prules.PartMaxAge = (float)tempf; + break; + + case (int)BuiltIn_Commands_BaseClass.PSYS_SRC_ACCEL: + tempv = (LSL_Types.Vector3)rules.Data[i + 1]; + prules.PartAcceleration.X = (float)tempv.x; + prules.PartAcceleration.Y = (float)tempv.y; + prules.PartAcceleration.Z = (float)tempv.z; + break; + + case (int)BuiltIn_Commands_BaseClass.PSYS_SRC_PATTERN: + int tmpi = int.Parse(rules.Data[i + 1].ToString()); + prules.Pattern = (Primitive.ParticleSystem.SourcePattern)tmpi; + break; + + // Xantor 03-May-2008 + // Wiki: PSYS_SRC_TEXTURE string inventory item name or key of the particle texture + // "" = default texture. + case (int)BuiltIn_Commands_BaseClass.PSYS_SRC_TEXTURE: + LLUUID tkey = LLUUID.Zero; + + // if we can parse the string as a key, use it. + if (LLUUID.TryParse(rules.Data[i + 1].ToString(), out tkey)) + { + prules.Texture = tkey; + } + // else try to locate the name in inventory of object. found returns key, + // not found returns LLUUID.Zero which will translate to the default particle texture + else + { + prules.Texture = InventoryKey(rules.Data[i+1].ToString()); + } + break; + + case (int)BuiltIn_Commands_BaseClass.PSYS_SRC_BURST_RATE: + tempf = Convert.ToSingle(rules.Data[i + 1].ToString()); + prules.BurstRate = (float)tempf; + break; + + case (int)BuiltIn_Commands_BaseClass.PSYS_SRC_BURST_PART_COUNT: + prules.BurstPartCount = (byte)Convert.ToByte(rules.Data[i + 1].ToString()); + break; + + case (int)BuiltIn_Commands_BaseClass.PSYS_SRC_BURST_RADIUS: + tempf = Convert.ToSingle(rules.Data[i + 1].ToString()); + prules.BurstRadius = (float)tempf; + break; + + case (int)BuiltIn_Commands_BaseClass.PSYS_SRC_BURST_SPEED_MIN: + tempf = Convert.ToSingle(rules.Data[i + 1].ToString()); + prules.BurstSpeedMin = (float)tempf; + break; + + case (int)BuiltIn_Commands_BaseClass.PSYS_SRC_BURST_SPEED_MAX: + tempf = Convert.ToSingle(rules.Data[i + 1].ToString()); + prules.BurstSpeedMax = (float)tempf; + break; + + case (int)BuiltIn_Commands_BaseClass.PSYS_SRC_MAX_AGE: + tempf = Convert.ToSingle(rules.Data[i + 1].ToString()); + prules.MaxAge = (float)tempf; + break; + + case (int)BuiltIn_Commands_BaseClass.PSYS_SRC_TARGET_KEY: + LLUUID key = LLUUID.Zero; + if (LLUUID.TryParse(rules.Data[i + 1].ToString(), out key)) + { + prules.Target = key; + } + else + { + prules.Target = m_host.UUID; + } + break; + + case (int)BuiltIn_Commands_BaseClass.PSYS_SRC_OMEGA: + // AL: This is an assumption, since it is the only thing that would match. + tempv = (LSL_Types.Vector3)rules.Data[i + 1]; + prules.AngularVelocity.X = (float)tempv.x; + prules.AngularVelocity.Y = (float)tempv.y; + prules.AngularVelocity.Z = (float)tempv.z; + //cast?? prules.MaxAge = (float)rules[i + 1]; + break; + + case (int)BuiltIn_Commands_BaseClass.PSYS_SRC_ANGLE_BEGIN: + tempf = Convert.ToSingle(rules.Data[i + 1].ToString()); + prules.InnerAngle = (float)tempf; + break; + + case (int)BuiltIn_Commands_BaseClass.PSYS_SRC_ANGLE_END: + tempf = Convert.ToSingle(rules.Data[i + 1].ToString()); + prules.OuterAngle = (float)tempf; + break; + } + + } + prules.CRC = 1; + + m_host.AddNewParticleSystem(prules); + m_host.SendFullUpdateToAllClients(); + } + + public void llGroundRepel(double height, int water, double tau) + { + m_host.AddScriptLPS(1); + NotImplemented("llGroundRepel"); + } + + public void llGiveInventoryList(string destination, string category, LSL_Types.list inventory) + { + m_host.AddScriptLPS(1); + NotImplemented("llGiveInventoryList"); + } + + public void llSetVehicleType(int type) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetVehicleType"); + } + + public void llSetVehicledoubleParam(int param, double value) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetVehicledoubleParam"); + } + + public void llSetVehicleFloatParam(int param, float value) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetVehicleFloatParam"); + } + + public void llSetVehicleVectorParam(int param, LSL_Types.Vector3 vec) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetVehicleVectorParam"); + } + + public void llSetVehicleRotationParam(int param, LSL_Types.Quaternion rot) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetVehicleRotationParam"); + } + + public void llSetVehicleFlags(int flags) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetVehicleFlags"); + } + + public void llRemoveVehicleFlags(int flags) + { + m_host.AddScriptLPS(1); + NotImplemented("llRemoveVehicleFlags"); + } + + public void llSitTarget(LSL_Types.Vector3 offset, LSL_Types.Quaternion rot) + { + m_host.AddScriptLPS(1); + // LSL quaternions can normalize to 0, normal Quaternions can't. + if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0) + rot.z = 1; // ZERO_ROTATION = 0,0,0,1 + + m_host.SetSitTarget(new Vector3((float)offset.x, (float)offset.y, (float)offset.z), new Quaternion((float)rot.s, (float)rot.x, (float)rot.y, (float)rot.z)); + } + + public string llAvatarOnSitTarget() + { + m_host.AddScriptLPS(1); + return m_host.GetAvatarOnSitTarget().ToString(); + //LLUUID AVID = m_host.GetAvatarOnSitTarget(); + + //if (AVID != LLUUID.Zero) + // return AVID.ToString(); + //else + // return String.Empty; + } + + public void llAddToLandPassList(string avatar, double hours) + { + m_host.AddScriptLPS(1); + LLUUID key; + LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData; + if (land.ownerID == m_host.OwnerID) + { + ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); + if (LLUUID.TryParse(avatar, out key)) + { + entry.AgentID = key; + entry.Flags = ParcelManager.AccessList.Access; + entry.Time = DateTime.Now.AddHours(hours); + land.parcelAccessList.Add(entry); + } + } + } + + public void llSetTouchText(string text) + { + m_host.AddScriptLPS(1); + m_host.TouchName = text; + } + + public void llSetSitText(string text) + { + m_host.AddScriptLPS(1); + m_host.SitName = text; + } + + public void llSetCameraEyeOffset(LSL_Types.Vector3 offset) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetCameraEyeOffset"); + } + + public void llSetCameraAtOffset(LSL_Types.Vector3 offset) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetCameraAtOffset"); + } + + public string llDumpList2String(LSL_Types.list src, string seperator) + { + m_host.AddScriptLPS(1); + if (src.Length == 0) + { + return String.Empty; + } + string ret = String.Empty; + foreach (object o in src.Data) + { + ret = ret + o.ToString() + seperator; + } + ret = ret.Substring(0, ret.Length - seperator.Length); + return ret; + } + + public LSL_Types.LSLInteger llScriptDanger(LSL_Types.Vector3 pos) + { + m_host.AddScriptLPS(1); + bool result = World.scriptDanger(m_host.LocalId, new LLVector3((float)pos.x, (float)pos.y, (float)pos.z)); + if (result) + { + return 1; + } + else + { + return 0; + } + + } + + public void llDialog(string avatar, string message, LSL_Types.list buttons, int chat_channel) + { + m_host.AddScriptLPS(1); + LLUUID av = new LLUUID(); + if (!LLUUID.TryParse(avatar,out av)) + { + LSLError("First parameter to llDialog needs to be a key"); + return; + } + if (buttons.Length > 12) + { + LSLError("No more than 12 buttons can be shown"); + return; + } + string[] buts = new string[buttons.Length]; + for (int i = 0; i < buttons.Length; i++) + { + if (buttons.Data[i].ToString() == String.Empty) + { + LSLError("button label cannot be blank"); + return; + } + if (buttons.Data[i].ToString().Length > 24) + { + LSLError("button label cannot be longer than 24 characters"); + return; + } + buts[i] = buttons.Data[i].ToString(); + } + World.SendDialogToUser(av, m_host.Name, m_host.UUID, m_host.OwnerID, message, new LLUUID("00000000-0000-2222-3333-100000001000"), chat_channel, buts); + } + + public void llVolumeDetect(int detect) + { + m_host.AddScriptLPS(1); + NotImplemented("llVolumeDetect"); + } + + /// + /// Reset the named script. The script must be present + /// in the same prim. + /// + + public void llResetOtherScript(string name) + { + LLUUID item; + + m_host.AddScriptLPS(1); + + if ((item = ScriptByName(name)) != LLUUID.Zero) + m_ScriptEngine.ResetScript(item); + else + ShoutError("llResetOtherScript: script "+name+" not found"); + } + + public LSL_Types.LSLInteger llGetScriptState(string name) + { + LLUUID item; + + m_host.AddScriptLPS(1); + + if ((item = ScriptByName(name)) != LLUUID.Zero) + { + return m_ScriptEngine.GetScriptState(item) ?1:0; + } + + ShoutError("llGetScriptState: script "+name+" not found"); + + // If we didn't find it, then it's safe to + // assume it is not running. + + return 0; + } + + public void llRemoteLoadScript() + { + m_host.AddScriptLPS(1); + Deprecated("llRemoteLoadScript"); + } + + public void llSetRemoteScriptAccessPin(int pin) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetRemoteScriptAccessPin"); + } + + public void llRemoteLoadScriptPin(string target, string name, int pin, int running, int start_param) + { + m_host.AddScriptLPS(1); + NotImplemented("llRemoteLoadScriptPin"); + } + + // remote_data(integer type, key channel, key message_id, string sender, integer ival, string sval) + // Not sure where these constants should live: + // REMOTE_DATA_CHANNEL = 1 + // REMOTE_DATA_REQUEST = 2 + // REMOTE_DATA_REPLY = 3 + public void llOpenRemoteDataChannel() + { + m_host.AddScriptLPS(1); + IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface(); + if (xmlrpcMod.IsEnabled()) + { + LLUUID channelID = xmlrpcMod.OpenXMLRPCChannel(m_localID, m_itemID, LLUUID.Zero); + object[] resobj = new object[] { new LSL_Types.LSLInteger(1), new LSL_Types.LSLString(channelID.ToString()), new LSL_Types.LSLString(LLUUID.Zero.ToString()), new LSL_Types.LSLString(String.Empty), new LSL_Types.LSLInteger(0), new LSL_Types.LSLString(String.Empty) }; + m_ScriptEngine.PostScriptEvent(m_itemID, new XEventParams( + "remote_data", resobj, + new XDetectParams[0])); + } + } + + public string llSendRemoteData(string channel, string dest, int idata, string sdata) + { + m_host.AddScriptLPS(1); + IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface(); + return (xmlrpcMod.SendRemoteData(m_localID, m_itemID, channel, dest, idata, sdata)).ToString(); + } + + public void llRemoteDataReply(string channel, string message_id, string sdata, int idata) + { + m_host.AddScriptLPS(1); + IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface(); + xmlrpcMod.RemoteDataReply(channel, message_id, sdata, idata); + } + + public void llCloseRemoteDataChannel(string channel) + { + m_host.AddScriptLPS(1); + IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface(); + xmlrpcMod.CloseXMLRPCChannel(channel); + } + + public string llMD5String(string src, int nonce) + { + m_host.AddScriptLPS(1); + return Util.Md5Hash(src + ":" + nonce.ToString()); + } + + public void llSetPrimitiveParams(LSL_Types.list rules) + { + llSetLinkPrimitiveParams(m_host.LinkNum+1, rules); + } + + public void llSetLinkPrimitiveParams(int linknumber, LSL_Types.list rules) + { + m_host.AddScriptLPS(1); + + SceneObjectPart part=null; + + if (m_host.LinkNum+1 != linknumber) + { + foreach (SceneObjectPart partInst in m_host.ParentGroup.GetParts()) + { + if ((partInst.LinkNum + 1) == linknumber) + { + part = partInst; + break; + } + } + } + else + { + part = m_host; + } + + if (part == null) + return; + + int idx = 0; + + while (idx < rules.Length) + { + int code = Convert.ToInt32(rules.Data[idx++]); + + int remain = rules.Length - idx; + + int face; + LSL_Types.Vector3 v; + + switch (code) + { + case 6: // PRIM_POSITION + if (remain < 1) + return; + + v=new LSL_Types.Vector3(rules.Data[idx++].ToString()); + SetPos(part, v); + + break; + + case 8: // PRIM_ROTATION + if (remain < 1) + return; + + LSL_Types.Quaternion q = new LSL_Types.Quaternion(rules.Data[idx++].ToString()); + SetRot(part, q); + + break; + + case 17: // PRIM_TEXTURE + if (remain < 5) + return; + + face=Convert.ToInt32(rules.Data[idx++]); + string tex=rules.Data[idx++].ToString(); + LSL_Types.Vector3 repeats=new LSL_Types.Vector3(rules.Data[idx++].ToString()); + LSL_Types.Vector3 offsets=new LSL_Types.Vector3(rules.Data[idx++].ToString()); + double rotation=Convert.ToDouble(rules.Data[idx++]); + + SetTexture(part, tex, face); + ScaleTexture(part, repeats.x, repeats.y, face); + OffsetTexture(part, offsets.x, offsets.y, face); + RotateTexture(part, rotation, face); + + break; + + case 18: // PRIM_COLOR + if (remain < 3) + return; + + face=Convert.ToInt32(rules.Data[idx++]); + LSL_Types.Vector3 color=new LSL_Types.Vector3(rules.Data[idx++].ToString()); + double alpha=Convert.ToDouble(rules.Data[idx++]); + + SetColor(part, color, face); + SetAlpha(part, alpha, face); + + break; + + case 7: // PRIM_SIZE + if (remain < 1) + return; + + v=new LSL_Types.Vector3(rules.Data[idx++].ToString()); + SetScale(part, v); + + break; + } + } + } + + public string llStringToBase64(string str) + { + m_host.AddScriptLPS(1); + try + { + byte[] encData_byte = new byte[str.Length]; + encData_byte = Encoding.UTF8.GetBytes(str); + string encodedData = Convert.ToBase64String(encData_byte); + return encodedData; + } + catch (Exception e) + { + throw new Exception("Error in base64Encode" + e.Message); + } + } + + public string llBase64ToString(string str) + { + m_host.AddScriptLPS(1); + UTF8Encoding encoder = new UTF8Encoding(); + Decoder utf8Decode = encoder.GetDecoder(); + try + { + byte[] todecode_byte = Convert.FromBase64String(str); + int charCount = utf8Decode.GetCharCount(todecode_byte, 0, todecode_byte.Length); + char[] decoded_char = new char[charCount]; + utf8Decode.GetChars(todecode_byte, 0, todecode_byte.Length, decoded_char, 0); + string result = new String(decoded_char); + return result; + } + catch (Exception e) + { + throw new Exception("Error in base64Decode" + e.Message); + } + } + + public void llXorBase64Strings() + { + m_host.AddScriptLPS(1); + Deprecated("llXorBase64Strings"); + } + + public void llRemoteDataSetRegion() + { + m_host.AddScriptLPS(1); + NotImplemented("llRemoteDataSetRegion"); + } + + public double llLog10(double val) + { + m_host.AddScriptLPS(1); + return (double)Math.Log10(val); + } + + public double llLog(double val) + { + m_host.AddScriptLPS(1); + return (double)Math.Log(val); + } + + public LSL_Types.list llGetAnimationList(string id) + { + m_host.AddScriptLPS(1); + NotImplemented("llGetAnimationList"); + return new LSL_Types.list(); + } + + public void llSetParcelMusicURL(string url) + { + m_host.AddScriptLPS(1); + LLUUID landowner = World.GetLandOwner(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); + if (landowner == LLUUID.Zero) + { + return; + } + if (landowner != m_host.ObjectOwner) + { + return; + } + World.SetLandMusicURL(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y, url); + } + + public void osSetParcelMediaURL(string url) + { + m_host.AddScriptLPS(1); + LLUUID landowner = World.GetLandOwner(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); + + if (landowner == LLUUID.Zero) + { + return; + } + + if (landowner != m_host.ObjectOwner) + { + return; + } + + World.SetLandMediaURL(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y, url); + } + + public LSL_Types.Vector3 llGetRootPosition() + { + m_host.AddScriptLPS(1); + return new LSL_Types.Vector3(m_host.ParentGroup.AbsolutePosition.X, m_host.ParentGroup.AbsolutePosition.Y, m_host.ParentGroup.AbsolutePosition.Z); + } + + public LSL_Types.Quaternion llGetRootRotation() + { + m_host.AddScriptLPS(1); + return new LSL_Types.Quaternion(m_host.ParentGroup.GroupRotation.X, m_host.ParentGroup.GroupRotation.Y, m_host.ParentGroup.GroupRotation.Z, m_host.ParentGroup.GroupRotation.W); + } + + public string llGetObjectDesc() + { + return m_host.Description!=null?m_host.Description:String.Empty; + } + + public void llSetObjectDesc(string desc) + { + m_host.AddScriptLPS(1); + m_host.Description = desc!=null?desc:String.Empty; + } + + public string llGetCreator() + { + m_host.AddScriptLPS(1); + return m_host.ObjectCreator.ToString(); + } + + public string llGetTimestamp() + { + m_host.AddScriptLPS(1); + return DateTime.Now.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ"); + } + + public void llSetLinkAlpha(int linknumber, double alpha, int face) + { + m_host.AddScriptLPS(1); + SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknumber); + if (linknumber > -1) + { + LLObject.TextureEntry tex = part.Shape.Textures; + LLColor texcolor; + if (face > -1) + { + texcolor = tex.CreateFace((uint)face).RGBA; + texcolor.A = (float)Math.Abs(alpha - 1); + tex.FaceTextures[face].RGBA = texcolor; + part.UpdateTexture(tex); + return; + } + else if (face == -1) + { + texcolor = tex.DefaultTexture.RGBA; + texcolor.A = (float)Math.Abs(alpha - 1); + tex.DefaultTexture.RGBA = texcolor; + for (uint i = 0; i < 32; i++) + { + if (tex.FaceTextures[i] != null) + { + texcolor = tex.FaceTextures[i].RGBA; + texcolor.A = (float)Math.Abs(alpha - 1); + tex.FaceTextures[i].RGBA = texcolor; + } + } + texcolor = tex.DefaultTexture.RGBA; + texcolor.A = (float)Math.Abs(alpha - 1); + tex.DefaultTexture.RGBA = texcolor; + part.UpdateTexture(tex); + return; + } + return; + } + else if (linknumber == -1) + { + int num = m_host.ParentGroup.PrimCount; + for (int w = 0; w < num; w++) + { + linknumber = w; + part = m_host.ParentGroup.GetLinkNumPart(linknumber); + LLObject.TextureEntry tex = part.Shape.Textures; + LLColor texcolor; + if (face > -1) + { + texcolor = tex.CreateFace((uint)face).RGBA; + texcolor.A = (float)Math.Abs(alpha - 1); + tex.FaceTextures[face].RGBA = texcolor; + part.UpdateTexture(tex); + } + else if (face == -1) + { + texcolor = tex.DefaultTexture.RGBA; + texcolor.A = (float)Math.Abs(alpha - 1); + tex.DefaultTexture.RGBA = texcolor; + for (uint i = 0; i < 32; i++) + { + if (tex.FaceTextures[i] != null) + { + texcolor = tex.FaceTextures[i].RGBA; + texcolor.A = (float)Math.Abs(alpha - 1); + tex.FaceTextures[i].RGBA = texcolor; + } + } + texcolor = tex.DefaultTexture.RGBA; + texcolor.A = (float)Math.Abs(alpha - 1); + tex.DefaultTexture.RGBA = texcolor; + part.UpdateTexture(tex); + } + } + return; + } + } + + public LSL_Types.LSLInteger llGetNumberOfPrims() + { + m_host.AddScriptLPS(1); + return m_host.ParentGroup.PrimCount; + } + + public LSL_Types.list llGetBoundingBox(string obj) + { + m_host.AddScriptLPS(1); + NotImplemented("llGetBoundingBox"); + return new LSL_Types.list(); + } + + public LSL_Types.Vector3 llGetGeometricCenter() + { + return new LSL_Types.Vector3(m_host.GetGeometricCenter().X, m_host.GetGeometricCenter().Y, m_host.GetGeometricCenter().Z); + } + + public LSL_Types.list llGetPrimitiveParams(LSL_Types.list rules) + { + m_host.AddScriptLPS(1); + + LSL_Types.list res = new LSL_Types.list(); + int idx=0; + while (idx < rules.Length) + { + int code=Convert.ToInt32(rules.Data[idx++]); + int remain=rules.Length-idx; + + switch (code) + { + case 2: // PRIM_MATERIAL + res.Add(new LSL_Types.LSLInteger(m_host.Material)); + break; + + case 3: // PRIM_PHYSICS + if ((m_host.GetEffectiveObjectFlags() & (uint)LLObject.ObjectFlags.Physics) != 0) + res.Add(new LSL_Types.LSLInteger(1)); + else + res.Add(new LSL_Types.LSLInteger(0)); + break; + + case 4: // PRIM_TEMP_ON_REZ + if ((m_host.GetEffectiveObjectFlags() & (uint)LLObject.ObjectFlags.TemporaryOnRez) != 0) + res.Add(new LSL_Types.LSLInteger(1)); + else + res.Add(new LSL_Types.LSLInteger(0)); + break; + + case 5: // PRIM_PHANTOM + if ((m_host.GetEffectiveObjectFlags() & (uint)LLObject.ObjectFlags.Phantom) != 0) + res.Add(new LSL_Types.LSLInteger(1)); + else + res.Add(new LSL_Types.LSLInteger(0)); + break; + + case 6: // PRIM_POSITION + res.Add(new LSL_Types.Vector3(m_host.AbsolutePosition.X, + m_host.AbsolutePosition.Y, + m_host.AbsolutePosition.Z)); + break; + + case 7: // PRIM_SIZE + res.Add(new LSL_Types.Vector3(m_host.Scale.X, + m_host.Scale.Y, + m_host.Scale.Z)); + break; + + case 8: // PRIM_ROTATION + res.Add(new LSL_Types.Quaternion(m_host.RotationOffset.X, + m_host.RotationOffset.Y, + m_host.RotationOffset.Z, + m_host.RotationOffset.W)); + break; + + case 9: // PRIM_TYPE + // TODO-------------- + res.Add(new LSL_Types.LSLInteger(0)); + break; + + case 17: // PRIM_TEXTURE + if (remain < 1) + return res; + + int face=Convert.ToInt32(rules.Data[idx++]); + if (face == -1) + face = 0; + + LLObject.TextureEntry tex = m_host.Shape.Textures; + LLObject.TextureEntryFace texface = tex.GetFace((uint)face); + + res.Add(new LSL_Types.LSLString(texface.TextureID.ToString())); + res.Add(new LSL_Types.Vector3(texface.RepeatU, + texface.RepeatV, + 0)); + res.Add(new LSL_Types.Vector3(texface.OffsetU, + texface.OffsetV, + 0)); + res.Add(new LSL_Types.LSLFloat(texface.Rotation)); + break; + + case 18: // PRIM_COLOR + if (remain < 1) + return res; + + face=Convert.ToInt32(rules.Data[idx++]); + + tex = m_host.Shape.Textures; + LLColor texcolor; + if (face == -1) // TMP: Until we can determine number of sides, ALL_SIDES (-1) will return default color + texcolor = tex.DefaultTexture.RGBA; + else + texcolor = tex.GetFace((uint)face).RGBA; + res.Add(new LSL_Types.Vector3((255 - (texcolor.R * 255)) / 255, + (255 - (texcolor.G * 255)) / 255, + (255 - (texcolor.B * 255)) / 255)); + res.Add(new LSL_Types.LSLFloat((texcolor.A * 255) / 255)); + break; + + case 19: // PRIM_BUMP_SHINY + // TODO-------------- + if (remain < 1) + return res; + + face=Convert.ToInt32(rules.Data[idx++]); + + res.Add(new LSL_Types.LSLInteger(0)); + res.Add(new LSL_Types.LSLInteger(0)); + break; + + case 20: // PRIM_FULLBRIGHT + // TODO-------------- + if (remain < 1) + return res; + + face=Convert.ToInt32(rules.Data[idx++]); + + res.Add(new LSL_Types.LSLInteger(0)); + break; + + case 21: // PRIM_FLEXIBLE + PrimitiveBaseShape shape = m_host.Shape; + + if (shape.FlexiEntry) + res.Add(new LSL_Types.LSLInteger(1)); // active + else + res.Add(new LSL_Types.LSLInteger(0)); + res.Add(new LSL_Types.LSLInteger(shape.FlexiSoftness));// softness + res.Add(new LSL_Types.LSLFloat(shape.FlexiGravity)); // gravity + res.Add(new LSL_Types.LSLFloat(shape.FlexiDrag)); // friction + res.Add(new LSL_Types.LSLFloat(shape.FlexiWind)); // wind + res.Add(new LSL_Types.LSLFloat(shape.FlexiTension)); // tension + res.Add(new LSL_Types.Vector3(shape.FlexiForceX, // force + shape.FlexiForceY, + shape.FlexiForceZ)); + break; + + case 22: // PRIM_TEXGEN + // TODO-------------- + // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR) + if (remain < 1) + return res; + + face=Convert.ToInt32(rules.Data[idx++]); + + res.Add(new LSL_Types.LSLInteger(0)); + break; + + case 23: // PRIM_POINT_LIGHT: + shape = m_host.Shape; + + if (shape.LightEntry) + res.Add(new LSL_Types.LSLInteger(1)); // active + else + res.Add(new LSL_Types.LSLInteger(0)); + res.Add(new LSL_Types.Vector3(shape.LightColorR, // color + shape.LightColorG, + shape.LightColorB)); + res.Add(new LSL_Types.LSLFloat(shape.LightIntensity)); // intensity + res.Add(new LSL_Types.LSLFloat(shape.LightRadius)); // radius + res.Add(new LSL_Types.LSLFloat(shape.LightFalloff)); // falloff + break; + + case 24: // PRIM_GLOW + // TODO-------------- + if (remain < 1) + return res; + + face=Convert.ToInt32(rules.Data[idx++]); + + res.Add(new LSL_Types.LSLFloat(0)); + break; + } + } + return res; + } + + // + // + // The .NET definition of base 64 is: + // + // + // Significant: A-Z a-z 0-9 + - + // + // + // Whitespace: \t \n \r ' ' + // + // + // Valueless: = + // + // + // End-of-string: \0 or '==' + // + // + // + // + // Each point in a base-64 string represents + // a 6 bit value. A 32-bit integer can be + // represented using 6 characters (with some + // redundancy). + // + // + // LSL requires a base64 string to be 8 + // characters in length. LSL also uses '/' + // rather than '-' (MIME compliant). + // + // + // RFC 1341 used as a reference (as specified + // by the SecondLife Wiki). + // + // + // SL do not record any kind of exception for + // these functions, so the string to integer + // conversion returns '0' if an invalid + // character is encountered during conversion. + // + // + // References + // + // + // http://lslwiki.net/lslwiki/wakka.php?wakka=Base64 + // + // + // + // + // + // + + // + // Table for converting 6-bit integers into + // base-64 characters + // + + private static readonly char[] i2ctable = + { + 'A','B','C','D','E','F','G','H', + 'I','J','K','L','M','N','O','P', + 'Q','R','S','T','U','V','W','X', + 'Y','Z', + 'a','b','c','d','e','f','g','h', + 'i','j','k','l','m','n','o','p', + 'q','r','s','t','u','v','w','x', + 'y','z', + '0','1','2','3','4','5','6','7', + '8','9', + '+','/' + }; + + // + // Table for converting base-64 characters + // into 6-bit integers. + // + + private static readonly int[] c2itable = + { + -1,-1,-1,-1,-1,-1,-1,-1, // 0x + -1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1, // 1x + -1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1, // 2x + -1,-1,-1,63,-1,-1,-1,64, + 53,54,55,56,57,58,59,60, // 3x + 61,62,-1,-1,-1,0,-1,-1, + -1,1,2,3,4,5,6,7, // 4x + 8,9,10,11,12,13,14,15, + 16,17,18,19,20,21,22,23, // 5x + 24,25,26,-1,-1,-1,-1,-1, + -1,27,28,29,30,31,32,33, // 6x + 34,35,36,37,38,39,40,41, + 42,43,44,45,46,47,48,49, // 7x + 50,51,52,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1, // 8x + -1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1, // 9x + -1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1, // Ax + -1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1, // Bx + -1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1, // Cx + -1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1, // Dx + -1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1, // Ex + -1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1, // Fx + -1,-1,-1,-1,-1,-1,-1,-1 + }; + + // + // Converts a 32-bit integer into a Base64 + // character string. Base64 character strings + // are always 8 characters long. All iinteger + // values are acceptable. + // + // + // 32-bit integer to be converted. + // + // + // 8 character string. The 1st six characters + // contain the encoded number, the last two + // characters are padded with "=". + // + + public string llIntegerToBase64(int number) + { + // uninitialized string + + char[] imdt = new char[8]; + + m_host.AddScriptLPS(1); + + // Manually unroll the loop + + imdt[7] = '='; + imdt[6] = '='; + imdt[5] = i2ctable[number<<4 & 0x3F]; + imdt[4] = i2ctable[number>>2 & 0x3F]; + imdt[3] = i2ctable[number>>8 & 0x3F]; + imdt[2] = i2ctable[number>>14 & 0x3F]; + imdt[1] = i2ctable[number>>20 & 0x3F]; + imdt[0] = i2ctable[number>>26 & 0x3F]; + + return new string(imdt); + } + + // + // Converts an eight character base-64 string + // into a 32-bit integer. + // + // + // 8 characters string to be converted. Other + // length strings return zero. + // + // + // Returns an integer representing the + // encoded value providedint he 1st 6 + // characters of the string. + // + // + // This is coded to behave like LSL's + // implementation (I think), based upon the + // information available at the Wiki. + // If more than 8 characters are supplied, + // zero is returned. + // If a NULL string is supplied, zero will + // be returned. + // If fewer than 6 characters are supplied, then + // the answer will reflect a partial + // accumulation. + // + // The 6-bit segments are + // extracted left-to-right in big-endian mode, + // which means that segment 6 only contains the + // two low-order bits of the 32 bit integer as + // its high order 2 bits. A short string therefore + // means loss of low-order information. E.g. + // + // |<---------------------- 32-bit integer ----------------------->|<-Pad->| + // |<--Byte 0----->|<--Byte 1----->|<--Byte 2----->|<--Byte 3----->|<-Pad->| + // |3|3|2|2|2|2|2|2|2|2|2|2|1|1|1|1|1|1|1|1|1|1| | | | | | | | | | |P|P|P|P| + // |1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|P|P|P|P| + // | str[0] | str[1] | str[2] | str[3] | str[4] | str[6] | + // + // + // + + public LSL_Types.LSLInteger llBase64ToInteger(string str) + { + int number = 0; + int digit; + + m_host.AddScriptLPS(1); + + // Require a well-fromed base64 string + + if (str.Length > 8) + return 0; + + // The loop is unrolled in the interests + // of performance and simple necessity. + // + // MUST find 6 digits to be well formed + // -1 == invalid + // 0 == padding + + if ((digit=c2itable[str[0]])<=0) + { + return digit<0?(int)0:number; + } + number += --digit<<26; + + if ((digit=c2itable[str[1]])<=0) + { + return digit<0?(int)0:number; + } + number += --digit<<20; + + if ((digit=c2itable[str[2]])<=0) + { + return digit<0?(int)0:number; + } + number += --digit<<14; + + if ((digit=c2itable[str[3]])<=0) + { + return digit<0?(int)0:number; + } + number += --digit<<8; + + if ((digit=c2itable[str[4]])<=0) + { + return digit<0?(int)0:number; + } + number += --digit<<2; + + if ((digit=c2itable[str[5]])<=0) + { + return digit<0?(int)0:number; + } + number += --digit>>4; + + // ignore trailing padding + + return number; + } + + public double llGetGMTclock() + { + m_host.AddScriptLPS(1); + return DateTime.UtcNow.TimeOfDay.TotalSeconds; + } + + public string llGetSimulatorHostname() + { + m_host.AddScriptLPS(1); + return System.Environment.MachineName; + } + + public void llSetLocalRot(LSL_Types.Quaternion rot) + { + m_host.AddScriptLPS(1); + m_host.RotationOffset = new LLQuaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s); + } + + // + // Scan the string supplied in 'src' and + // tokenize it based upon two sets of + // tokenizers provided in two lists, + // separators and spacers. + // + // + // + // 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. + // + + public LSL_Types.list llParseStringKeepNulls(string src, LSL_Types.list separators, LSL_Types.list spacers) + { + 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]; + + int best; + int j; + + // Initial capacity reduces resize cost + + LSL_Types.list tokens = new LSL_Types.list(); + + m_host.AddScriptLPS(1); + + // All entries are initially valid + + for (int i = 0; i < mlen; i++) + active[i] = true; + + offset[mlen] = srclen; + + while (beginning < srclen) + { + + best = mlen; // as bad as it gets + + // Scan for separators + + for (j = 0; j < seplen; j++) + { + if (active[j]) + { + // scan all of the markers + if ((offset[j] = src.IndexOf((string)separray[j],beginning)) == -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 (active[j]) + { + // scan all of the markers + if ((offset[j] = src.IndexOf((string)spcarray[j-seplen],beginning)) == -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 + tokens.Add(src.Substring(beginning, srclen-beginning)); + break; + } + + // Otherwise we just add the newly delimited token + // and recalculate where the search should continue. + + tokens.Add(src.Substring(beginning,offset[best]-beginning)); + + if (best inv in m_host.TaskInventory) + { + if (inv.Value.Name == item) + { + switch (mask) + { + case 0: + return (int)inv.Value.BaseMask; + case 1: + return (int)inv.Value.OwnerMask; + case 2: + return (int)inv.Value.GroupMask; + case 3: + return (int)inv.Value.EveryoneMask; + case 4: + return (int)inv.Value.NextOwnerMask; + } + } + } + return -1; + } + + public void llSetInventoryPermMask(string item, int mask, int value) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetInventoryPermMask"); + } + + public string llGetInventoryCreator(string item) + { + m_host.AddScriptLPS(1); + foreach (KeyValuePair inv in m_host.TaskInventory) + { + if (inv.Value.Name == item) + { + return inv.Value.CreatorID.ToString(); + } + } + llSay(0, "No item name '" + item + "'"); + return String.Empty; + } + + public void llOwnerSay(string msg) + { + m_host.AddScriptLPS(1); + + World.SimChatBroadcast(Helpers.StringToField(msg), ChatTypeEnum.Owner, 0, m_host.AbsolutePosition, m_host.Name, m_host.UUID, false); +// IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface(); +// wComm.DeliverMessage(ChatTypeEnum.Owner, 0, m_host.Name, m_host.UUID, msg); + } + + public string llRequestSimulatorData(string simulator, int data) + { +try +{ + m_host.AddScriptLPS(1); + + string reply = String.Empty; + + RegionInfo info = m_ScriptEngine.World.RequestClosestRegion(simulator); + + switch(data) + { + case 5: // DATA_SIM_POS + if(info == null) + return LLUUID.Zero.ToString(); + reply = new LSL_Types.Vector3( + info.RegionLocX * Constants.RegionSize, + info.RegionLocY * Constants.RegionSize, + 0).ToString(); + break; + case 6: // DATA_SIM_STATUS + if(info != null) + reply = "up"; // Duh! + else + reply = "unknown"; + break; + case 7: // DATA_SIM_RATING + if(info == null) + return LLUUID.Zero.ToString(); + int access = (int)info.EstateSettings.simAccess; + if(access == 21) + reply = "MATURE"; + else if(access == 13) + reply = "MATURE"; + else + reply = "UNKNOWN"; + break; + default: + return LLUUID.Zero.ToString(); // Raise no event + } + LLUUID rq = LLUUID.Random(); + + LLUUID tid = m_ScriptEngine.m_ASYNCLSLCommandManager. + m_Dataserver.RegisterRequest(m_localID, + m_itemID, rq.ToString()); + + m_ScriptEngine.m_ASYNCLSLCommandManager. + m_Dataserver.DataserverReply(rq.ToString(), reply); + + return tid.ToString(); +} +catch(Exception e) +{ +Console.WriteLine(e.ToString()); +return LLUUID.Zero.ToString(); +} + } + + public void llForceMouselook(int mouselook) + { + m_host.AddScriptLPS(1); + NotImplemented("llForceMouselook"); + } + + public double llGetObjectMass(string id) + { + m_host.AddScriptLPS(1); + LLUUID key = new LLUUID(); + if (LLUUID.TryParse(id,out key)) + { + return (double)World.GetSceneObjectPart(World.Entities[key].LocalId).GetMass(); + } + return 0; + } + + /// + /// 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. + /// + + public LSL_Types.list llListReplaceList(LSL_Types.list dest, LSL_Types.list src, int start, int end) + { + + LSL_Types.list pref = null; + + m_host.AddScriptLPS(1); + + // 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) + { + 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); + } + else + { + 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. + else + { + if (end+1 < dest.Length) + { + return src + dest.GetSublist(end+1,-1); + } + else + { + return src; + } + } + } + // Finally, if start > end, we strip away a prefix and + // a suffix, to leave the list that sits 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. + else + { + return dest.GetSublist(end+1,start-1)+src; + } + } + + public void llLoadURL(string avatar_id, string message, string url) + { + m_host.AddScriptLPS(1); + LLUUID avatarId = new LLUUID(avatar_id); + m_ScriptEngine.World.SendUrlToUser(avatarId, m_host.Name, m_host.UUID, m_host.ObjectOwner, false, message, + url); + } + + public void llParcelMediaCommandList(LSL_Types.list commandList) + { + m_host.AddScriptLPS(1); + NotImplemented("llParcelMediaCommandList"); + } + + public void llParcelMediaQuery() + { + m_host.AddScriptLPS(1); + NotImplemented("llParcelMediaQuery"); + } + + public LSL_Types.LSLInteger llModPow(int a, int b, int c) + { + m_host.AddScriptLPS(1); + Int64 tmp = 0; + Math.DivRem(Convert.ToInt64(Math.Pow(a, b)), c, out tmp); + return Convert.ToInt32(tmp); + } + + public LSL_Types.LSLInteger llGetInventoryType(string name) + { + m_host.AddScriptLPS(1); + foreach (KeyValuePair inv in m_host.TaskInventory) + { + if (inv.Value.Name == name) + { + return inv.Value.InvType; + } + } + return -1; + } + + public void llSetPayPrice(int price, LSL_Types.list quick_pay_buttons) + { + m_host.AddScriptLPS(1); + + if (quick_pay_buttons.Data.Length != 4) + { + LSLError("List must have 4 elements"); + return; + } + m_host.ParentGroup.RootPart.PayPrice[0]=price; + m_host.ParentGroup.RootPart.PayPrice[1]=(int)quick_pay_buttons.Data[0]; + m_host.ParentGroup.RootPart.PayPrice[2]=(int)quick_pay_buttons.Data[1]; + m_host.ParentGroup.RootPart.PayPrice[3]=(int)quick_pay_buttons.Data[2]; + m_host.ParentGroup.RootPart.PayPrice[4]=(int)quick_pay_buttons.Data[3]; + } + + public LSL_Types.Vector3 llGetCameraPos() + { + m_host.AddScriptLPS(1); + NotImplemented("llGetCameraPos"); + return new LSL_Types.Vector3(); + } + + public LSL_Types.Quaternion llGetCameraRot() + { + m_host.AddScriptLPS(1); + NotImplemented("llGetCameraRot"); + return new LSL_Types.Quaternion(); + } + + public void llSetPrimURL() + { + m_host.AddScriptLPS(1); + NotImplemented("llSetPrimURL"); + } + + public void llRefreshPrimURL() + { + m_host.AddScriptLPS(1); + NotImplemented("llRefreshPrimURL"); + } + + public string llEscapeURL(string url) + { + m_host.AddScriptLPS(1); + try + { + return Uri.EscapeUriString(url); + } + catch (Exception ex) + { + return "llEscapeURL: " + ex.ToString(); + } + } + + public string llUnescapeURL(string url) + { + m_host.AddScriptLPS(1); + try + { + return Uri.UnescapeDataString(url); + } + catch (Exception ex) + { + return "llUnescapeURL: " + ex.ToString(); + } + } + + public void llMapDestination(string simname, LSL_Types.Vector3 pos, LSL_Types.Vector3 look_at) + { + m_host.AddScriptLPS(1); + NotImplemented("llMapDestination"); + } + + public void llAddToLandBanList(string avatar, double hours) + { + m_host.AddScriptLPS(1); + LLUUID key; + LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData; + if (land.ownerID == m_host.OwnerID) + { + ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); + if (LLUUID.TryParse(avatar, out key)) + { + entry.AgentID = key; + entry.Flags = ParcelManager.AccessList.Ban; + entry.Time = DateTime.Now.AddHours(hours); + land.parcelAccessList.Add(entry); + } + } + } + + public void llRemoveFromLandPassList(string avatar) + { + m_host.AddScriptLPS(1); + LLUUID key; + LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData; + if (land.ownerID == m_host.OwnerID) + { + if (LLUUID.TryParse(avatar, out key)) + { + foreach (ParcelManager.ParcelAccessEntry entry in land.parcelAccessList) + { + if (entry.AgentID == key && entry.Flags == ParcelManager.AccessList.Access) + { + land.parcelAccessList.Remove(entry); + break; + } + } + } + } + } + + public void llRemoveFromLandBanList(string avatar) + { + m_host.AddScriptLPS(1); + LLUUID key; + LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData; + if (land.ownerID == m_host.OwnerID) + { + if (LLUUID.TryParse(avatar, out key)) + { + foreach (ParcelManager.ParcelAccessEntry entry in land.parcelAccessList) + { + if (entry.AgentID == key && entry.Flags == ParcelManager.AccessList.Ban) + { + land.parcelAccessList.Remove(entry); + break; + } + } + } + } + } + + public void llSetCameraParams(LSL_Types.list rules) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetCameraParams"); + } + + public void llClearCameraParams() + { + m_host.AddScriptLPS(1); + NotImplemented("llClearCameraParams"); + } + + public double llListStatistics(int operation, LSL_Types.list src) + { + m_host.AddScriptLPS(1); + LSL_Types.list nums = LSL_Types.list.ToDoubleList(src); + switch (operation) + { + case BuiltIn_Commands_BaseClass.LIST_STAT_RANGE: + return nums.Range(); + case BuiltIn_Commands_BaseClass.LIST_STAT_MIN: + return nums.Min(); + case BuiltIn_Commands_BaseClass.LIST_STAT_MAX: + return nums.Max(); + case BuiltIn_Commands_BaseClass.LIST_STAT_MEAN: + return nums.Mean(); + case BuiltIn_Commands_BaseClass.LIST_STAT_MEDIAN: + return nums.Median(); + case BuiltIn_Commands_BaseClass.LIST_STAT_NUM_COUNT: + return nums.NumericLength(); + case BuiltIn_Commands_BaseClass.LIST_STAT_STD_DEV: + return nums.StdDev(); + case BuiltIn_Commands_BaseClass.LIST_STAT_SUM: + return nums.Sum(); + case BuiltIn_Commands_BaseClass.LIST_STAT_SUM_SQUARES: + return nums.SumSqrs(); + case BuiltIn_Commands_BaseClass.LIST_STAT_GEOMETRIC_MEAN: + return nums.GeometricMean(); + case BuiltIn_Commands_BaseClass.LIST_STAT_HARMONIC_MEAN: + return nums.HarmonicMean(); + default: + return 0.0; + } + } + + public LSL_Types.LSLInteger llGetUnixTime() + { + m_host.AddScriptLPS(1); + return Util.UnixTimeSinceEpoch(); + } + + public LSL_Types.LSLInteger llGetParcelFlags(LSL_Types.Vector3 pos) + { + m_host.AddScriptLPS(1); + return (int)World.LandChannel.GetLandObject((float)pos.x, (float)pos.y).landData.landFlags; + } + + public LSL_Types.LSLInteger llGetRegionFlags() + { + m_host.AddScriptLPS(1); + return (int)World.RegionInfo.EstateSettings.regionFlags; + } + + public string llXorBase64StringsCorrect(string str1, string str2) + { + m_host.AddScriptLPS(1); + string ret = String.Empty; + string src1 = llBase64ToString(str1); + string src2 = llBase64ToString(str2); + int c = 0; + for (int i = 0; i < src1.Length; i++) + { + ret += src1[i] ^ src2[c]; + + c++; + if (c > src2.Length) + c = 0; + } + return llStringToBase64(ret); + } + + public string llHTTPRequest(string url, LSL_Types.list parameters, string body) + { + // Partial implementation: support for parameter flags needed + // see http://wiki.secondlife.com/wiki/LlHTTPRequest + // parameter flags support are implemented in ScriptsHttpRequests.cs + // in StartHttpRequest + + m_host.AddScriptLPS(1); + IHttpRequests httpScriptMod = + m_ScriptEngine.World.RequestModuleInterface(); + List param = new List(); + foreach (object o in parameters.Data) + { + param.Add(o.ToString()); + } + LLUUID reqID = httpScriptMod. + StartHttpRequest(m_localID, m_itemID, url, param, body); + + if (reqID != LLUUID.Zero) + return reqID.ToString(); + else + return null; + } + + public void llResetLandBanList() + { + m_host.AddScriptLPS(1); + LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData; + if (land.ownerID == m_host.OwnerID) + { + foreach (ParcelManager.ParcelAccessEntry entry in land.parcelAccessList) + { + if (entry.Flags == ParcelManager.AccessList.Ban) + { + land.parcelAccessList.Remove(entry); + } + } + } + } + + public void llResetLandPassList() + { + m_host.AddScriptLPS(1); + LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData; + if (land.ownerID == m_host.OwnerID) + { + foreach (ParcelManager.ParcelAccessEntry entry in land.parcelAccessList) + { + if (entry.Flags == ParcelManager.AccessList.Access) + { + land.parcelAccessList.Remove(entry); + } + } + } + } + + public LSL_Types.LSLInteger llGetParcelPrimCount(LSL_Types.Vector3 pos, int category, int sim_wide) + { + m_host.AddScriptLPS(1); + + LandData land = World.GetLandData((float)pos.x, (float)pos.y); + + if (land == null) + { + return 0; + } + + else + { + if (sim_wide == 1) + { + if (category == 0) + { + return land.simwidePrims; + } + + else + { + //public int simwideArea = 0; + return 0; + } + } + + else + { + if (category == 0)//Total Prims + { + return 0;//land. + } + + else if (category == 1)//Owner Prims + { + return land.ownerPrims; + } + + else if (category == 2)//Group Prims + { + return land.groupPrims; + } + + else if (category == 3)//Other Prims + { + return land.otherPrims; + } + + else if (category == 4)//Selected + { + return land.selectedPrims; + } + + else if (category == 5)//Temp + { + return 0;//land. + } + } + } + return 0; + } + + public LSL_Types.list llGetParcelPrimOwners(LSL_Types.Vector3 pos) + { + m_host.AddScriptLPS(1); + LandObject land = (LandObject)World.LandChannel.GetLandObject((float)pos.x, (float)pos.y); + LSL_Types.list ret = new LSL_Types.list(); + if (land != null) + { + foreach (KeyValuePair d in land.getLandObjectOwners()) + { + ret.Add(d.Key.ToString()); + ret.Add(d.Value); + } + } + return ret; + } + + public LSL_Types.LSLInteger llGetObjectPrimCount(string object_id) + { + m_host.AddScriptLPS(1); + SceneObjectPart part = World.GetSceneObjectPart(new LLUUID(object_id)); + if (part == null) + { + return 0; + } + else + { + return part.ParentGroup.Children.Count; + } + } + + public LSL_Types.LSLInteger llGetParcelMaxPrims(LSL_Types.Vector3 pos, int sim_wide) + { + m_host.AddScriptLPS(1); + // Alondria: This currently just is utilizing the normal grid's 0.22 prims/m2 calculation + // Which probably will be irrelevent in OpenSim.... + LandData land = World.GetLandData((float)pos.x, (float)pos.y); + + float bonusfactor = World.RegionInfo.EstateSettings.objectBonusFactor; + + if (land == null) + { + return 0; + } + + if (sim_wide == 1) + { + decimal v = land.simwideArea * (decimal)(0.22) * (decimal)bonusfactor; + + return (int)v; + } + + else + { + decimal v = land.area * (decimal)(0.22) * (decimal)bonusfactor; + + return (int)v; + } + + } + + public LSL_Types.list llGetParcelDetails(LSL_Types.Vector3 pos, LSL_Types.list param) + { + m_host.AddScriptLPS(1); + LandData land = World.GetLandData((float)pos.x, (float)pos.y); + if (land == null) + { + return new LSL_Types.list(0); + } + LSL_Types.list ret = new LSL_Types.list(); + foreach (object o in param.Data) + { + switch (o.ToString()) + { + case "0": + ret = ret + new LSL_Types.list(land.landName); + break; + case "1": + ret = ret + new LSL_Types.list(land.landDesc); + break; + case "2": + ret = ret + new LSL_Types.list(land.ownerID.ToString()); + break; + case "3": + ret = ret + new LSL_Types.list(land.groupID.ToString()); + break; + case "4": + ret = ret + new LSL_Types.list(land.area); + break; + default: + ret = ret + new LSL_Types.list(0); + break; + } + } + return ret; + } + + public void llSetLinkTexture(int linknumber, string texture, int face) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetLinkTexture"); + } + + public string llStringTrim(string src, int type) + { + m_host.AddScriptLPS(1); + if (type == (int)BuiltIn_Commands_BaseClass.STRING_TRIM_HEAD) { return src.TrimStart(); } + if (type == (int)BuiltIn_Commands_BaseClass.STRING_TRIM_TAIL) { return src.TrimEnd(); } + if (type == (int)BuiltIn_Commands_BaseClass.STRING_TRIM) { return src.Trim(); } + return src; + } + + public LSL_Types.list llGetObjectDetails(string id, LSL_Types.list args) + { + m_host.AddScriptLPS(1); + LSL_Types.list ret = new LSL_Types.list(); + LLUUID key = new LLUUID(); + if (LLUUID.TryParse(id, out key)) + { + ScenePresence av = World.GetScenePresence(key); + + if (av != null) + { + foreach (object o in args.Data) + { + switch (o.ToString()) + { + case "1": + ret.Add(av.Firstname + " " + av.Lastname); + break; + case "2": + ret.Add(""); + break; + case "3": + ret.Add(new LSL_Types.Vector3((double)av.AbsolutePosition.X, (double)av.AbsolutePosition.Y, (double)av.AbsolutePosition.Z)); + break; + case "4": + ret.Add(new LSL_Types.Quaternion((double)av.Rotation.x, (double)av.Rotation.y, (double)av.Rotation.z, (double)av.Rotation.w)); + break; + case "5": + ret.Add(new LSL_Types.Vector3(av.Velocity.X,av.Velocity.Y,av.Velocity.Z)); + break; + case "6": + ret.Add(id); + break; + case "7": + ret.Add(LLUUID.Zero.ToString()); + break; + case "8": + ret.Add(LLUUID.Zero.ToString()); + break; + } + } + return ret; + } + SceneObjectPart obj = World.GetSceneObjectPart(key); + if (obj != null) + { + foreach (object o in args.Data) + { + switch (o.ToString()) + { + case "1": + ret.Add(obj.Name); + break; + case "2": + ret.Add(obj.Description); + break; + case "3": + ret.Add(new LSL_Types.Vector3(obj.AbsolutePosition.X,obj.AbsolutePosition.Y,obj.AbsolutePosition.Z)); + break; + case "4": + ret.Add(new LSL_Types.Quaternion(obj.RotationOffset.X, obj.RotationOffset.Y, obj.RotationOffset.Z, obj.RotationOffset.W)); + break; + case "5": + ret.Add(new LSL_Types.Vector3(obj.Velocity.X, obj.Velocity.Y, obj.Velocity.Z)); + break; + case "6": + ret.Add(obj.OwnerID.ToString()); + break; + case "7": + ret.Add(obj.GroupID.ToString()); + break; + case "8": + ret.Add(obj.CreatorID.ToString()); + break; + } + } + return ret; + } + } + return new LSL_Types.list(); + } + + + internal LLUUID ScriptByName(string name) + { + foreach (TaskInventoryItem item in m_host.TaskInventory.Values) + { + if (item.Type == 10 && item.Name == name) + return item.ItemID; + } + return LLUUID.Zero; + } + + internal void ShoutError(string msg) + { + llShout(BuiltIn_Commands_BaseClass.DEBUG_CHANNEL, msg); + } + + + + internal void NotImplemented(string command) + { + if (throwErrorOnNotImplemented) + throw new NotImplementedException("Command not implemented: " + command); + } + + internal void Deprecated(string command) + { + throw new Exception("Command deprecated: " + command); + } + + internal void LSLError(string msg) + { + throw new Exception("LSL Runtime Error: " + msg); + } + + public delegate void AssetRequestCallback(LLUUID assetID, AssetBase asset); + private void WithNotecard(LLUUID assetID, AssetRequestCallback cb) + { + World.AssetCache.GetAsset(assetID, delegate(LLUUID i, AssetBase a) { cb(i, a); }, false); + } + + public string llGetNumberOfNotecardLines(string name) + { + m_host.AddScriptLPS(1); + + foreach (TaskInventoryItem item in m_host.TaskInventory.Values) + { + if (item.Type == 7 && item.Name == name) + { + LLUUID tid = m_ScriptEngine.m_ASYNCLSLCommandManager. + m_Dataserver.RegisterRequest(m_localID, + m_itemID, item.AssetID.ToString()); + if(NotecardCache.IsCached(item.AssetID)) + { + m_ScriptEngine.m_ASYNCLSLCommandManager. + m_Dataserver.DataserverReply(item.AssetID.ToString(), + NotecardCache.GetLines(item.AssetID).ToString()); + return tid.ToString(); + } + WithNotecard(item.AssetID, delegate (LLUUID id, AssetBase a) + { + System.Text.ASCIIEncoding enc = + new System.Text.ASCIIEncoding(); + string data = enc.GetString(a.Data); + Console.WriteLine(data); + NotecardCache.Cache(id, data); + m_ScriptEngine.m_ASYNCLSLCommandManager. + m_Dataserver.DataserverReply(id.ToString(), + NotecardCache.GetLines(id).ToString()); + }); + + return tid.ToString(); + } + } + return LLUUID.Zero.ToString(); + } + + public string llGetNotecardLine(string name, int line) + { + m_host.AddScriptLPS(1); + + foreach (TaskInventoryItem item in m_host.TaskInventory.Values) + { + if (item.Type == 7 && item.Name == name) + { + LLUUID tid = m_ScriptEngine.m_ASYNCLSLCommandManager. + m_Dataserver.RegisterRequest(m_localID, + m_itemID, item.AssetID.ToString()); + if(NotecardCache.IsCached(item.AssetID)) + { + m_ScriptEngine.m_ASYNCLSLCommandManager. + m_Dataserver.DataserverReply(item.AssetID.ToString(), + NotecardCache.GetLine(item.AssetID, line)); + return tid.ToString(); + } + WithNotecard(item.AssetID, delegate (LLUUID id, AssetBase a) + { + System.Text.ASCIIEncoding enc = + new System.Text.ASCIIEncoding(); + string data = enc.GetString(a.Data); + Console.WriteLine(data); + NotecardCache.Cache(id, data); + m_ScriptEngine.m_ASYNCLSLCommandManager. + m_Dataserver.DataserverReply(id.ToString(), + NotecardCache.GetLine(id, line)); + }); + + return tid.ToString(); + } + } + + return String.Empty; + } + + } + + public class NotecardCache + { + private class Notecard + { + public string[] text; + public DateTime lastRef; + } + + private static Dictionary m_Notecards = + new Dictionary(); + + public static void Cache(LLUUID assetID, string text) + { + CacheCheck(); + + lock(m_Notecards) + { + if(m_Notecards.ContainsKey(assetID)) + return; + + Notecard nc = new Notecard(); + nc.lastRef=DateTime.Now; + nc.text = ParseText(text.Replace("\r", "").Split('\n')); + m_Notecards[assetID] = nc; + } + } + + private static string[] ParseText(string[] input) + { + int idx=0; + int level=0; + List output = new List(); + string[] words; + + while(idx < input.Length) + { + if(input[idx] == "{") + { + level++; + idx++; + continue; + } + if(input[idx]== "}") + { + level--; + idx++; + continue; + } + + switch(level) + { + case 0: + words = input[idx].Split(' '); // Linden text ver + int version = int.Parse(words[3]); + if(version != 2) + return new String[0]; + break; + case 1: + words = input[idx].Split(' '); + if(words[0] == "LLEmbeddedItems") + break; + if(words[0] == "Text") + { + int len = int.Parse(words[2]); + idx++; + + int count=-1; + + while(count < len) + { + int l = input[idx].Length; + string ln = input[idx]; + + int need = len-count-1; + if(ln.Length > need) + ln=ln.Substring(0, need); + + output.Add(ln); + count+=ln.Length+1; + idx++; + } + + return output.ToArray(); + } + break; + case 2: + words = input[idx].Split(' '); // count + if(words[0] == "count") + { + int c = int.Parse(words[1]); + if(c > 0) + return new String[0]; + break; + } + break; + } + idx++; + } + return output.ToArray(); + } + + public static bool IsCached(LLUUID assetID) + { + lock(m_Notecards) + { + return m_Notecards.ContainsKey(assetID); + } + } + + public static int GetLines(LLUUID assetID) + { + if(!IsCached(assetID)) + return -1; + + lock(m_Notecards) + { + m_Notecards[assetID].lastRef = DateTime.Now; + return m_Notecards[assetID].text.Length; + } + } + + public static string GetLine(LLUUID assetID, int line) + { + if(line < 0) + return ""; + + string data; + + if(!IsCached(assetID)) + return ""; + + lock(m_Notecards) + { + m_Notecards[assetID].lastRef = DateTime.Now; + + if(line >= m_Notecards[assetID].text.Length) + return "\n\n\n"; + + data=m_Notecards[assetID].text[line]; + if(data.Length > 255) + data = data.Substring(0, 255); + + return data; + } + } + + public static void CacheCheck() + { + foreach (LLUUID key in new List(m_Notecards.Keys)) + { + Notecard nc = m_Notecards[key]; + if(nc.lastRef.AddSeconds(30) < DateTime.Now) + m_Notecards.Remove(key); + } + } + + } +} diff --git a/OpenSim/Region/ScriptEngine/XEngine/OSSL_ScriptCommands.cs b/OpenSim/Region/ScriptEngine/XEngine/OSSL_ScriptCommands.cs new file mode 100644 index 0000000..bc4e8ba --- /dev/null +++ b/OpenSim/Region/ScriptEngine/XEngine/OSSL_ScriptCommands.cs @@ -0,0 +1,553 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using Axiom.Math; +using libsecondlife; +using Nini.Config; +using OpenSim.Framework.Console; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; +using OpenSim.Region.ScriptEngine.XEngine.Script; + +namespace OpenSim.Region.ScriptEngine.XEngine +{ + [Serializable] + public class OSSL_ScriptCommands : MarshalByRefObject, IOSSL_ScriptCommands + { + internal XEngine m_ScriptEngine; + internal XScriptInstance m_Instance; + internal SceneObjectPart m_host; + internal uint m_localID; + internal LLUUID m_itemID; + + public OSSL_ScriptCommands(XEngine scriptEngine, + XScriptInstance instance, SceneObjectPart host, + uint localID, LLUUID itemID) + { + m_ScriptEngine = scriptEngine; + m_Instance = instance; + m_host = host; + m_localID = localID; + m_itemID = itemID; + } + + + // + // OpenSim functions + // + + public int osTerrainSetHeight(int x, int y, double val) + { + if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false)) + { + OSSLError("osTerrainSetHeight: permission denied"); + return 0; + } + + m_host.AddScriptLPS(1); + if (x > 255 || x < 0 || y > 255 || y < 0) + OSSLError("osTerrainSetHeight: Coordinate out of bounds"); + + if (World.ExternalChecks.ExternalChecksCanTerraformLand(m_host.OwnerID, new LLVector3(x, y, 0))) + { + World.Heightmap[x, y] = val; + return 1; + } + else + { + return 0; + } + } + + public double osTerrainGetHeight(int x, int y) + { + if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false)) + { + OSSLError("osTerrainGetHeight: permission denied"); + return 0.0; + } + + m_host.AddScriptLPS(1); + if (x > 255 || x < 0 || y > 255 || y < 0) + OSSLError("osTerrainGetHeight: Coordinate out of bounds"); + + return World.Heightmap[x, y]; + } + + public int osRegionRestart(double seconds) + { + if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false)) + { + OSSLError("osRegionRestart: permission denied"); + return 0; + } + + m_host.AddScriptLPS(1); + if (World.ExternalChecks.ExternalChecksCanIssueEstateCommand(m_host.OwnerID)) + { + World.Restart((float)seconds); + return 1; + } + else + { + return 0; + } + } + + public void osRegionNotice(string msg) + { + if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false)) + { + OSSLError("osRegionNotice: permission denied"); + return; + } + + m_host.AddScriptLPS(1); + World.SendGeneralAlert(msg); + } + + public void osSetRot(LLUUID target, Quaternion rotation) + { + if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false)) + { + OSSLError("osSetRot: permission denied"); + return; + } + + m_host.AddScriptLPS(1); + if (World.Entities.ContainsKey(target)) + { + World.Entities[target].Rotation = rotation; + } + else + { + OSSLError("osSetRot: Invalid target"); + } + } + + public string osSetDynamicTextureURL(string dynamicID, string contentType, string url, string extraParams, + int timer) + { + if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false)) + { + OSSLError("osSetDynamicTextureURL: permission denied"); + return String.Empty; + } + + m_host.AddScriptLPS(1); + if (dynamicID == String.Empty) + { + IDynamicTextureManager textureManager = World.RequestModuleInterface(); + LLUUID createdTexture = + textureManager.AddDynamicTextureURL(World.RegionInfo.RegionID, m_host.UUID, contentType, url, + extraParams, timer); + return createdTexture.ToString(); + } + else + { + //TODO update existing dynamic textures + } + + return LLUUID.Zero.ToString(); + } + + public string osSetDynamicTextureURLBlend(string dynamicID, string contentType, string url, string extraParams, + int timer, int alpha) + { + if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false)) + { + OSSLError("osSetDynamicTextureURLBlend: permission denied"); + return String.Empty; + } + + m_host.AddScriptLPS(1); + if (dynamicID == String.Empty) + { + IDynamicTextureManager textureManager = World.RequestModuleInterface(); + LLUUID createdTexture = + textureManager.AddDynamicTextureURL(World.RegionInfo.RegionID, m_host.UUID, contentType, url, + extraParams, timer, true, (byte) alpha); + return createdTexture.ToString(); + } + else + { + //TODO update existing dynamic textures + } + + return LLUUID.Zero.ToString(); + } + + public string osSetDynamicTextureData(string dynamicID, string contentType, string data, string extraParams, + int timer) + { + if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false)) + { + OSSLError("osSetDynamicTextureData: permission denied"); + return String.Empty; + } + + m_host.AddScriptLPS(1); + if (dynamicID == String.Empty) + { + IDynamicTextureManager textureManager = World.RequestModuleInterface(); + if (textureManager != null) + { + LLUUID createdTexture = + textureManager.AddDynamicTextureData(World.RegionInfo.RegionID, m_host.UUID, contentType, data, + extraParams, timer); + return createdTexture.ToString(); + } + } + else + { + //TODO update existing dynamic textures + } + + return LLUUID.Zero.ToString(); + } + + public string osSetDynamicTextureDataBlend(string dynamicID, string contentType, string data, string extraParams, + int timer, int alpha) + { + if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false)) + { + OSSLError("osSetDynamicTextureDataBlend: permission denied"); + return String.Empty; + } + + m_host.AddScriptLPS(1); + if (dynamicID == String.Empty) + { + IDynamicTextureManager textureManager = World.RequestModuleInterface(); + if (textureManager != null) + { + LLUUID createdTexture = + textureManager.AddDynamicTextureData(World.RegionInfo.RegionID, m_host.UUID, contentType, data, + extraParams, timer, true, (byte) alpha); + return createdTexture.ToString(); + } + } + else + { + //TODO update existing dynamic textures + } + + return LLUUID.Zero.ToString(); + } + + public bool osConsoleCommand(string command) + { + m_host.AddScriptLPS(1); + if (m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowosConsoleCommand", false)) + { + if (World.ExternalChecks.ExternalChecksCanRunConsoleCommand(m_host.OwnerID)) + { + MainConsole.Instance.RunCommand(command); + return true; + } + return false; + } + return false; + } + public void osSetPrimFloatOnWater(int floatYN) + { + if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false)) + { + OSSLError("osSetPrimFloatOnWater: permission denied"); + return; + } + + m_host.AddScriptLPS(1); + if (m_host.ParentGroup != null) + { + if (m_host.ParentGroup.RootPart != null) + { + m_host.ParentGroup.RootPart.SetFloatOnWater(floatYN); + } + } + } + + // Adam's super super custom animation functions + public void osAvatarPlayAnimation(string avatar, string animation) + { + if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false)) + { + OSSLError("osAvatarPlayAnimation: permission denied"); + return; + } + + m_host.AddScriptLPS(1); + if (World.Entities.ContainsKey(avatar) && World.Entities[avatar] is ScenePresence) + { + ScenePresence target = (ScenePresence)World.Entities[avatar]; + target.AddAnimation(avatar); + } + } + + public void osAvatarStopAnimation(string avatar, string animation) + { + if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false)) + { + OSSLError("osAvatarStopAnimation: permission denied"); + return; + } + + m_host.AddScriptLPS(1); + if (World.Entities.ContainsKey(avatar) && World.Entities[avatar] is ScenePresence) + { + ScenePresence target = (ScenePresence)World.Entities[avatar]; + target.RemoveAnimation(animation); + } + } + + //Texture draw functions + public string osMovePen(string drawList, int x, int y) + { + if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false)) + { + OSSLError("osMovePen: permission denied"); + return String.Empty; + } + + m_host.AddScriptLPS(1); + drawList += "MoveTo " + x + "," + y + ";"; + return drawList; + } + + public string osDrawLine(string drawList, int startX, int startY, int endX, int endY) + { + if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false)) + { + OSSLError("osDrawLine: permission denied"); + return String.Empty; + } + + m_host.AddScriptLPS(1); + drawList += "MoveTo "+ startX+","+ startY +"; LineTo "+endX +","+endY +"; "; + return drawList; + } + + public string osDrawLine(string drawList, int endX, int endY) + { + if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false)) + { + OSSLError("osDrawLine: permission denied"); + return String.Empty; + } + + m_host.AddScriptLPS(1); + drawList += "LineTo " + endX + "," + endY + "; "; + return drawList; + } + + public string osDrawText(string drawList, string text) + { + if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false)) + { + OSSLError("osDrawText: permission denied"); + return String.Empty; + } + + m_host.AddScriptLPS(1); + drawList += "Text " + text + "; "; + return drawList; + } + + public string osDrawEllipse(string drawList, int width, int height) + { + if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false)) + { + OSSLError("osDrawEllipse: permission denied"); + return String.Empty; + } + + m_host.AddScriptLPS(1); + drawList += "Ellipse " + width + "," + height + "; "; + return drawList; + } + + public string osDrawRectangle(string drawList, int width, int height) + { + if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false)) + { + OSSLError("osDrawRectangle: permission denied"); + return String.Empty; + } + + m_host.AddScriptLPS(1); + drawList += "Rectangle " + width + "," + height + "; "; + return drawList; + } + + public string osDrawFilledRectangle(string drawList, int width, int height) + { + if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false)) + { + OSSLError("osDrawFilledRectangle: permission denied"); + return String.Empty; + } + + m_host.AddScriptLPS(1); + drawList += "FillRectangle " + width + "," + height + "; "; + return drawList; + } + + public string osSetFontSize(string drawList, int fontSize) + { + if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false)) + { + OSSLError("osSetFontSize: permission denied"); + return String.Empty; + } + + m_host.AddScriptLPS(1); + drawList += "FontSize "+ fontSize +"; "; + return drawList; + } + + public string osSetPenSize(string drawList, int penSize) + { + if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false)) + { + OSSLError("osSetPenSize: permission denied"); + return String.Empty; + } + + m_host.AddScriptLPS(1); + drawList += "PenSize " + penSize + "; "; + return drawList; + } + + public string osSetPenColour(string drawList, string colour) + { + if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false)) + { + OSSLError("osSetPenColour: permission denied"); + return String.Empty; + } + + m_host.AddScriptLPS(1); + drawList += "PenColour " + colour + "; "; + return drawList; + } + + public string osDrawImage(string drawList, int width, int height, string imageUrl) + { + if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false)) + { + OSSLError("osDrawImage: permission denied"); + return String.Empty; + } + + m_host.AddScriptLPS(1); + drawList +="Image " +width + "," + height+ ","+ imageUrl +"; " ; + return drawList; + } + + public void osSetStateEvents(int events) + { + if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false)) + { + OSSLError("osSetStateEvents: permission denied"); + return; + } + + m_host.SetScriptEvents(m_itemID, events); + } + + public void osSetRegionWaterHeight(double height) + { + if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false)) + { + OSSLError("osSetRegionWaterHeight: permission denied"); + return; + } + + m_host.AddScriptLPS(1); + //Check to make sure that the script's owner is the estate manager/master + //World.Permissions.GenericEstatePermission( + if (World.ExternalChecks.ExternalChecksCanBeGodLike(m_host.OwnerID)) + { + World.EventManager.TriggerRequestChangeWaterHeight((float)height); + } + } + + public double osList2Double(LSL_Types.list src, int index) + { + if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false)) + { + OSSLError("osList2Double: permission denied"); + return 0.0; + } + + m_host.AddScriptLPS(1); + if (index < 0) + { + index = src.Length + index; + } + if (index >= src.Length) + { + return 0.0; + } + return Convert.ToDouble(src.Data[index]); + } + + public void osSetParcelMediaURL(string url) + { + if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false)) + { + OSSLError("osSetParcelMediaURL: permission denied"); + return; + } + + m_host.AddScriptLPS(1); + LLUUID landowner = World.GetLandOwner(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); + + if (landowner == LLUUID.Zero) + { + return; + } + + if (landowner != m_host.ObjectOwner) + { + return; + } + + World.SetLandMediaURL(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y, url); + } + + public Scene World + { + get { return m_ScriptEngine.World; } + } + + internal void OSSLError(string msg) + { + throw new Exception("OSSL Runtime Error: " + msg); + } + } +} diff --git a/OpenSim/Region/ScriptEngine/XEngine/Script/AssemblyResolver.cs b/OpenSim/Region/ScriptEngine/XEngine/Script/AssemblyResolver.cs new file mode 100644 index 0000000..8107788 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/XEngine/Script/AssemblyResolver.cs @@ -0,0 +1,65 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.IO; +using System.Reflection; + +namespace OpenSim.Region.ScriptEngine.XEngine.Script +{ + [Serializable] + public class AssemblyResolver + { + public static Assembly OnAssemblyResolve(object sender, + ResolveEventArgs args) + { + if(!(sender is System.AppDomain)) + return null; + + AppDomain myDomain = (AppDomain)sender; + string dirName = myDomain.FriendlyName; + + string[] pathList=new string[] {"bin", "ScriptEngines", + Path.Combine("ScriptEngines", dirName)}; + + string assemblyName = args.Name; + if(assemblyName.IndexOf(",") != -1) + assemblyName=args.Name.Substring(0, args.Name.IndexOf(",")); + + foreach (string s in pathList) + { + string path=Path.Combine(Directory.GetCurrentDirectory(), + Path.Combine(s, assemblyName))+".dll"; + + if(File.Exists(path)) + return Assembly.LoadFrom(path); + } + + return null; + } + } +} diff --git a/OpenSim/Region/ScriptEngine/XEngine/Script/BuiltIn_Commands_BaseClass.cs b/OpenSim/Region/ScriptEngine/XEngine/Script/BuiltIn_Commands_BaseClass.cs new file mode 100644 index 0000000..bae8192 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/XEngine/Script/BuiltIn_Commands_BaseClass.cs @@ -0,0 +1,2393 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Runtime.Remoting.Lifetime; +using System.Threading; +using System.Reflection; +using System.Collections; +using System.Collections.Generic; +using OpenSim.Region.Environment.Interfaces; +using integer = OpenSim.Region.ScriptEngine.XEngine.Script.LSL_Types.LSLInteger; +using key = System.String; +using vector = OpenSim.Region.ScriptEngine.XEngine.Script.LSL_Types.Vector3; +using rotation = OpenSim.Region.ScriptEngine.XEngine.Script.LSL_Types.Quaternion; + +namespace OpenSim.Region.ScriptEngine.XEngine.Script +{ + public class BuiltIn_Commands_BaseClass : MarshalByRefObject, IOSSL_ScriptCommands, ILSL_ScriptCommands, IScript + { + //private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + // Object never expires + public override Object InitializeLifetimeService() + { + //Console.WriteLine("LSL_BaseClass: InitializeLifetimeService()"); + // return null; + ILease lease = (ILease)base.InitializeLifetimeService(); + + if (lease.CurrentState == LeaseState.Initial) + { + lease.InitialLeaseTime = TimeSpan.Zero; // TimeSpan.FromMinutes(1); + //lease.SponsorshipTimeout = TimeSpan.FromMinutes(2); + //lease.RenewOnCallTime = TimeSpan.FromSeconds(2); + } + return lease; + } + + public ILSL_ScriptCommands m_LSL_Functions; + public IOSSL_ScriptCommands m_OSSL_Functions; + + public BuiltIn_Commands_BaseClass() + { + } + + public Type Start(ILSL_ScriptCommands LSL_Functions, IOSSL_ScriptCommands OSSL_Functions) + { + m_LSL_Functions = LSL_Functions; + m_OSSL_Functions = OSSL_Functions; + m_InitialValues=GetVars(); + return GetType(); + } + + private Dictionary m_InitialValues = + new Dictionary(); + private Dictionary m_Fields = + new Dictionary(); + + public Dictionary GetVars() + { + m_Fields.Clear(); + + Dictionary vars = new Dictionary(); + + Type t = GetType(); + + FieldInfo[] fields = t.GetFields(BindingFlags.NonPublic | + BindingFlags.Public | + BindingFlags.Instance | + BindingFlags.DeclaredOnly); + + foreach (FieldInfo field in fields) + { + m_Fields[field.Name]=field; + + vars[field.Name]=field.GetValue(this); + } + + return vars; + } + + public void SetVars(Dictionary vars) + { + foreach (KeyValuePair var in vars) + { + if(m_Fields.ContainsKey(var.Key)) + { + m_Fields[var.Key].SetValue(this, var.Value); + } + } + } + + public void ResetVars() + { + SetVars(m_InitialValues); + } + + public string State + { + get { return m_LSL_Functions.State; } + set { m_LSL_Functions.State = value; } + } + + public void state(string newState) + { + m_LSL_Functions.state(newState); + } + + public void llSay(int channelID, string text) + { + m_LSL_Functions.llSay(channelID, text); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + // They are only forwarders to LSL_BuiltIn_Commands.cs + // + + public ICommander GetCommander(string name) + { + return m_LSL_Functions.GetCommander(name); + } + + public double llSin(double f) + { + return m_LSL_Functions.llSin(f); + } + public double llCos(double f) + { + return m_LSL_Functions.llCos(f); + } + + public double llTan(double f) + { + return m_LSL_Functions.llTan(f); + } + + public double llAtan2(double x, double y) + { + return m_LSL_Functions.llAtan2(x, y); + } + + public double llSqrt(double f) + { + return m_LSL_Functions.llSqrt(f); + } + + public double llPow(double fbase, double fexponent) + { + return m_LSL_Functions.llPow(fbase, fexponent); + } + + public LSL_Types.LSLInteger llAbs(int i) + { + return m_LSL_Functions.llAbs(i); + } + + public double llFabs(double f) + { + return m_LSL_Functions.llFabs(f); + } + + public double llFrand(double mag) + { + return m_LSL_Functions.llFrand(mag); + } + + public LSL_Types.LSLInteger llFloor(double f) + { + return m_LSL_Functions.llFloor(f); + } + + public LSL_Types.LSLInteger llCeil(double f) + { + return m_LSL_Functions.llCeil(f); + } + + public LSL_Types.LSLInteger llRound(double f) + { + return m_LSL_Functions.llRound(f); + } + + public double llVecMag(vector v) + { + return m_LSL_Functions.llVecMag(v); + } + + public vector llVecNorm(vector v) + { + return m_LSL_Functions.llVecNorm(v); + } + + public double llVecDist(vector a, vector b) + { + return m_LSL_Functions.llVecDist(a, b); + } + + public vector llRot2Euler(rotation r) + { + return m_LSL_Functions.llRot2Euler(r); + } + + public rotation llEuler2Rot(vector v) + { + return m_LSL_Functions.llEuler2Rot(v); + } + + public rotation llAxes2Rot(vector fwd, vector left, vector up) + { + return m_LSL_Functions.llAxes2Rot(fwd, left, up); + } + + public vector llRot2Fwd(rotation r) + { + return m_LSL_Functions.llRot2Fwd(r); + } + + public vector llRot2Left(rotation r) + { + return m_LSL_Functions.llRot2Left(r); + } + + public vector llRot2Up(rotation r) + { + return m_LSL_Functions.llRot2Up(r); + } + + public rotation llRotBetween(vector start, vector end) + { + return m_LSL_Functions.llRotBetween(start, end); + } + + public void llWhisper(int channelID, string text) + { + m_LSL_Functions.llWhisper(channelID, text); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public void llShout(int channelID, string text) + { + m_LSL_Functions.llShout(channelID, text); + } + + public void llRegionSay(int channelID, string text) + { + m_LSL_Functions.llRegionSay(channelID, text); + } + + public LSL_Types.LSLInteger llListen(int channelID, string name, string ID, string msg) + { + return m_LSL_Functions.llListen(channelID, name, ID, msg); + } + + public void llListenControl(int number, int active) + { + m_LSL_Functions.llListenControl(number, active); + } + + public void llListenRemove(int number) + { + m_LSL_Functions.llListenRemove(number); + } + + public void llSensor(string name, string id, int type, double range, double arc) + { + m_LSL_Functions.llSensor(name, id, type, range, arc); + } + + public void llSensorRepeat(string name, string id, int type, double range, double arc, double rate) + { + m_LSL_Functions.llSensorRepeat(name, id, type, range, arc, rate); + } + + public void llSensorRemove() + { + m_LSL_Functions.llSensorRemove(); + } + + public string llDetectedName(int number) + { + return m_LSL_Functions.llDetectedName(number); + } + + public string llDetectedKey(int number) + { + return m_LSL_Functions.llDetectedKey(number); + } + + public string llDetectedOwner(int number) + { + return m_LSL_Functions.llDetectedOwner(number); + } + + public LSL_Types.LSLInteger llDetectedType(int number) + { + return m_LSL_Functions.llDetectedType(number); + } + + public vector llDetectedPos(int number) + { + return m_LSL_Functions.llDetectedPos(number); + } + + public vector llDetectedVel(int number) + { + return m_LSL_Functions.llDetectedVel(number); + } + + public vector llDetectedGrab(int number) + { + return m_LSL_Functions.llDetectedGrab(number); + } + + public rotation llDetectedRot(int number) + { + return m_LSL_Functions.llDetectedRot(number); + } + + public LSL_Types.LSLInteger llDetectedGroup(int number) + { + return m_LSL_Functions.llDetectedGroup(number); + } + + public LSL_Types.LSLInteger llDetectedLinkNumber(int number) + { + return m_LSL_Functions.llDetectedLinkNumber(number); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public void llDie() + { + m_LSL_Functions.llDie(); + } + + public double llGround(vector offset) + { + return m_LSL_Functions.llGround(offset); + } + + public double llCloud(vector offset) + { + return m_LSL_Functions.llCloud(offset); + } + + public vector llWind(vector offset) + { + return m_LSL_Functions.llWind(offset); + } + + public void llSetStatus(int status, int value) + { + m_LSL_Functions.llSetStatus(status, value); + } + + public LSL_Types.LSLInteger llGetStatus(int status) + { + return m_LSL_Functions.llGetStatus(status); + } + + public void llSetScale(vector scale) + { + m_LSL_Functions.llSetScale(scale); + } + + public vector llGetScale() + { + return m_LSL_Functions.llGetScale(); + } + + public void llSetColor(vector color, int face) + { + m_LSL_Functions.llSetColor(color, face); + } + + public double llGetAlpha(int face) + { + return m_LSL_Functions.llGetAlpha(face); + } + + public void llSetAlpha(double alpha, int face) + { + m_LSL_Functions.llSetAlpha(alpha, face); + } + + public vector llGetColor(int face) + { + return m_LSL_Functions.llGetColor(face); + } + + public void llSetTexture(string texture, int face) + { + m_LSL_Functions.llSetTexture(texture, face); + } + + public void llScaleTexture(double u, double v, int face) + { + m_LSL_Functions.llScaleTexture(u, v, face); + } + + public void llOffsetTexture(double u, double v, int face) + { + m_LSL_Functions.llOffsetTexture(u, v, face); + } + + public void llRotateTexture(double rotation, int face) + { + m_LSL_Functions.llRotateTexture(rotation, face); + } + + public string llGetTexture(int face) + { + return m_LSL_Functions.llGetTexture(face); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public void llSetPos(vector pos) + { + m_LSL_Functions.llSetPos(pos); + } + + public vector llGetPos() + { + return m_LSL_Functions.llGetPos(); + } + + public vector llGetLocalPos() + { + return m_LSL_Functions.llGetLocalPos(); + } + + public void llSetRot(rotation rot) + { + m_LSL_Functions.llSetRot(rot); + } + + public rotation llGetRot() + { + return m_LSL_Functions.llGetRot(); + } + + public rotation llGetLocalRot() + { + return m_LSL_Functions.llGetLocalRot(); + } + + public void llSetForce(vector force, int local) + { + m_LSL_Functions.llSetForce(force, local); + } + + public vector llGetForce() + { + return m_LSL_Functions.llGetForce(); + } + + public LSL_Types.LSLInteger llTarget(vector position, double range) + { + return m_LSL_Functions.llTarget(position, range); + } + + public void llTargetRemove(int number) + { + m_LSL_Functions.llTargetRemove(number); + } + + public LSL_Types.LSLInteger llRotTarget(rotation rot, double error) + { + return m_LSL_Functions.llRotTarget(rot, error); + } + + public void llRotTargetRemove(int number) + { + m_LSL_Functions.llRotTargetRemove(number); + } + + public void llMoveToTarget(vector target, double tau) + { + m_LSL_Functions.llMoveToTarget(target, tau); + } + + public void llStopMoveToTarget() + { + m_LSL_Functions.llStopMoveToTarget(); + } + + public void llApplyImpulse(vector force, int local) + { + m_LSL_Functions.llApplyImpulse(force, local); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public void llApplyRotationalImpulse(vector force, int local) + { + m_LSL_Functions.llApplyRotationalImpulse(force, local); + } + + public void llSetTorque(vector torque, int local) + { + m_LSL_Functions.llSetTorque(torque, local); + } + + public vector llGetTorque() + { + return m_LSL_Functions.llGetTorque(); + } + + public void llSetForceAndTorque(vector force, vector torque, int local) + { + m_LSL_Functions.llSetForceAndTorque(force, torque, local); + } + + public vector llGetVel() + { + return m_LSL_Functions.llGetVel(); + } + + public vector llGetAccel() + { + return m_LSL_Functions.llGetAccel(); + } + + public vector llGetOmega() + { + return m_LSL_Functions.llGetOmega(); + } + + public double llGetTimeOfDay() + { + return m_LSL_Functions.llGetTimeOfDay(); + } + + public double llGetWallclock() + { + return m_LSL_Functions.llGetWallclock(); + } + + public double llGetTime() + { + return m_LSL_Functions.llGetTime(); + } + + public void llResetTime() + { + m_LSL_Functions.llResetTime(); + } + + public double llGetAndResetTime() + { + return m_LSL_Functions.llGetAndResetTime(); + } + + public void llSound() + { + m_LSL_Functions.llSound(); + } + + public void llPlaySound(string sound, double volume) + { + m_LSL_Functions.llPlaySound(sound, volume); + } + + public void llLoopSound(string sound, double volume) + { + m_LSL_Functions.llLoopSound(sound, volume); + } + + public void llLoopSoundMaster(string sound, double volume) + { + m_LSL_Functions.llLoopSoundMaster(sound, volume); + } + + public void llLoopSoundSlave(string sound, double volume) + { + m_LSL_Functions.llLoopSoundSlave(sound, volume); + } + + public void llPlaySoundSlave(string sound, double volume) + { + m_LSL_Functions.llPlaySoundSlave(sound, volume); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public void llTriggerSound(string sound, double volume) + { + m_LSL_Functions.llTriggerSound(sound, volume); + } + + public void llStopSound() + { + m_LSL_Functions.llStopSound(); + } + + public void llPreloadSound(string sound) + { + m_LSL_Functions.llPreloadSound(sound); + } + + public string llGetSubString(string src, int start, int end) + { + return m_LSL_Functions.llGetSubString(src, start, end); + } + + public string llDeleteSubString(string src, int start, int end) + { + return m_LSL_Functions.llDeleteSubString(src, start, end); + } + + public string llInsertString(string dst, int position, string src) + { + return m_LSL_Functions.llInsertString(dst, position, src); + } + + public string llToUpper(string source) + { + return m_LSL_Functions.llToUpper(source); + } + + public string llToLower(string source) + { + return m_LSL_Functions.llToLower(source); + } + + public LSL_Types.LSLInteger llGiveMoney(string destination, int amount) + { + return m_LSL_Functions.llGiveMoney(destination, amount); + } + + public void llMakeExplosion() + { + m_LSL_Functions.llMakeExplosion(); + } + + public void llMakeFountain() + { + m_LSL_Functions.llMakeFountain(); + } + + public void llMakeSmoke() + { + m_LSL_Functions.llMakeSmoke(); + } + + public void llMakeFire() + { + m_LSL_Functions.llMakeFire(); + } + + public void llRezObject(string inventory, vector pos, vector vel, rotation rot, int param) + { + m_LSL_Functions.llRezObject(inventory, pos, vel, rot, param); + } + + public void llLookAt(vector target, double strength, double damping) + { + m_LSL_Functions.llLookAt(target, strength, damping); + } + + public void llStopLookAt() + { + m_LSL_Functions.llStopLookAt(); + } + + public void llSetTimerEvent(double sec) + { + m_LSL_Functions.llSetTimerEvent(sec); + } + + public void llSleep(double sec) + { + m_LSL_Functions.llSleep(sec); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public double llGetMass() + { + return m_LSL_Functions.llGetMass(); + } + + public void llCollisionFilter(string name, string id, int accept) + { + m_LSL_Functions.llCollisionFilter(name, id, accept); + } + + public void llTakeControls(int controls, int accept, int pass_on) + { + m_LSL_Functions.llTakeControls(controls, accept, pass_on); + } + + public void llReleaseControls() + { + m_LSL_Functions.llReleaseControls(); + } + + public void llAttachToAvatar(int attachment) + { + m_LSL_Functions.llAttachToAvatar(attachment); + } + + public void llDetachFromAvatar() + { + m_LSL_Functions.llDetachFromAvatar(); + } + + public void llTakeCamera() + { + m_LSL_Functions.llTakeCamera(); + } + + public void llReleaseCamera() + { + m_LSL_Functions.llReleaseCamera(); + } + + public string llGetOwner() + { + return m_LSL_Functions.llGetOwner(); + } + + public void llInstantMessage(string user, string message) + { + m_LSL_Functions.llInstantMessage(user, message); + } + + public void llEmail(string address, string subject, string message) + { + m_LSL_Functions.llEmail(address, subject, message); + } + + public void llGetNextEmail(string address, string subject) + { + m_LSL_Functions.llGetNextEmail(address, subject); + } + + public string llGetKey() + { + return m_LSL_Functions.llGetKey(); + } + + public void llSetBuoyancy(double buoyancy) + { + m_LSL_Functions.llSetBuoyancy(buoyancy); + } + + public void llSetHoverHeight(double height, int water, double tau) + { + m_LSL_Functions.llSetHoverHeight(height, water, tau); + } + + public void llStopHover() + { + m_LSL_Functions.llStopHover(); + } + + public void llMinEventDelay(double delay) + { + m_LSL_Functions.llMinEventDelay(delay); + } + + public void llSoundPreload() + { + m_LSL_Functions.llSoundPreload(); + } + + public void llRotLookAt(rotation target, double strength, double damping) + { + m_LSL_Functions.llRotLookAt(target, strength, damping); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public LSL_Types.LSLInteger llStringLength(string str) + { + return m_LSL_Functions.llStringLength(str); + } + + public void llStartAnimation(string anim) + { + m_LSL_Functions.llStartAnimation(anim); + } + + public void llStopAnimation(string anim) + { + m_LSL_Functions.llStopAnimation(anim); + } + + public void llPointAt() + { + m_LSL_Functions.llPointAt(); + } + + public void llStopPointAt() + { + m_LSL_Functions.llStopPointAt(); + } + + public void llTargetOmega(vector axis, double spinrate, double gain) + { + m_LSL_Functions.llTargetOmega(axis, spinrate, gain); + } + + public LSL_Types.LSLInteger llGetStartParameter() + { + return m_LSL_Functions.llGetStartParameter(); + } + + public void llGodLikeRezObject(string inventory, vector pos) + { + m_LSL_Functions.llGodLikeRezObject(inventory, pos); + } + + public void llRequestPermissions(string agent, int perm) + { + m_LSL_Functions.llRequestPermissions(agent, perm); + } + + public string llGetPermissionsKey() + { + return m_LSL_Functions.llGetPermissionsKey(); + } + + public LSL_Types.LSLInteger llGetPermissions() + { + return m_LSL_Functions.llGetPermissions(); + } + + public LSL_Types.LSLInteger llGetLinkNumber() + { + return m_LSL_Functions.llGetLinkNumber(); + } + + public void llSetLinkColor(int linknumber, vector color, int face) + { + m_LSL_Functions.llSetLinkColor(linknumber, color, face); + } + + public void llCreateLink(string target, int parent) + { + m_LSL_Functions.llCreateLink(target, parent); + } + + public void llBreakLink(int linknum) + { + m_LSL_Functions.llBreakLink(linknum); + } + + public void llBreakAllLinks() + { + m_LSL_Functions.llBreakAllLinks(); + } + + public string llGetLinkKey(int linknum) + { + return m_LSL_Functions.llGetLinkKey(linknum); + } + + public string llGetLinkName(int linknum) + { + return m_LSL_Functions.llGetLinkName(linknum); + } + + public LSL_Types.LSLInteger llGetInventoryNumber(int type) + { + return m_LSL_Functions.llGetInventoryNumber(type); + } + + public string llGetInventoryName(int type, int number) + { + return m_LSL_Functions.llGetInventoryName(type, number); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public void llSetScriptState(string name, int run) + { + m_LSL_Functions.llSetScriptState(name, run); + } + + public double llGetEnergy() + { + return m_LSL_Functions.llGetEnergy(); + } + + public void llGiveInventory(string destination, string inventory) + { + m_LSL_Functions.llGiveInventory(destination, inventory); + } + + public void llRemoveInventory(string item) + { + m_LSL_Functions.llRemoveInventory(item); + } + + public void llSetText(string text, vector color, double alpha) + { + m_LSL_Functions.llSetText(text, color, alpha); + } + + public double llWater(vector offset) + { + return m_LSL_Functions.llWater(offset); + } + + public void llPassTouches(int pass) + { + m_LSL_Functions.llPassTouches(pass); + } + + public string llRequestAgentData(string id, int data) + { + return m_LSL_Functions.llRequestAgentData(id, data); + } + + public string llRequestInventoryData(string name) + { + return m_LSL_Functions.llRequestInventoryData(name); + } + + public void llSetDamage(double damage) + { + m_LSL_Functions.llSetDamage(damage); + } + + public void llTeleportAgentHome(string agent) + { + m_LSL_Functions.llTeleportAgentHome(agent); + } + + public void llModifyLand(int action, int brush) + { + m_LSL_Functions.llModifyLand(action, brush); + } + + public void llCollisionSound(string impact_sound, double impact_volume) + { + m_LSL_Functions.llCollisionSound(impact_sound, impact_volume); + } + + public void llCollisionSprite(string impact_sprite) + { + m_LSL_Functions.llCollisionSprite(impact_sprite); + } + + public string llGetAnimation(string id) + { + return m_LSL_Functions.llGetAnimation(id); + } + + public void llResetScript() + { + m_LSL_Functions.llResetScript(); + } + + public void llMessageLinked(int linknum, int num, string str, string id) + { + m_LSL_Functions.llMessageLinked(linknum, num, str, id); + } + + public void llPushObject(string target, vector impulse, vector ang_impulse, int local) + { + m_LSL_Functions.llPushObject(target, impulse, ang_impulse, local); + } + + public void llPassCollisions(int pass) + { + m_LSL_Functions.llPassCollisions(pass); + } + + public string llGetScriptName() + { + return m_LSL_Functions.llGetScriptName(); + } + + public LSL_Types.LSLInteger llGetNumberOfSides() + { + return m_LSL_Functions.llGetNumberOfSides(); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public rotation llAxisAngle2Rot(vector axis, double angle) + { + return m_LSL_Functions.llAxisAngle2Rot(axis, angle); + } + + public vector llRot2Axis(rotation rot) + { + return m_LSL_Functions.llRot2Axis(rot); + } + + public double llRot2Angle(rotation rot) + { + return m_LSL_Functions.llRot2Angle(rot); + } + + public double llAcos(double val) + { + return m_LSL_Functions.llAcos(val); + } + + public double llAsin(double val) + { + return m_LSL_Functions.llAsin(val); + } + + public double llAngleBetween(rotation a, rotation b) + { + return m_LSL_Functions.llAngleBetween(a, b); + } + + public string llGetInventoryKey(string name) + { + return m_LSL_Functions.llGetInventoryKey(name); + } + + public void llAllowInventoryDrop(int add) + { + m_LSL_Functions.llAllowInventoryDrop(add); + } + + public vector llGetSunDirection() + { + return m_LSL_Functions.llGetSunDirection(); + } + + public vector llGetTextureOffset(int face) + { + return m_LSL_Functions.llGetTextureOffset(face); + } + + public vector llGetTextureScale(int side) + { + return m_LSL_Functions.llGetTextureScale(side); + } + + public double llGetTextureRot(int side) + { + return m_LSL_Functions.llGetTextureRot(side); + } + + public LSL_Types.LSLInteger llSubStringIndex(string source, string pattern) + { + return m_LSL_Functions.llSubStringIndex(source, pattern); + } + + public string llGetOwnerKey(string id) + { + return m_LSL_Functions.llGetOwnerKey(id); + } + + public vector llGetCenterOfMass() + { + return m_LSL_Functions.llGetCenterOfMass(); + } + + public LSL_Types.list llListSort(LSL_Types.list src, int stride, int ascending) + { + return m_LSL_Functions.llListSort(src, stride, ascending); + } + + public LSL_Types.LSLInteger llGetListLength(LSL_Types.list src) + { + return m_LSL_Functions.llGetListLength(src); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public LSL_Types.LSLInteger llList2Integer(LSL_Types.list src, int index) + { + return m_LSL_Functions.llList2Integer(src, index); + } + + public string llList2String(LSL_Types.list src, int index) + { + return m_LSL_Functions.llList2String(src, index); + } + + public string llList2Key(LSL_Types.list src, int index) + { + return m_LSL_Functions.llList2Key(src, index); + } + + public vector llList2Vector(LSL_Types.list src, int index) + { + return m_LSL_Functions.llList2Vector(src, index); + } + + public rotation llList2Rot(LSL_Types.list src, int index) + { + return m_LSL_Functions.llList2Rot(src, index); + } + + public LSL_Types.list llList2List(LSL_Types.list src, int start, int end) + { + return m_LSL_Functions.llList2List(src, start, end); + } + + public LSL_Types.list llDeleteSubList(LSL_Types.list src, int start, int end) + { + return m_LSL_Functions.llDeleteSubList(src, start, end); + } + + public LSL_Types.LSLInteger llGetListEntryType(LSL_Types.list src, int index) + { + return m_LSL_Functions.llGetListEntryType(src, index); + } + + public string llList2CSV(LSL_Types.list src) + { + return m_LSL_Functions.llList2CSV(src); + } + + public LSL_Types.list llCSV2List(string src) + { + return m_LSL_Functions.llCSV2List(src); + } + + public LSL_Types.list llListRandomize(LSL_Types.list src, int stride) + { + return m_LSL_Functions.llListRandomize(src, stride); + } + + public LSL_Types.list llList2ListStrided(LSL_Types.list src, int start, int end, int stride) + { + return m_LSL_Functions.llList2ListStrided(src, start, end, stride); + } + + public vector llGetRegionCorner() + { + return m_LSL_Functions.llGetRegionCorner(); + } + + public LSL_Types.list llListInsertList(LSL_Types.list dest, LSL_Types.list src, int start) + { + return m_LSL_Functions.llListInsertList(dest, src, start); + } + + public LSL_Types.LSLInteger llListFindList(LSL_Types.list src, LSL_Types.list test) + { + return m_LSL_Functions.llListFindList(src, test); + } + + public string llGetObjectName() + { + return m_LSL_Functions.llGetObjectName(); + } + + public void llSetObjectName(string name) + { + m_LSL_Functions.llSetObjectName(name); + } + + public string llGetDate() + { + return m_LSL_Functions.llGetDate(); + } + + public LSL_Types.LSLInteger llEdgeOfWorld(vector pos, vector dir) + { + return m_LSL_Functions.llEdgeOfWorld(pos, dir); + } + + public LSL_Types.LSLInteger llGetAgentInfo(string id) + { + return m_LSL_Functions.llGetAgentInfo(id); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public void llAdjustSoundVolume(double volume) + { + m_LSL_Functions.llAdjustSoundVolume(volume); + } + + public void llSetSoundQueueing(int queue) + { + m_LSL_Functions.llSetSoundQueueing(queue); + } + + public void llSetSoundRadius(double radius) + { + m_LSL_Functions.llSetSoundRadius(radius); + } + + public string llKey2Name(string id) + { + return m_LSL_Functions.llKey2Name(id); + } + + public void llSetTextureAnim(int mode, int face, int sizex, int sizey, double start, double length, double rate) + { + m_LSL_Functions.llSetTextureAnim(mode, face, sizex, sizey, start, length, rate); + } + + public void llTriggerSoundLimited(string sound, double volume, vector top_north_east, vector bottom_south_west) + { + m_LSL_Functions.llTriggerSoundLimited(sound, volume, top_north_east, bottom_south_west); + } + + public void llEjectFromLand(string pest) + { + m_LSL_Functions.llEjectFromLand(pest); + } + + public LSL_Types.list llParseString2List(string str, LSL_Types.list separators, LSL_Types.list spacers) + { + return m_LSL_Functions.llParseString2List(str,separators,spacers); + } + + public LSL_Types.LSLInteger llOverMyLand(string id) + { + return m_LSL_Functions.llOverMyLand(id); + } + + public string llGetLandOwnerAt(vector pos) + { + return m_LSL_Functions.llGetLandOwnerAt(pos); + } + + public string llGetNotecardLine(string name, int line) + { + return m_LSL_Functions.llGetNotecardLine(name, line); + } + + public vector llGetAgentSize(string id) + { + return m_LSL_Functions.llGetAgentSize(id); + } + + public LSL_Types.LSLInteger llSameGroup(string agent) + { + return m_LSL_Functions.llSameGroup(agent); + } + + public void llUnSit(string id) + { + m_LSL_Functions.llUnSit(id); + } + + public vector llGroundSlope(vector offset) + { + return m_LSL_Functions.llGroundSlope(offset); + } + + public vector llGroundNormal(vector offset) + { + return m_LSL_Functions.llGroundNormal(offset); + } + + public vector llGroundContour(vector offset) + { + return m_LSL_Functions.llGroundContour(offset); + } + + public LSL_Types.LSLInteger llGetAttached() + { + return m_LSL_Functions.llGetAttached(); + } + + public LSL_Types.LSLInteger llGetFreeMemory() + { + return m_LSL_Functions.llGetFreeMemory(); + } + + public string llGetRegionName() + { + return m_LSL_Functions.llGetRegionName(); + } + + public double llGetRegionTimeDilation() + { + return m_LSL_Functions.llGetRegionTimeDilation(); + } + + public double llGetRegionFPS() + { + return m_LSL_Functions.llGetRegionFPS(); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public void llParticleSystem(LSL_Types.list rules) + { + m_LSL_Functions.llParticleSystem(rules); + } + + public void llGroundRepel(double height, int water, double tau) + { + m_LSL_Functions.llGroundRepel(height, water, tau); + } + + public void llGiveInventoryList(string destination, string category, LSL_Types.list inventory) + { + m_LSL_Functions.llGiveInventoryList(destination, category, inventory); + } + + public void llSetVehicleType(int type) + { + m_LSL_Functions.llSetVehicleType(type); + } + + public void llSetVehicledoubleParam(int param, double value) + { + m_LSL_Functions.llSetVehicledoubleParam(param, value); + } + + public void llSetVehicleFloatParam(int param, float value) + { + m_LSL_Functions.llSetVehicleFloatParam(param, value); + } + + public void llSetVehicleVectorParam(int param, vector vec) + { + m_LSL_Functions.llSetVehicleVectorParam(param, vec); + } + + public void llSetVehicleRotationParam(int param, rotation rot) + { + m_LSL_Functions.llSetVehicleRotationParam(param, rot); + } + + public void llSetVehicleFlags(int flags) + { + m_LSL_Functions.llSetVehicleFlags(flags); + } + + public void llRemoveVehicleFlags(int flags) + { + m_LSL_Functions.llRemoveVehicleFlags(flags); + } + + public void llSitTarget(vector offset, rotation rot) + { + m_LSL_Functions.llSitTarget(offset, rot); + } + + public string llAvatarOnSitTarget() + { + return m_LSL_Functions.llAvatarOnSitTarget(); + } + + public void llAddToLandPassList(string avatar, double hours) + { + m_LSL_Functions.llAddToLandPassList(avatar, hours); + } + + public void llSetTouchText(string text) + { + m_LSL_Functions.llSetTouchText(text); + } + + public void llSetSitText(string text) + { + m_LSL_Functions.llSetSitText(text); + } + + public void llSetCameraEyeOffset(vector offset) + { + m_LSL_Functions.llSetCameraEyeOffset(offset); + } + + public void llSetCameraAtOffset(vector offset) + { + m_LSL_Functions.llSetCameraAtOffset(offset); + } + + public string llDumpList2String(LSL_Types.list src, string seperator) + { + return m_LSL_Functions.llDumpList2String(src, seperator); + } + + public LSL_Types.LSLInteger llScriptDanger(vector pos) + { + return m_LSL_Functions.llScriptDanger(pos); + } + + public void llDialog(string avatar, string message, LSL_Types.list buttons, int chat_channel) + { + m_LSL_Functions.llDialog(avatar, message, buttons, chat_channel); + } + + public void llVolumeDetect(int detect) + { + m_LSL_Functions.llVolumeDetect(detect); + } + + public void llResetOtherScript(string name) + { + m_LSL_Functions.llResetOtherScript(name); + } + + public LSL_Types.LSLInteger llGetScriptState(string name) + { + return m_LSL_Functions.llGetScriptState(name); + } + + public void llRemoteLoadScript() + { + m_LSL_Functions.llRemoteLoadScript(); + } + + public void llSetRemoteScriptAccessPin(int pin) + { + m_LSL_Functions.llSetRemoteScriptAccessPin(pin); + } + + public void llRemoteLoadScriptPin(string target, string name, int pin, int running, int start_param) + { + m_LSL_Functions.llRemoteLoadScriptPin(target, name, pin, running, start_param); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public void llOpenRemoteDataChannel() + { + m_LSL_Functions.llOpenRemoteDataChannel(); + } + + public string llSendRemoteData(string channel, string dest, int idata, string sdata) + { + return m_LSL_Functions.llSendRemoteData(channel, dest, idata, sdata); + } + + public void llRemoteDataReply(string channel, string message_id, string sdata, int idata) + { + m_LSL_Functions.llRemoteDataReply(channel, message_id, sdata, idata); + } + + public void llCloseRemoteDataChannel(string channel) + { + m_LSL_Functions.llCloseRemoteDataChannel(channel); + } + + public string llMD5String(string src, int nonce) + { + return m_LSL_Functions.llMD5String(src, nonce); + } + + public void llSetPrimitiveParams(LSL_Types.list rules) + { + m_LSL_Functions.llSetPrimitiveParams(rules); + } + + public void llSetLinkPrimitiveParams(int linknumber, LSL_Types.list rules) + { + m_LSL_Functions.llSetLinkPrimitiveParams(linknumber, rules); + } + public string llStringToBase64(string str) + { + return m_LSL_Functions.llStringToBase64(str); + } + + public string llBase64ToString(string str) + { + return m_LSL_Functions.llBase64ToString(str); + } + + public void llXorBase64Strings() + { + m_LSL_Functions.llXorBase64Strings(); + } + + public void llRemoteDataSetRegion() + { + m_LSL_Functions.llRemoteDataSetRegion(); + } + + public double llLog10(double val) + { + return m_LSL_Functions.llLog10(val); + } + + public double llLog(double val) + { + return m_LSL_Functions.llLog(val); + } + + public LSL_Types.list llGetAnimationList(string id) + { + return m_LSL_Functions.llGetAnimationList(id); + } + + public void llSetParcelMusicURL(string url) + { + m_LSL_Functions.llSetParcelMusicURL(url); + } + + public vector llGetRootPosition() + { + return m_LSL_Functions.llGetRootPosition(); + } + + public rotation llGetRootRotation() + { + return m_LSL_Functions.llGetRootRotation(); + } + + public string llGetObjectDesc() + { + return m_LSL_Functions.llGetObjectDesc(); + } + + public void llSetObjectDesc(string desc) + { + m_LSL_Functions.llSetObjectDesc(desc); + } + + public string llGetCreator() + { + return m_LSL_Functions.llGetCreator(); + } + + public string llGetTimestamp() + { + return m_LSL_Functions.llGetTimestamp(); + } + + public void llSetLinkAlpha(int linknumber, double alpha, int face) + { + m_LSL_Functions.llSetLinkAlpha(linknumber, alpha, face); + } + + public LSL_Types.LSLInteger llGetNumberOfPrims() + { + return m_LSL_Functions.llGetNumberOfPrims(); + } + + public string llGetNumberOfNotecardLines(string name) + { + return m_LSL_Functions.llGetNumberOfNotecardLines(name); + } + + public LSL_Types.list llGetBoundingBox(string obj) + { + return m_LSL_Functions.llGetBoundingBox(obj); + } + + public vector llGetGeometricCenter() + { + return m_LSL_Functions.llGetGeometricCenter(); + } + + public LSL_Types.list llGetPrimitiveParams(LSL_Types.list rules) + { + return m_LSL_Functions.llGetPrimitiveParams(rules); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public string llIntegerToBase64(int number) + { + return m_LSL_Functions.llIntegerToBase64(number); + } + + public LSL_Types.LSLInteger llBase64ToInteger(string str) + { + return m_LSL_Functions.llBase64ToInteger(str); + } + + public double llGetGMTclock() + { + return m_LSL_Functions.llGetGMTclock(); + } + + public string llGetSimulatorHostname() + { + return m_LSL_Functions.llGetSimulatorHostname(); + } + + public void llSetLocalRot(rotation rot) + { + m_LSL_Functions.llSetLocalRot(rot); + } + + public LSL_Types.list llParseStringKeepNulls(string src, LSL_Types.list seperators, LSL_Types.list spacers) + { + return m_LSL_Functions.llParseStringKeepNulls(src, seperators, spacers); + } + + public void llRezAtRoot(string inventory, vector position, vector velocity, rotation rot, int param) + { + m_LSL_Functions.llRezAtRoot(inventory, position, velocity, rot, param); + } + + public LSL_Types.LSLInteger llGetObjectPermMask(int mask) + { + return m_LSL_Functions.llGetObjectPermMask(mask); + } + + public void llSetObjectPermMask(int mask, int value) + { + m_LSL_Functions.llSetObjectPermMask(mask, value); + } + + public LSL_Types.LSLInteger llGetInventoryPermMask(string item, int mask) + { + return m_LSL_Functions.llGetInventoryPermMask(item, mask); + } + + public void llSetInventoryPermMask(string item, int mask, int value) + { + m_LSL_Functions.llSetInventoryPermMask(item, mask, value); + } + + public string llGetInventoryCreator(string item) + { + return m_LSL_Functions.llGetInventoryCreator(item); + } + + public void llOwnerSay(string msg) + { + m_LSL_Functions.llOwnerSay(msg); + } + + public string llRequestSimulatorData(string simulator, int data) + { + return m_LSL_Functions.llRequestSimulatorData(simulator, data); + } + + public void llForceMouselook(int mouselook) + { + m_LSL_Functions.llForceMouselook(mouselook); + } + + public double llGetObjectMass(string id) + { + return m_LSL_Functions.llGetObjectMass(id); + } + + public LSL_Types.list llListReplaceList(LSL_Types.list dest, LSL_Types.list src, int start, int end) + { + return m_LSL_Functions.llListReplaceList(dest, src, start, end); + } + + public void llLoadURL(string avatar_id, string message, string url) + { + m_LSL_Functions.llLoadURL(avatar_id, message, url); + } + + public void llParcelMediaCommandList(LSL_Types.list commandList) + { + m_LSL_Functions.llParcelMediaCommandList(commandList); + } + + public void llParcelMediaQuery() + { + m_LSL_Functions.llParcelMediaQuery(); + } + + public LSL_Types.LSLInteger llModPow(int a, int b, int c) + { + return m_LSL_Functions.llModPow(a, b, c); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public LSL_Types.LSLInteger llGetInventoryType(string name) + { + return m_LSL_Functions.llGetInventoryType(name); + } + + public void llSetPayPrice(int price, LSL_Types.list quick_pay_buttons) + { + m_LSL_Functions.llSetPayPrice(price, quick_pay_buttons); + } + + public vector llGetCameraPos() + { + return m_LSL_Functions.llGetCameraPos(); + } + + public rotation llGetCameraRot() + { + return m_LSL_Functions.llGetCameraRot(); + } + + public void llSetPrimURL() + { + m_LSL_Functions.llSetPrimURL(); + } + + public void llRefreshPrimURL() + { + m_LSL_Functions.llRefreshPrimURL(); + } + + public string llEscapeURL(string url) + { + return m_LSL_Functions.llEscapeURL(url); + } + + public string llUnescapeURL(string url) + { + return m_LSL_Functions.llUnescapeURL(url); + } + + public void llMapDestination(string simname, vector pos, vector look_at) + { + m_LSL_Functions.llMapDestination(simname, pos, look_at); + } + + public void llAddToLandBanList(string avatar, double hours) + { + m_LSL_Functions.llAddToLandBanList(avatar, hours); + } + + public void llRemoveFromLandPassList(string avatar) + { + m_LSL_Functions.llRemoveFromLandPassList(avatar); + } + + public void llRemoveFromLandBanList(string avatar) + { + m_LSL_Functions.llRemoveFromLandBanList(avatar); + } + + public void llSetCameraParams(LSL_Types.list rules) + { + m_LSL_Functions.llSetCameraParams(rules); + } + + public void llClearCameraParams() + { + m_LSL_Functions.llClearCameraParams(); + } + + public double llListStatistics(int operation, LSL_Types.list src) + { + return m_LSL_Functions.llListStatistics(operation, src); + } + + public LSL_Types.LSLInteger llGetUnixTime() + { + return m_LSL_Functions.llGetUnixTime(); + } + + public LSL_Types.LSLInteger llGetParcelFlags(vector pos) + { + return m_LSL_Functions.llGetParcelFlags(pos); + } + + public LSL_Types.LSLInteger llGetRegionFlags() + { + return m_LSL_Functions.llGetRegionFlags(); + } + + public string llXorBase64StringsCorrect(string str1, string str2) + { + return m_LSL_Functions.llXorBase64StringsCorrect(str1, str2); + } + + public string llHTTPRequest(string url, LSL_Types.list parameters, string body) + { + return m_LSL_Functions.llHTTPRequest(url, parameters, body); + } + + public void llResetLandBanList() + { + m_LSL_Functions.llResetLandBanList(); + } + + public void llResetLandPassList() + { + m_LSL_Functions.llResetLandPassList(); + } + + public LSL_Types.LSLInteger llGetParcelPrimCount(vector pos, int category, int sim_wide) + { + return m_LSL_Functions.llGetParcelPrimCount(pos, category, sim_wide); + } + + public LSL_Types.list llGetParcelPrimOwners(vector pos) + { + return m_LSL_Functions.llGetParcelPrimOwners(pos); + } + + public LSL_Types.LSLInteger llGetObjectPrimCount(string object_id) + { + return m_LSL_Functions.llGetObjectPrimCount(object_id); + } + + // + // DO NOT MODIFY HERE: MODIFY IN LSL_BuiltIn_Commands.cs + // + public LSL_Types.LSLInteger llGetParcelMaxPrims(vector pos, int sim_wide) + { + return m_LSL_Functions.llGetParcelMaxPrims(pos, sim_wide); + } + + public LSL_Types.list llGetParcelDetails(vector pos, LSL_Types.list param) + { + return m_LSL_Functions.llGetParcelDetails(pos, param); + } + + public void llSetLinkTexture(int linknumber, string texture, int face) + { + m_LSL_Functions.llSetLinkTexture(linknumber, texture, face); + } + + public string llStringTrim(string src, int type) + { + return m_LSL_Functions.llStringTrim(src, type); + } + + public LSL_Types.list llGetObjectDetails(string id, LSL_Types.list args) + { + return m_LSL_Functions.llGetObjectDetails(id, args); + } + + public double llList2Float(LSL_Types.list src, int index) + { + return m_LSL_Functions.llList2Float(src, index); + } + + // LSL CONSTANTS + public const int TRUE = 1; + public const int FALSE = 0; + + public const int STATUS_PHYSICS = 1; + public const int STATUS_ROTATE_X = 2; + public const int STATUS_ROTATE_Y = 4; + public const int STATUS_ROTATE_Z = 8; + public const int STATUS_PHANTOM = 16; + public const int STATUS_SANDBOX = 32; + public const int STATUS_BLOCK_GRAB = 64; + public const int STATUS_DIE_AT_EDGE = 128; + public const int STATUS_RETURN_AT_EDGE = 256; + public const int STATUS_CAST_SHADOWS = 512; + + public const int AGENT = 1; + public const int ACTIVE = 2; + public const int PASSIVE = 4; + public const int SCRIPTED = 8; + + public const int CONTROL_FWD = 1; + public const int CONTROL_BACK = 2; + public const int CONTROL_LEFT = 4; + public const int CONTROL_RIGHT = 8; + public const int CONTROL_UP = 16; + public const int CONTROL_DOWN = 32; + public const int CONTROL_ROT_LEFT = 256; + public const int CONTROL_ROT_RIGHT = 512; + public const int CONTROL_LBUTTON = 268435456; + public const int CONTROL_ML_LBUTTON = 1073741824; + + //Permissions + public const int PERMISSION_DEBIT = 2; + public const int PERMISSION_TAKE_CONTROLS = 4; + public const int PERMISSION_REMAP_CONTROLS = 8; + public const int PERMISSION_TRIGGER_ANIMATION = 16; + public const int PERMISSION_ATTACH = 32; + public const int PERMISSION_RELEASE_OWNERSHIP = 64; + public const int PERMISSION_CHANGE_LINKS = 128; + public const int PERMISSION_CHANGE_JOINTS = 256; + public const int PERMISSION_CHANGE_PERMISSIONS = 512; + public const int PERMISSION_TRACK_CAMERA = 1024; + + public const int AGENT_FLYING = 1; + public const int AGENT_ATTACHMENTS = 2; + public const int AGENT_SCRIPTED = 4; + public const int AGENT_MOUSELOOK = 8; + public const int AGENT_SITTING = 16; + public const int AGENT_ON_OBJECT = 32; + public const int AGENT_AWAY = 64; + public const int AGENT_WALKING = 128; + public const int AGENT_IN_AIR = 256; + public const int AGENT_TYPING = 512; + public const int AGENT_CROUCHING = 1024; + public const int AGENT_BUSY = 2048; + public const int AGENT_ALWAYS_RUN = 4096; + + //Particle Systems + public const int PSYS_PART_INTERP_COLOR_MASK = 1; + public const int PSYS_PART_INTERP_SCALE_MASK = 2; + public const int PSYS_PART_BOUNCE_MASK = 4; + public const int PSYS_PART_WIND_MASK = 8; + public const int PSYS_PART_FOLLOW_SRC_MASK = 16; + public const int PSYS_PART_FOLLOW_VELOCITY_MASK = 32; + public const int PSYS_PART_TARGET_POS_MASK = 64; + public const int PSYS_PART_TARGET_LINEAR_MASK = 128; + public const int PSYS_PART_EMISSIVE_MASK = 256; + public const int PSYS_PART_FLAGS = 0; + public const int PSYS_PART_START_COLOR = 1; + public const int PSYS_PART_START_ALPHA = 2; + public const int PSYS_PART_END_COLOR = 3; + public const int PSYS_PART_END_ALPHA = 4; + public const int PSYS_PART_START_SCALE = 5; + public const int PSYS_PART_END_SCALE = 6; + public const int PSYS_PART_MAX_AGE = 7; + public const int PSYS_SRC_ACCEL = 8; + public const int PSYS_SRC_PATTERN = 9; + public const int PSYS_SRC_INNERANGLE = 10; + public const int PSYS_SRC_OUTERANGLE = 11; + public const int PSYS_SRC_TEXTURE = 12; + public const int PSYS_SRC_BURST_RATE = 13; + public const int PSYS_SRC_BURST_PART_COUNT = 15; + public const int PSYS_SRC_BURST_RADIUS = 16; + public const int PSYS_SRC_BURST_SPEED_MIN = 17; + public const int PSYS_SRC_BURST_SPEED_MAX = 18; + public const int PSYS_SRC_MAX_AGE = 19; + public const int PSYS_SRC_TARGET_KEY = 20; + public const int PSYS_SRC_OMEGA = 21; + public const int PSYS_SRC_ANGLE_BEGIN = 22; + public const int PSYS_SRC_ANGLE_END = 23; + public const int PSYS_SRC_PATTERN_DROP = 1; + public const int PSYS_SRC_PATTERN_EXPLODE = 2; + public const int PSYS_SRC_PATTERN_ANGLE = 4; + public const int PSYS_SRC_PATTERN_ANGLE_CONE = 8; + public const int PSYS_SRC_PATTERN_ANGLE_CONE_EMPTY = 16; + + public const int VEHICLE_TYPE_NONE = 0; + public const int VEHICLE_TYPE_SLED = 1; + public const int VEHICLE_TYPE_CAR = 2; + public const int VEHICLE_TYPE_BOAT = 3; + public const int VEHICLE_TYPE_AIRPLANE = 4; + public const int VEHICLE_TYPE_BALLOON = 5; + public const int VEHICLE_LINEAR_FRICTION_TIMESCALE = 16; + public const int VEHICLE_ANGULAR_FRICTION_TIMESCALE = 17; + public const int VEHICLE_LINEAR_MOTOR_DIRECTION = 18; + public const int VEHICLE_LINEAR_MOTOR_OFFSET = 20; + public const int VEHICLE_ANGULAR_MOTOR_DIRECTION = 19; + public const int VEHICLE_HOVER_HEIGHT = 24; + public const int VEHICLE_HOVER_EFFICIENCY = 25; + public const int VEHICLE_HOVER_TIMESCALE = 26; + public const int VEHICLE_BUOYANCY = 27; + public const int VEHICLE_LINEAR_DEFLECTION_EFFICIENCY = 28; + public const int VEHICLE_LINEAR_DEFLECTION_TIMESCALE = 29; + public const int VEHICLE_LINEAR_MOTOR_TIMESCALE = 30; + public const int VEHICLE_LINEAR_MOTOR_DECAY_TIMESCALE = 31; + public const int VEHICLE_ANGULAR_DEFLECTION_EFFICIENCY = 32; + public const int VEHICLE_ANGULAR_DEFLECTION_TIMESCALE = 33; + public const int VEHICLE_ANGULAR_MOTOR_TIMESCALE = 34; + public const int VEHICLE_ANGULAR_MOTOR_DECAY_TIMESCALE = 35; + public const int VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY = 36; + public const int VEHICLE_VERTICAL_ATTRACTION_TIMESCALE = 37; + public const int VEHICLE_BANKING_EFFICIENCY = 38; + public const int VEHICLE_BANKING_MIX = 39; + public const int VEHICLE_BANKING_TIMESCALE = 40; + public const int VEHICLE_REFERENCE_FRAME = 44; + public const int VEHICLE_FLAG_NO_DEFLECTION_UP = 1; + public const int VEHICLE_FLAG_LIMIT_ROLL_ONLY = 2; + public const int VEHICLE_FLAG_HOVER_WATER_ONLY = 4; + public const int VEHICLE_FLAG_HOVER_TERRAIN_ONLY = 8; + public const int VEHICLE_FLAG_HOVER_GLOBAL_HEIGHT = 16; + public const int VEHICLE_FLAG_HOVER_UP_ONLY = 32; + public const int VEHICLE_FLAG_LIMIT_MOTOR_UP = 64; + public const int VEHICLE_FLAG_MOUSELOOK_STEER = 128; + public const int VEHICLE_FLAG_MOUSELOOK_BANK = 256; + public const int VEHICLE_FLAG_CAMERA_DECOUPLED = 512; + + public const int INVENTORY_ALL = -1; + public const int INVENTORY_NONE = -1; + public const int INVENTORY_TEXTURE = 0; + public const int INVENTORY_SOUND = 1; + public const int INVENTORY_LANDMARK = 3; + public const int INVENTORY_CLOTHING = 5; + public const int INVENTORY_OBJECT = 6; + public const int INVENTORY_NOTECARD = 7; + public const int INVENTORY_SCRIPT = 10; + public const int INVENTORY_BODYPART = 13; + public const int INVENTORY_ANIMATION = 20; + public const int INVENTORY_GESTURE = 21; + + public const int ATTACH_CHEST = 1; + public const int ATTACH_HEAD = 2; + public const int ATTACH_LSHOULDER = 3; + public const int ATTACH_RSHOULDER = 4; + public const int ATTACH_LHAND = 5; + public const int ATTACH_RHAND = 6; + public const int ATTACH_LFOOT = 7; + public const int ATTACH_RFOOT = 8; + public const int ATTACH_BACK = 9; + public const int ATTACH_PELVIS = 10; + public const int ATTACH_MOUTH = 11; + public const int ATTACH_CHIN = 12; + public const int ATTACH_LEAR = 13; + public const int ATTACH_REAR = 14; + public const int ATTACH_LEYE = 15; + public const int ATTACH_REYE = 16; + public const int ATTACH_NOSE = 17; + public const int ATTACH_RUARM = 18; + public const int ATTACH_RLARM = 19; + public const int ATTACH_LUARM = 20; + public const int ATTACH_LLARM = 21; + public const int ATTACH_RHIP = 22; + public const int ATTACH_RULEG = 23; + public const int ATTACH_RLLEG = 24; + public const int ATTACH_LHIP = 25; + public const int ATTACH_LULEG = 26; + public const int ATTACH_LLLEG = 27; + public const int ATTACH_BELLY = 28; + public const int ATTACH_RPEC = 29; + public const int ATTACH_LPEC = 30; + + public const int LAND_LEVEL = 0; + public const int LAND_RAISE = 1; + public const int LAND_LOWER = 2; + public const int LAND_SMOOTH = 3; + public const int LAND_NOISE = 4; + public const int LAND_REVERT = 5; + public const int LAND_SMALL_BRUSH = 1; + public const int LAND_MEDIUM_BRUSH = 2; + public const int LAND_LARGE_BRUSH = 3; + + //Agent Dataserver + public const int DATA_ONLINE = 1; + public const int DATA_NAME = 2; + public const int DATA_BORN = 3; + public const int DATA_RATING = 4; + public const int DATA_SIM_POS = 5; + public const int DATA_SIM_STATUS = 6; + public const int DATA_SIM_RATING = 7; + public const int DATA_PAYINFO = 8; + + public const int ANIM_ON = 1; + public const int LOOP = 2; + public const int REVERSE = 4; + public const int PING_PONG = 8; + public const int SMOOTH = 16; + public const int ROTATE = 32; + public const int SCALE = 64; + public const int ALL_SIDES = -1; + public const int LINK_SET = -1; + public const int LINK_ROOT = 1; + public const int LINK_ALL_OTHERS = -2; + public const int LINK_ALL_CHILDREN = -3; + public const int LINK_THIS = -4; + public const int CHANGED_INVENTORY = 1; + public const int CHANGED_COLOR = 2; + public const int CHANGED_SHAPE = 4; + public const int CHANGED_SCALE = 8; + public const int CHANGED_TEXTURE = 16; + public const int CHANGED_LINK = 32; + public const int CHANGED_ALLOWED_DROP = 64; + public const int CHANGED_OWNER = 128; + public const int TYPE_INVALID = 0; + public const int TYPE_INTEGER = 1; + public const int TYPE_double = 2; + public const int TYPE_STRING = 3; + public const int TYPE_KEY = 4; + public const int TYPE_VECTOR = 5; + public const int TYPE_ROTATION = 6; + + //XML RPC Remote Data Channel + public const int REMOTE_DATA_CHANNEL = 1; + public const int REMOTE_DATA_REQUEST = 2; + public const int REMOTE_DATA_REPLY = 3; + + //llHTTPRequest + public const int HTTP_METHOD = 0; + public const int HTTP_MIMETYPE = 1; + public const int HTTP_BODY_MAXLENGTH = 2; + public const int HTTP_VERIFY_CERT = 3; + + public const int PRIM_MATERIAL = 2; + public const int PRIM_PHYSICS = 3; + public const int PRIM_TEMP_ON_REZ = 4; + public const int PRIM_PHANTOM = 5; + public const int PRIM_POSITION = 6; + public const int PRIM_SIZE = 7; + public const int PRIM_ROTATION = 8; + public const int PRIM_TYPE = 9; + public const int PRIM_TEXTURE = 17; + public const int PRIM_COLOR = 18; + public const int PRIM_BUMP_SHINY = 19; + public const int PRIM_FULLBRIGHT = 20; + public const int PRIM_FLEXIBLE = 21; + public const int PRIM_TEXGEN = 22; + public const int PRIM_CAST_SHADOWS = 24; // Not implemented, here for completeness sake + public const int PRIM_POINT_LIGHT = 23; // Huh? + public const int PRIM_TEXGEN_DEFAULT = 0; + public const int PRIM_TEXGEN_PLANAR = 1; + + public const int PRIM_TYPE_BOX = 0; + public const int PRIM_TYPE_CYLINDER = 1; + public const int PRIM_TYPE_PRISM = 2; + public const int PRIM_TYPE_SPHERE = 3; + public const int PRIM_TYPE_TORUS = 4; + public const int PRIM_TYPE_TUBE = 5; + public const int PRIM_TYPE_RING = 6; + public const int PRIM_TYPE_SCULPT = 7; + + public const int PRIM_HOLE_DEFAULT = 0; + public const int PRIM_HOLE_CIRCLE = 16; + public const int PRIM_HOLE_SQUARE = 32; + public const int PRIM_HOLE_TRIANGLE = 48; + + public const int PRIM_MATERIAL_STONE = 0; + public const int PRIM_MATERIAL_METAL = 1; + public const int PRIM_MATERIAL_GLASS = 2; + public const int PRIM_MATERIAL_WOOD = 3; + public const int PRIM_MATERIAL_FLESH = 4; + public const int PRIM_MATERIAL_PLASTIC = 5; + public const int PRIM_MATERIAL_RUBBER = 6; + public const int PRIM_MATERIAL_LIGHT = 7; + + public const int PRIM_SHINY_NONE = 0; + public const int PRIM_SHINY_LOW = 1; + public const int PRIM_SHINY_MEDIUM = 2; + public const int PRIM_SHINY_HIGH = 3; + public const int PRIM_BUMP_NONE = 0; + public const int PRIM_BUMP_BRIGHT = 1; + public const int PRIM_BUMP_DARK = 2; + public const int PRIM_BUMP_WOOD = 3; + public const int PRIM_BUMP_BARK = 4; + public const int PRIM_BUMP_BRICKS = 5; + public const int PRIM_BUMP_CHECKER = 6; + public const int PRIM_BUMP_CONCRETE = 7; + public const int PRIM_BUMP_TILE = 8; + public const int PRIM_BUMP_STONE = 9; + public const int PRIM_BUMP_DISKS = 10; + public const int PRIM_BUMP_GRAVEL = 11; + public const int PRIM_BUMP_BLOBS = 12; + public const int PRIM_BUMP_SIDING = 13; + public const int PRIM_BUMP_LARGETILE = 14; + public const int PRIM_BUMP_STUCCO = 15; + public const int PRIM_BUMP_SUCTION = 16; + public const int PRIM_BUMP_WEAVE = 17; + + public const int PRIM_SCULPT_TYPE_SPHERE = 1; + public const int PRIM_SCULPT_TYPE_TORUS = 2; + public const int PRIM_SCULPT_TYPE_PLANE = 3; + public const int PRIM_SCULPT_TYPE_CYLINDER = 4; + + public const int MASK_BASE = 0; + public const int MASK_OWNER = 1; + public const int MASK_GROUP = 2; + public const int MASK_EVERYONE = 3; + public const int MASK_NEXT = 4; + + public const int PERM_TRANSFER = 8192; + public const int PERM_MODIFY = 16384; + public const int PERM_COPY = 32768; + public const int PERM_MOVE = 524288; + public const int PERM_ALL = 2147483647; + + public const int PARCEL_MEDIA_COMMAND_STOP = 0; + public const int PARCEL_MEDIA_COMMAND_PAUSE = 1; + public const int PARCEL_MEDIA_COMMAND_PLAY = 2; + public const int PARCEL_MEDIA_COMMAND_LOOP = 3; + public const int PARCEL_MEDIA_COMMAND_TEXTURE = 4; + public const int PARCEL_MEDIA_COMMAND_URL = 5; + public const int PARCEL_MEDIA_COMMAND_TIME = 6; + public const int PARCEL_MEDIA_COMMAND_AGENT = 7; + public const int PARCEL_MEDIA_COMMAND_UNLOAD = 8; + public const int PARCEL_MEDIA_COMMAND_AUTO_ALIGN = 9; + + public const int PAY_HIDE = -1; + public const int PAY_DEFAULT = -2; + + public const string NULL_KEY = "00000000-0000-0000-0000-000000000000"; + public const string EOF = "\n\n\n"; + public const double PI = 3.14159274f; + public const double TWO_PI = 6.28318548f; + public const double PI_BY_TWO = 1.57079637f; + public const double DEG_TO_RAD = 0.01745329238f; + public const double RAD_TO_DEG = 57.29578f; + public const double SQRT2 = 1.414213538f; + public const int STRING_TRIM_HEAD = 1; + public const int STRING_TRIM_TAIL = 2; + public const int STRING_TRIM = 3; + public const int LIST_STAT_RANGE = 0; + public const int LIST_STAT_MIN = 1; + public const int LIST_STAT_MAX = 2; + public const int LIST_STAT_MEAN = 3; + public const int LIST_STAT_MEDIAN = 4; + public const int LIST_STAT_STD_DEV = 5; + public const int LIST_STAT_SUM = 6; + public const int LIST_STAT_SUM_SQUARES = 7; + public const int LIST_STAT_NUM_COUNT = 8; + public const int LIST_STAT_GEOMETRIC_MEAN = 9; + public const int LIST_STAT_HARMONIC_MEAN = 100; + + //ParcelPrim Categories + public const int PARCEL_COUNT_TOTAL = 0; + public const int PARCEL_COUNT_OWNER = 1; + public const int PARCEL_COUNT_GROUP = 2; + public const int PARCEL_COUNT_OTHER = 3; + public const int PARCEL_COUNT_SELECTED = 4; + public const int PARCEL_COUNT_TEMP = 5; + + public const int DEBUG_CHANNEL = 0x7FFFFFFF; + public const int PUBLIC_CHANNEL = 0x00000000; + + public const int OBJECT_NAME = 1; + public const int OBJECT_DESC = 2; + public const int OBJECT_POS = 3; + public const int OBJECT_ROT = 4; + public const int OBJECT_VELOCITY = 5; + public const int OBJECT_OWNER = 6; + public const int OBJECT_GROUP = 7; + public const int OBJECT_CREATOR = 8; + + // Can not be public const? + public vector ZERO_VECTOR = new vector(0.0, 0.0, 0.0); + public rotation ZERO_ROTATION = new rotation(0.0, 0, 0.0, 1.0); + + + // + // OSSL + // + // FIXME: Refactor so we don't need to pull the script engine + // into the app domain + // + + public void osSetRegionWaterHeight(double height) + { + m_OSSL_Functions.osSetRegionWaterHeight(height); + } + + public double osList2Double(LSL_Types.list src, int index) + { + return m_OSSL_Functions.osList2Double(src, index); + } + + public string osSetDynamicTextureURL(string dynamicID, string contentType, string url, string extraParams, + int timer) + { + return m_OSSL_Functions.osSetDynamicTextureURL(dynamicID, contentType, url, extraParams, timer); + } + + public string osSetDynamicTextureData(string dynamicID, string contentType, string data, string extraParams, + int timer) + { + return m_OSSL_Functions.osSetDynamicTextureData(dynamicID, contentType, data, extraParams, timer); + } + + public string osSetDynamicTextureURLBlend(string dynamicID, string contentType, string url, string extraParams, + int timer, int alpha) + { + return m_OSSL_Functions.osSetDynamicTextureURLBlend(dynamicID, contentType, url, extraParams, timer, alpha); + } + + public string osSetDynamicTextureDataBlend(string dynamicID, string contentType, string data, string extraParams, + int timer, int alpha) + { + return m_OSSL_Functions.osSetDynamicTextureDataBlend(dynamicID, contentType, data, extraParams, timer, alpha); + } + + public double osTerrainGetHeight(int x, int y) + { + return m_OSSL_Functions.osTerrainGetHeight(x, y); + } + + public int osTerrainSetHeight(int x, int y, double val) + { + return m_OSSL_Functions.osTerrainSetHeight(x, y, val); + } + + public int osRegionRestart(double seconds) + { + return m_OSSL_Functions.osRegionRestart(seconds); + } + + public void osRegionNotice(string msg) + { + m_OSSL_Functions.osRegionNotice(msg); + } + + public bool osConsoleCommand(string Command) + { + return m_OSSL_Functions.osConsoleCommand(Command); + } + + public void osSetParcelMediaURL(string url) + { + m_OSSL_Functions.osSetParcelMediaURL(url); + } + + public void osSetPrimFloatOnWater(int floatYN) + { + m_OSSL_Functions.osSetPrimFloatOnWater(floatYN); + } + + // Animation Functions + + public void osAvatarPlayAnimation(string avatar, string animation) + { + m_OSSL_Functions.osAvatarPlayAnimation(avatar, animation); + } + + public void osAvatarStopAnimation(string avatar, string animation) + { + m_OSSL_Functions.osAvatarStopAnimation(avatar, animation); + } + + + //Texture Draw functions + + public string osMovePen(string drawList, int x, int y) + { + return m_OSSL_Functions.osMovePen(drawList, x, y); + } + + public string osDrawLine(string drawList, int startX, int startY, int endX, int endY) + { + return m_OSSL_Functions.osDrawLine(drawList, startX, startY, endX, endY); + } + + public string osDrawLine(string drawList, int endX, int endY) + { + return m_OSSL_Functions.osDrawLine(drawList, endX, endY); + } + + public string osDrawText(string drawList, string text) + { + return m_OSSL_Functions.osDrawText(drawList, text); + } + + public string osDrawEllipse(string drawList, int width, int height) + { + return m_OSSL_Functions.osDrawEllipse(drawList, width, height); + } + + public string osDrawRectangle(string drawList, int width, int height) + { + return m_OSSL_Functions.osDrawRectangle(drawList, width, height); + } + + public string osDrawFilledRectangle(string drawList, int width, int height) + { + return m_OSSL_Functions.osDrawFilledRectangle(drawList, width, height); + } + + public string osSetFontSize(string drawList, int fontSize) + { + return m_OSSL_Functions.osSetFontSize(drawList, fontSize); + } + + public string osSetPenSize(string drawList, int penSize) + { + return m_OSSL_Functions.osSetPenSize(drawList, penSize); + } + + public string osSetPenColour(string drawList, string colour) + { + return m_OSSL_Functions.osSetPenColour(drawList, colour); + } + + public string osDrawImage(string drawList, int width, int height, string imageUrl) + { + return m_OSSL_Functions.osDrawImage(drawList, width, height, imageUrl); + } + public void osSetStateEvents(int events) + { + m_OSSL_Functions.osSetStateEvents(events); + } + } +} diff --git a/OpenSim/Region/ScriptEngine/XEngine/Script/ILSL_ScriptCommands.cs b/OpenSim/Region/ScriptEngine/XEngine/Script/ILSL_ScriptCommands.cs new file mode 100644 index 0000000..9e8965c --- /dev/null +++ b/OpenSim/Region/ScriptEngine/XEngine/Script/ILSL_ScriptCommands.cs @@ -0,0 +1,653 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using OpenSim.Region.Environment.Interfaces; + +namespace OpenSim.Region.ScriptEngine.XEngine.Script +{ + public interface ILSL_ScriptCommands + { + // Interface used for loading and executing scripts + + string State { get; set ; } + + void state(string newState); + + ICommander GetCommander(string name); + + void llSay(int channelID, string text); + double llSin(double f); + double llCos(double f); + double llTan(double f); + double llAtan2(double x, double y); + double llSqrt(double f); + double llPow(double fbase, double fexponent); + LSL_Types.LSLInteger llAbs(int i); + double llFabs(double f); + double llFrand(double mag); + LSL_Types.LSLInteger llFloor(double f); + LSL_Types.LSLInteger llCeil(double f); + LSL_Types.LSLInteger llRound(double f); + double llVecMag(LSL_Types.Vector3 v); + LSL_Types.Vector3 llVecNorm(LSL_Types.Vector3 v); + double llVecDist(LSL_Types.Vector3 a, LSL_Types.Vector3 b); + LSL_Types.Vector3 llRot2Euler(LSL_Types.Quaternion r); + LSL_Types.Quaternion llEuler2Rot(LSL_Types.Vector3 v); + LSL_Types.Quaternion llAxes2Rot(LSL_Types.Vector3 fwd, LSL_Types.Vector3 left, LSL_Types.Vector3 up); + LSL_Types.Vector3 llRot2Fwd(LSL_Types.Quaternion r); + LSL_Types.Vector3 llRot2Left(LSL_Types.Quaternion r); + LSL_Types.Vector3 llRot2Up(LSL_Types.Quaternion r); + LSL_Types.Quaternion llRotBetween(LSL_Types.Vector3 start, LSL_Types.Vector3 end); + void llWhisper(int channelID, string text); + //void llSay(int channelID, string text); + void llShout(int channelID, string text); + void llRegionSay(int channelID, string text); + LSL_Types.LSLInteger llListen(int channelID, string name, string ID, string msg); + void llListenControl(int number, int active); + void llListenRemove(int number); + void llSensor(string name, string id, int type, double range, double arc); + void llSensorRepeat(string name, string id, int type, double range, double arc, double rate); + void llSensorRemove(); + string llDetectedName(int number); + string llDetectedKey(int number); + string llDetectedOwner(int number); + LSL_Types.LSLInteger llDetectedType(int number); + LSL_Types.Vector3 llDetectedPos(int number); + LSL_Types.Vector3 llDetectedVel(int number); + LSL_Types.Vector3 llDetectedGrab(int number); + LSL_Types.Quaternion llDetectedRot(int number); + LSL_Types.LSLInteger llDetectedGroup(int number); + LSL_Types.LSLInteger llDetectedLinkNumber(int number); + void llDie(); + double llGround(LSL_Types.Vector3 offset); + double llCloud(LSL_Types.Vector3 offset); + LSL_Types.Vector3 llWind(LSL_Types.Vector3 offset); + void llSetStatus(int status, int value); + LSL_Types.LSLInteger llGetStatus(int status); + void llSetScale(LSL_Types.Vector3 scale); + LSL_Types.Vector3 llGetScale(); + void llSetColor(LSL_Types.Vector3 color, int face); + double llGetAlpha(int face); + void llSetAlpha(double alpha, int face); + LSL_Types.Vector3 llGetColor(int face); + void llSetTexture(string texture, int face); + void llScaleTexture(double u, double v, int face); + void llOffsetTexture(double u, double v, int face); + void llRotateTexture(double rotation, int face); + string llGetTexture(int face); + void llSetPos(LSL_Types.Vector3 pos); + + //wiki: vector llGetPos() + LSL_Types.Vector3 llGetPos(); + //wiki: vector llGetLocalPos() + LSL_Types.Vector3 llGetLocalPos(); + //wiki: llSetRot(rotation rot) + void llSetRot(LSL_Types.Quaternion rot); + //wiki: rotation llGetRot() + LSL_Types.Quaternion llGetRot(); + //wiki: rotation llGetLocalRot() + LSL_Types.Quaternion llGetLocalRot(); + //wiki: llSetForce(vector force, integer local) + void llSetForce(LSL_Types.Vector3 force, int local); + //wiki: vector llGetForce() + LSL_Types.Vector3 llGetForce(); + //wiki: integer llTarget(vector position, double range) + LSL_Types.LSLInteger llTarget(LSL_Types.Vector3 position, double range); + //wiki: llTargetRemove(integer number) + void llTargetRemove(int number); + //wiki: integer llRotTarget(rotation rot, double error) + LSL_Types.LSLInteger llRotTarget(LSL_Types.Quaternion rot, double error); + //wiki: integer llRotTargetRemove(integer number) + void llRotTargetRemove(int number); + //wiki: llMoveToTarget(vector target, double tau) + void llMoveToTarget(LSL_Types.Vector3 target, double tau); + //wiki: llStopMoveToTarget() + void llStopMoveToTarget(); + //wiki: llApplyImpulse(vector force, integer local) + void llApplyImpulse(LSL_Types.Vector3 force, int local); + //wiki: llapplyRotationalImpulse(vector force, integer local) + void llApplyRotationalImpulse(LSL_Types.Vector3 force, int local); + //wiki: llSetTorque(vector torque, integer local) + void llSetTorque(LSL_Types.Vector3 torque, int local); + //wiki: vector llGetTorque() + LSL_Types.Vector3 llGetTorque(); + //wiki: llSeForceAndTorque(vector force, vector torque, integer local) + void llSetForceAndTorque(LSL_Types.Vector3 force, LSL_Types.Vector3 torque, int local); + //wiki: vector llGetVel() + LSL_Types.Vector3 llGetVel(); + //wiki: vector llGetAccel() + LSL_Types.Vector3 llGetAccel(); + //wiki: vector llGetOmega() + LSL_Types.Vector3 llGetOmega(); + //wiki: double llGetTimeOfDay() + double llGetTimeOfDay(); + //wiki: double llGetWallclock() + double llGetWallclock(); + //wiki: double llGetTime() + double llGetTime(); + //wiki: llResetTime() + void llResetTime(); + //wiki: double llGetAndResetTime() + double llGetAndResetTime(); + //wiki (deprecated) llSound(string sound, double volume, integer queue, integer loop) + void llSound(); + //wiki: llPlaySound(string sound, double volume) + void llPlaySound(string sound, double volume); + //wiki: llLoopSound(string sound, double volume) + void llLoopSound(string sound, double volume); + //wiki: llLoopSoundMaster(string sound, double volume) + void llLoopSoundMaster(string sound, double volume); + //wiki: llLoopSoundSlave(string sound, double volume) + void llLoopSoundSlave(string sound, double volume); + //wiki llPlaySoundSlave(string sound, double volume) + void llPlaySoundSlave(string sound, double volume); + //wiki: llTriggerSound(string sound, double volume) + void llTriggerSound(string sound, double volume); + //wiki: llStopSound() + void llStopSound(); + //wiki: llPreloadSound(string sound) + void llPreloadSound(string sound); + //wiki: string llGetSubString(string src, integer start, integer end) + string llGetSubString(string src, int start, int end); + //wiki: string llDeleteSubString(string src, integer start, integer end) + string llDeleteSubString(string src, int start, int end); + //wiki string llInsertString(string dst, integer position, string src) + string llInsertString(string dst, int position, string src); + //wiki: string llToUpper(string source) + string llToUpper(string source); + //wiki: string llToLower(string source) + string llToLower(string source); + //wiki: integer llGiveMoney(key destination, integer amount) + LSL_Types.LSLInteger llGiveMoney(string destination, int amount); + //wiki: (deprecated) + void llMakeExplosion(); + //wiki: (deprecated) + void llMakeFountain(); + //wiki: (deprecated) + void llMakeSmoke(); + //wiki: (deprecated) + void llMakeFire(); + //wiki: llRezObject(string inventory, vector pos, vector rel, rotation rot, integer param) + void llRezObject(string inventory, LSL_Types.Vector3 pos, LSL_Types.Vector3 vel, LSL_Types.Quaternion rot, int param); + //wiki: llLookAt(vector target, double strength, double damping) + void llLookAt(LSL_Types.Vector3 target, double strength, double damping); + //wiki: llStopLookAt() + void llStopLookAt(); + //wiki: llSetTimerEvent(double sec) + void llSetTimerEvent(double sec); + //wiki: llSleep(double sec) + void llSleep(double sec); + //wiki: double llGetMass() + double llGetMass(); + //wiki: llCollisionFilter(string name, key id, integer accept) + void llCollisionFilter(string name, string id, int accept); + //wiki: llTakeControls(integer controls, integer accept, integer pass_on) + void llTakeControls(int controls, int accept, int pass_on); + //wiki: llReleaseControls() + void llReleaseControls(); + //wiki: llAttachToAvatar(integer attachment) + void llAttachToAvatar(int attachment); + //wiki: llDetachFromAvatar() + void llDetachFromAvatar(); + //wiki: (deprecated) llTakeCamera() + void llTakeCamera(); + //wiki: (deprecated) llReleaseCamera() + void llReleaseCamera(); + //wiki: key llGetOwner() + string llGetOwner(); + //wiki: llInstantMessage(key user, string message) + void llInstantMessage(string user, string message); + //wiki: llEmail(string address, string subject, string message) + void llEmail(string address, string subject, string message); + //wiki: llGetNextEmail(string address, string subject) + void llGetNextEmail(string address, string subject); + //wiki: key llGetKey() + string llGetKey(); + //wiki: llSetBuoyancy(double buoyancy) + void llSetBuoyancy(double buoyancy); + //wiki: llSetHoverHeight(double height, integer water, double tau) + void llSetHoverHeight(double height, int water, double tau); + //wiki: llStopHover + void llStopHover(); + //wiki: llMinEventDelay(double delay) + void llMinEventDelay(double delay); + //wiki: (deprecated) llSoundPreload() + void llSoundPreload(); + //wiki: llRotLookAt(rotation target, double strength, double damping) + void llRotLookAt(LSL_Types.Quaternion target, double strength, double damping); + //wiki: integer llStringLength(string str) + LSL_Types.LSLInteger llStringLength(string str); + //wiki: llStartAnimation(string anim) + void llStartAnimation(string anim); + //wiki: llStopAnimation(string anim) + void llStopAnimation(string anim); + //wiki: (deprecated) llPointAt + void llPointAt(); + //wiki: (deprecated) llStopPointAt + void llStopPointAt(); + //wiki: llTargetOmega(vector axis, double spinrate, double gain) + void llTargetOmega(LSL_Types.Vector3 axis, double spinrate, double gain); + //wiki: integer llGetStartParameter() + LSL_Types.LSLInteger llGetStartParameter(); + //wiki: llGodLikeRezObject(key inventory, vector pos) + void llGodLikeRezObject(string inventory, LSL_Types.Vector3 pos); + //wiki: llRequestPermissions(key agent, integer perm) + void llRequestPermissions(string agent, int perm); + //wiki: key llGetPermissionsKey() + string llGetPermissionsKey(); + //wiki: integer llGetPermissions() + LSL_Types.LSLInteger llGetPermissions(); + //wiki integer llGetLinkNumber() + LSL_Types.LSLInteger llGetLinkNumber(); + //wiki: llSetLinkColor(integer linknumber, vector color, integer face) + void llSetLinkColor(int linknumber, LSL_Types.Vector3 color, int face); + //wiki: llCreateLink(key target, integer parent) + void llCreateLink(string target, int parent); + //wiki: llBreakLink(integer linknum) + void llBreakLink(int linknum); + //wiki: llBreakAllLinks() + void llBreakAllLinks(); + //wiki: key llGetLinkKey(integer linknum) + string llGetLinkKey(int linknum); + //wiki: llGetLinkName(integer linknum) + string llGetLinkName(int linknum); + //wiki: integer llGetInventoryNumber(integer type) + LSL_Types.LSLInteger llGetInventoryNumber(int type); + //wiki: string llGetInventoryName(integer type, integer number) + string llGetInventoryName(int type, int number); + //wiki: llSetScriptState(string name, integer run) + void llSetScriptState(string name, int run); + //wiki: double llGetEnergy() + double llGetEnergy(); + //wiki: llGiveInventory(key destination, string inventory) + void llGiveInventory(string destination, string inventory); + //wiki: llRemoveInventory(string item) + void llRemoveInventory(string item); + //wiki: llSetText(string text, vector color, double alpha) + void llSetText(string text, LSL_Types.Vector3 color, double alpha); + //wiki: double llWater(vector offset) + double llWater(LSL_Types.Vector3 offset); + //wiki: llPassTouches(integer pass) + void llPassTouches(int pass); + //wiki: key llRequestAgentData(key id, integer data) + string llRequestAgentData(string id, int data); + //wiki: key llRequestInventoryData(string name) + string llRequestInventoryData(string name); + //wiki: llSetDamage(double damage) + void llSetDamage(double damage); + //wiki: llTeleportAgentHome(key agent) + void llTeleportAgentHome(string agent); + //wiki: llModifyLand(integer action, integer brush) + void llModifyLand(int action, int brush); + //wiki: llCollisionSound(string impact_sound, double impact_volume) + void llCollisionSound(string impact_sound, double impact_volume); + //wiki: llCollisionSprite(string impact_sprite) + void llCollisionSprite(string impact_sprite); + //wiki: string llGetAnimation(key id) + string llGetAnimation(string id); + //wiki: llResetScript() + void llResetScript(); + //wiki: llMessageLinked(integer linknum, integer num, string str, key id) + void llMessageLinked(int linknum, int num, string str, string id); + //wiki: llPushObject(key target, vector impulse, vector ang_impulse, integer local) + void llPushObject(string target, LSL_Types.Vector3 impulse, LSL_Types.Vector3 ang_impulse, int local); + //wiki: llPassCollisions(integer pass) + void llPassCollisions(int pass); + //wiki: string llGetScriptName() + string llGetScriptName(); + //wiki: integer llGetNumberOfSides() + LSL_Types.LSLInteger llGetNumberOfSides(); + //wiki: rotation llAxisAngle2Rot(vector axis, double angle) + LSL_Types.Quaternion llAxisAngle2Rot(LSL_Types.Vector3 axis, double angle); + //wiki: vector llRot2Axis(rotation rot) + LSL_Types.Vector3 llRot2Axis(LSL_Types.Quaternion rot); + //wiki: double llRot2Angle(rotation rot); + double llRot2Angle(LSL_Types.Quaternion rot); + //wiki: double llAcos(double val) + double llAcos(double val); + //wiki: double llAsin(double val) + double llAsin(double val); + //wiki: double llAngleBetween(rotation a, rotation b) + double llAngleBetween(LSL_Types.Quaternion a, LSL_Types.Quaternion b); + //wiki: string llGetInventoryKey(string name) + string llGetInventoryKey(string name); + //wiki: llAllowInventoryDrop(integer add) + void llAllowInventoryDrop(int add); + //wiki: vector llGetSunDirection() + LSL_Types.Vector3 llGetSunDirection(); + //wiki: vector llGetTextureOffset(integer face) + LSL_Types.Vector3 llGetTextureOffset(int face); + //wiki: vector llGetTextureScale(integer side) + LSL_Types.Vector3 llGetTextureScale(int side); + //wiki: double llGetTextureRot(integer side) + double llGetTextureRot(int side); + //wiki: integer llSubStringIndex(string source, string pattern) + LSL_Types.LSLInteger llSubStringIndex(string source, string pattern); + //wiki: key llGetOwnerKey(key id) + string llGetOwnerKey(string id); + //wiki: vector llGetCenterOfMass() + LSL_Types.Vector3 llGetCenterOfMass(); + //wiki: list llListSort(list src, integer stride, integer ascending) + LSL_Types.list llListSort(LSL_Types.list src, int stride, int ascending); + //integer llGetListLength(list src) + LSL_Types.LSLInteger llGetListLength(LSL_Types.list src); + //wiki: integer llList2Integer(list src, integer index) + LSL_Types.LSLInteger llList2Integer(LSL_Types.list src, int index); + //wiki: double llList2double(list src, integer index) + double llList2Float(LSL_Types.list src, int index); + //wiki: string llList2String(list src, integer index) + string llList2String(LSL_Types.list src, int index); + //wiki: key llList2Key(list src, integer index) + string llList2Key(LSL_Types.list src, int index); + //wiki: vector llList2Vector(list src, integer index) + LSL_Types.Vector3 llList2Vector(LSL_Types.list src, int index); + //wiki rotation llList2Rot(list src, integer index) + LSL_Types.Quaternion llList2Rot(LSL_Types.list src, int index); + //wiki: list llList2List(list src, integer start, integer end) + LSL_Types.list llList2List(LSL_Types.list src, int start, int end); + //wiki: llDeleteSubList(list src, integer start, integer end) + LSL_Types.list llDeleteSubList(LSL_Types.list src, int start, int end); + //wiki: integer llGetListEntryType(list src, integer index) + LSL_Types.LSLInteger llGetListEntryType(LSL_Types.list src, int index); + //wiki: string llList2CSV(list src) + string llList2CSV(LSL_Types.list src); + //wiki: list llCSV2List(string src) + LSL_Types.list llCSV2List(string src); + //wiki: list llListRandomize(list src, integer stride) + LSL_Types.list llListRandomize(LSL_Types.list src, int stride); + //wiki: list llList2ListStrided(list src, integer start, integer end, integer stride) + LSL_Types.list llList2ListStrided(LSL_Types.list src, int start, int end, int stride); + //wiki: vector llGetRegionCorner() + LSL_Types.Vector3 llGetRegionCorner(); + //wiki: list llListInsertList(list dest, list src, integer start) + LSL_Types.list llListInsertList(LSL_Types.list dest, LSL_Types.list src, int start); + //wiki: integer llListFindList(list src, list test) + LSL_Types.LSLInteger llListFindList(LSL_Types.list src, LSL_Types.list test); + //wiki: string llGetObjectName() + string llGetObjectName(); + //wiki: llSetObjectName(string name) + void llSetObjectName(string name); + //wiki: string llGetDate() + string llGetDate(); + //wiki: integer llEdgeOfWorld(vector pos, vector dir) + LSL_Types.LSLInteger llEdgeOfWorld(LSL_Types.Vector3 pos, LSL_Types.Vector3 dir); + //wiki: integer llGetAgentInfo(key id) + LSL_Types.LSLInteger llGetAgentInfo(string id); + //wiki: llAdjustSoundVolume(double volume) + void llAdjustSoundVolume(double volume); + //wiki: llSetSoundQueueing(integer queue) + void llSetSoundQueueing(int queue); + //wiki: llSetSoundRadius(double radius) + void llSetSoundRadius(double radius); + //wiki: string llKey2Name(key id) + string llKey2Name(string id); + //wiki: llSetTextureAnim(integer mode, integer face, integer sizex, integer sizey, double start, double length, double rate) + void llSetTextureAnim(int mode, int face, int sizex, int sizey, double start, double length, double rate); + //wiki: llTriggerSoundLimited(string sound, double volume, vector top_north_east, vector bottom_south_west) + void llTriggerSoundLimited(string sound, double volume, LSL_Types.Vector3 top_north_east, + LSL_Types.Vector3 bottom_south_west); + + //wiki: llEjectFromLand(key pest) + void llEjectFromLand(string pest); + LSL_Types.list llParseString2List(string str, LSL_Types.list separators, LSL_Types.list spacers); + //wiki: integer llOverMyLand(key id) + LSL_Types.LSLInteger llOverMyLand(string id); + //wiki: key llGetLandOwnerAt(vector pos) + string llGetLandOwnerAt(LSL_Types.Vector3 pos); + //wiki: key llGetNotecardLine(string name, integer line) + string llGetNotecardLine(string name, int line); + //wiki: vector llGetAgentSize(key id) + LSL_Types.Vector3 llGetAgentSize(string id); + //wiki: integer llSameGroup(key agent) + LSL_Types.LSLInteger llSameGroup(string agent); + //wiki: llUnSit(key id) + void llUnSit(string id); + //wiki: vector llGroundSlope(vector offset) + LSL_Types.Vector3 llGroundSlope(LSL_Types.Vector3 offset); + //wiki: vector llGroundNormal(vector offset) + LSL_Types.Vector3 llGroundNormal(LSL_Types.Vector3 offset); + //wiki: vector llGroundContour(vector offset) + LSL_Types.Vector3 llGroundContour(LSL_Types.Vector3 offset); + //wiki: integer llGetAttached() + LSL_Types.LSLInteger llGetAttached(); + //wiki: integer llGetFreeMemory() + LSL_Types.LSLInteger llGetFreeMemory(); + //wiki: string llGetRegionName() + string llGetRegionName(); + //wiki: double llGetRegionTimeDilation() + double llGetRegionTimeDilation(); + //wiki: double llGetRegionFPS() + double llGetRegionFPS(); + //wiki: llParticleSystem(List rules + void llParticleSystem(LSL_Types.list rules); + //wiki: llGroundRepel(double height, integer water, double tau) + void llGroundRepel(double height, int water, double tau); + //wiki: llGiveInventoryList(string destination, string category, LSL_Types.list inventory) + void llGiveInventoryList(string destination, string category, LSL_Types.list inventory); + //wiki: llSetVehicleType(integer type) + void llSetVehicleType(int type); + //wiki: llSetVehicledoubleParam(integer param, double value) + void llSetVehicledoubleParam(int param, double value); + // wiki: llSetVehicleFloatParam(integer param, float value) + void llSetVehicleFloatParam(int param, float value); + //wiki: llSetVehicleVectorParam(integer param, vector vec) + void llSetVehicleVectorParam(int param, LSL_Types.Vector3 vec); + //wiki: llSetVehicleRotationParam(integer param, rotation rot) + void llSetVehicleRotationParam(int param, LSL_Types.Quaternion rot); + //wiki: llSetVehicleFlags(integer flags) + void llSetVehicleFlags(int flags); + //wiki: llRemoveVehicleFlags(integer flags) + void llRemoveVehicleFlags(int flags); + //wiki: llSitTarget(vector offset, rotation rot) + void llSitTarget(LSL_Types.Vector3 offset, LSL_Types.Quaternion rot); + //wiki key llAvatarOnSitTarget() + string llAvatarOnSitTarget(); + //wiki: llAddToLandPassList(key avatar, double hours) + void llAddToLandPassList(string avatar, double hours); + //wiki: llSetTouchText(string text) + void llSetTouchText(string text); + //wiki: llSetSitText(string text) + void llSetSitText(string text); + //wiki: llSetCameraEyeOffset(vector offset) + void llSetCameraEyeOffset(LSL_Types.Vector3 offset); + //wiki: llSeteCameraAtOffset(vector offset) + void llSetCameraAtOffset(LSL_Types.Vector3 offset); + // + string llDumpList2String(LSL_Types.list src, string seperator); + //wiki: integer llScriptDanger(vector pos) + LSL_Types.LSLInteger llScriptDanger(LSL_Types.Vector3 pos); + //wiki: llDialog(key avatar, string message, list buttons, integer chat_channel) + void llDialog(string avatar, string message, LSL_Types.list buttons, int chat_channel); + //wiki: llVolumeDetect(integer detect) + void llVolumeDetect(int detect); + //wiki: llResetOtherScript(string name) + void llResetOtherScript(string name); + //wiki: integer llGetScriptState(string name) + LSL_Types.LSLInteger llGetScriptState(string name); + //wiki: (deprecated) + void llRemoteLoadScript(); + //wiki: llSetRemoteScriptAccessPin(integer pin) + void llSetRemoteScriptAccessPin(int pin); + //wiki: llRemoteLoadScriptPin(key target, string name, integer pin, integer running, integer start_param) + void llRemoteLoadScriptPin(string target, string name, int pin, int running, int start_param); + //wiki: llOpenRemoteDataChannel() + void llOpenRemoteDataChannel(); + //wiki: key llSendRemoteData(key channel, string dest, integer idata, string sdata) + string llSendRemoteData(string channel, string dest, int idata, string sdata); + //wiki: llRemoteDataReply(key channel, key message_id, string sdata, integer idata) + void llRemoteDataReply(string channel, string message_id, string sdata, int idata); + //wiki: llCloseRemoteDataChannel(key channel) + void llCloseRemoteDataChannel(string channel); + //wiki: string llMD5String(string src, integer nonce) + string llMD5String(string src, int nonce); + //wiki: llSetPrimitiveParams(list rules) + void llSetPrimitiveParams(LSL_Types.list rules); + //wiki: llSetLinkPrimitiveParams(integer linknumber, list rules) + void llSetLinkPrimitiveParams(int linknumber, LSL_Types.list rules); + //wiki: string llStringToBase64(string str) + string llStringToBase64(string str); + //wiki: string llBase64ToString(string str) + string llBase64ToString(string str); + //wiki: (deprecated) + void llXorBase64Strings(); + //wiki: llRemoteDataSetRegion() + void llRemoteDataSetRegion(); + //wiki: double llLog10(double val) + double llLog10(double val); + //wiki: double llLog(double val) + double llLog(double val); + //wiki: list llGetAnimationList(key id) + LSL_Types.list llGetAnimationList(string id); + //wiki: llSetParcelMusicURL(string url) + void llSetParcelMusicURL(string url); + //wiki: vector llGetRootPosition() + LSL_Types.Vector3 llGetRootPosition(); + //wiki: rotation llGetRootRotation() + LSL_Types.Quaternion llGetRootRotation(); + //wiki: string llGetObjectDesc() + string llGetObjectDesc(); + //wiki: llSetObjectDesc(string desc) + void llSetObjectDesc(string desc); + //wiki: key llGetCreator() + string llGetCreator(); + //wiki: string llGetTimestamp() + string llGetTimestamp(); + //wiki: llSetLinkAlpha(integer linknumber, double alpha, integer face) + void llSetLinkAlpha(int linknumber, double alpha, int face); + //wiki: integer llGetNumberOfPrims() + LSL_Types.LSLInteger llGetNumberOfPrims(); + //wiki: key llGetNumberOfNotecardLines(string name) + string llGetNumberOfNotecardLines(string name); + //wiki: list llGetBoundingBox(key object) + LSL_Types.list llGetBoundingBox(string obj); + //wiki: vector llGetGeometricCenter() + LSL_Types.Vector3 llGetGeometricCenter(); + //wiki: list llGetPrimitiveParams(list rules) + LSL_Types.list llGetPrimitiveParams(LSL_Types.list rules); + //wiki: string llIntegerToBase64(integer number) + string llIntegerToBase64(int number); + //wiki integer llBase64ToInteger(string str) + LSL_Types.LSLInteger llBase64ToInteger(string str); + //wiki: double llGetGMTclock() + double llGetGMTclock(); + //wiki: string llGetSimulatorHostname() + string llGetSimulatorHostname(); + //llSetLocalRot(rotation rot) + void llSetLocalRot(LSL_Types.Quaternion rot); + //wiki: list llParseStringKeepNulls(string src, list separators, list spacers) + LSL_Types.list llParseStringKeepNulls(string src, LSL_Types.list seperators, LSL_Types.list spacers); + //wiki: llRezAtRoot(string inventory, vector position, vector velocity, rotation rot, integer param) + void llRezAtRoot(string inventory, LSL_Types.Vector3 position, LSL_Types.Vector3 velocity, + LSL_Types.Quaternion rot, int param); + + //wiki: integer llGetObjectPermMask(integer mask) + LSL_Types.LSLInteger llGetObjectPermMask(int mask); + //wiki: llSetObjectPermMask(integer mask, integer value) + void llSetObjectPermMask(int mask, int value); + //wiki integer llGetInventoryPermMask(string item, integer mask) + LSL_Types.LSLInteger llGetInventoryPermMask(string item, int mask); + //wiki: llSetInventoryPermMask(string item, integer mask, integer value) + void llSetInventoryPermMask(string item, int mask, int value); + //wiki: key llGetInventoryCreator(string item) + string llGetInventoryCreator(string item); + //wiki: llOwnerSay(string msg) + void llOwnerSay(string msg); + //wiki: key llRequestSimulatorData(string simulator, integer data) + string llRequestSimulatorData(string simulator, int data); + //wiki: llForceMouselook(integer mouselook) + void llForceMouselook(int mouselook); + //wiki: double llGetObjectMass(key id) + double llGetObjectMass(string id); + LSL_Types.list llListReplaceList(LSL_Types.list dest, LSL_Types.list src, int start, int end); + //wiki: llLoadURL(key avatar_id, string message, string url) + void llLoadURL(string avatar_id, string message, string url); + //wiki: llParcelMediaCommandList(list commandList) + void llParcelMediaCommandList(LSL_Types.list commandList); + void llParcelMediaQuery(); + //wiki integer llModPow(integer a, integer b, integer c) + LSL_Types.LSLInteger llModPow(int a, int b, int c); + //wiki: integer llGetInventoryType(string name) + LSL_Types.LSLInteger llGetInventoryType(string name); + //wiki: llSetPayPrice(integer price, list quick_pay_buttons) + void llSetPayPrice(int price, LSL_Types.list quick_pay_buttons); + //wiki: vector llGetCameraPos() + LSL_Types.Vector3 llGetCameraPos(); + //wiki rotation llGetCameraRot() + LSL_Types.Quaternion llGetCameraRot(); + //wiki: (deprecated) + void llSetPrimURL(); + //wiki: (deprecated) + void llRefreshPrimURL(); + //wiki: string llEscapeURL(string url) + string llEscapeURL(string url); + //wiki: string llUnescapeURL(string url) + string llUnescapeURL(string url); + //wiki: llMapDestination(string simname, vector pos, vector look_at) + void llMapDestination(string simname, LSL_Types.Vector3 pos, LSL_Types.Vector3 look_at); + //wiki: llAddToLandBanList(key avatar, double hours) + void llAddToLandBanList(string avatar, double hours); + //wiki: llRemoveFromLandPassList(key avatar) + void llRemoveFromLandPassList(string avatar); + //wiki: llRemoveFromLandBanList(key avatar) + void llRemoveFromLandBanList(string avatar); + //wiki: llSetCameraParams(list rules) + void llSetCameraParams(LSL_Types.list rules); + //wiki: llClearCameraParams() + void llClearCameraParams(); + //wiki: double llListStatistics(integer operation, list src) + double llListStatistics(int operation, LSL_Types.list src); + //wiki: integer llGetUnixTime() + LSL_Types.LSLInteger llGetUnixTime(); + //wiki: integer llGetParcelFlags(vector pos) + LSL_Types.LSLInteger llGetParcelFlags(LSL_Types.Vector3 pos); + //wiki: integer llGetRegionFlags() + LSL_Types.LSLInteger llGetRegionFlags(); + //wiki: string llXorBase64StringsCorrect(string str1, string str2) + string llXorBase64StringsCorrect(string str1, string str2); + string llHTTPRequest(string url, LSL_Types.list parameters, string body); + //wiki: llResetLandBanList() + void llResetLandBanList(); + //wiki: llResetLandPassList() + void llResetLandPassList(); + //wiki: integer llGetParcelPrimCount(vector pos, integer category, integer sim_wide) + LSL_Types.LSLInteger llGetParcelPrimCount(LSL_Types.Vector3 pos, int category, int sim_wide); + //wiki: list llGetParcelPrimOwners(vector pos) + LSL_Types.list llGetParcelPrimOwners(LSL_Types.Vector3 pos); + //wiki: integer llGetObjectPrimCount(key object_id) + LSL_Types.LSLInteger llGetObjectPrimCount(string object_id); + //wiki: integer llGetParcelMaxPrims(vector pos, integer sim_wide) + LSL_Types.LSLInteger llGetParcelMaxPrims(LSL_Types.Vector3 pos, int sim_wide); + //wiki: llGetParcelDetails(vector pos, list params) + LSL_Types.list llGetParcelDetails(LSL_Types.Vector3 pos, LSL_Types.list param); + //wiki: llSetLinkTexture(integer linknumber, string texture, integer face) + void llSetLinkTexture(int linknumber, string texture, int face); + //wiki: string llStringTrim(string src, int type) + string llStringTrim(string src, int type); + //wiki: LSL_Types.list llGetObjectDetails(string id, LSL_Types.list args) + LSL_Types.list llGetObjectDetails(string id, LSL_Types.list args); + } +} diff --git a/OpenSim/Region/ScriptEngine/XEngine/Script/IOSSL_ScriptCommands.cs b/OpenSim/Region/ScriptEngine/XEngine/Script/IOSSL_ScriptCommands.cs new file mode 100644 index 0000000..82d4673 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/XEngine/Script/IOSSL_ScriptCommands.cs @@ -0,0 +1,68 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +namespace OpenSim.Region.ScriptEngine.XEngine.Script +{ + public interface IOSSL_ScriptCommands + { + //OpenSim functions + string osSetDynamicTextureURL(string dynamicID, string contentType, string url, string extraParams, int timer); + string osSetDynamicTextureURLBlend(string dynamicID, string contentType, string url, string extraParams, + int timer, int alpha); + string osSetDynamicTextureData(string dynamicID, string contentType, string data, string extraParams, int timer); + string osSetDynamicTextureDataBlend(string dynamicID, string contentType, string data, string extraParams, + int timer, int alpha); + double osTerrainGetHeight(int x, int y); + int osTerrainSetHeight(int x, int y, double val); + int osRegionRestart(double seconds); + void osRegionNotice(string msg); + bool osConsoleCommand(string Command); + void osSetParcelMediaURL(string url); + void osSetPrimFloatOnWater(int floatYN); + + // Animation commands + void osAvatarPlayAnimation(string avatar, string animation); + void osAvatarStopAnimation(string avatar, string animation); + + //texture draw functions + string osMovePen(string drawList, int x, int y); + string osDrawLine(string drawList, int startX, int startY, int endX, int endY); + string osDrawLine(string drawList, int endX, int endY); + string osDrawText(string drawList, string text); + string osDrawEllipse(string drawList, int width, int height); + string osDrawRectangle(string drawList, int width, int height); + string osDrawFilledRectangle(string drawList, int width, int height); + string osSetFontSize(string drawList, int fontSize); + string osSetPenSize(string drawList, int penSize); + string osSetPenColour(string drawList, string colour); + string osDrawImage(string drawList, int width, int height, string imageUrl); + void osSetStateEvents(int events); + + double osList2Double(LSL_Types.list src, int index); + void osSetRegionWaterHeight(double height); + } +} diff --git a/OpenSim/Region/ScriptEngine/XEngine/Script/IScript.cs b/OpenSim/Region/ScriptEngine/XEngine/Script/IScript.cs new file mode 100644 index 0000000..e5d0b33 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/XEngine/Script/IScript.cs @@ -0,0 +1,46 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System.Reflection; +using System; +using System.Collections; +using System.Collections.Generic; +using OpenSim.Region.Environment.Interfaces; + +namespace OpenSim.Region.ScriptEngine.XEngine.Script +{ + public interface IScript + { + Type Start(ILSL_ScriptCommands lsl, IOSSL_ScriptCommands ossl); + + Dictionary GetVars(); + void SetVars(Dictionary vars); + void ResetVars(); + + string State { get; set; } + } +} diff --git a/OpenSim/Region/ScriptEngine/XEngine/Script/LSL_Types.cs b/OpenSim/Region/ScriptEngine/XEngine/Script/LSL_Types.cs new file mode 100644 index 0000000..2d5d2b8 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/XEngine/Script/LSL_Types.cs @@ -0,0 +1,1411 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Text.RegularExpressions; + +namespace OpenSim.Region.ScriptEngine.XEngine.Script +{ + [Serializable] + public partial class LSL_Types + { + // Types are kept is separate .dll to avoid having to add whatever .dll it is in it to script AppDomain + + [Serializable] + public struct Vector3 + { + public double x; + public double y; + public double z; + + #region Constructors + + public Vector3(Vector3 vector) + { + x = (float)vector.x; + y = (float)vector.y; + z = (float)vector.z; + } + + public Vector3(double X, double Y, double Z) + { + x = X; + y = Y; + z = Z; + } + + public Vector3(string str) + { + str = str.Replace('<', ' '); + str = str.Replace('>', ' '); + string[] tmps = str.Split(new Char[] { ',', '<', '>' }); + if (tmps.Length < 3) + { + x=y=z=0; + return; + } + bool res; + res = Double.TryParse(tmps[0], out x); + res = res & Double.TryParse(tmps[1], out y); + res = res & Double.TryParse(tmps[2], out z); + } + + #endregion + + #region Overriders + + public override string ToString() + { + string s=String.Format("<{0:0.000000},{1:0.000000},{2:0.000000}>", x, y, z); + return s; + } + + public static explicit operator LSLString(Vector3 vec) + { + string s=String.Format("<{0:0.000000},{1:0.000000},{2:0.000000}>", vec.x, vec.y, vec.z); + return new LSLString(s); + } + + public static explicit operator string(Vector3 vec) + { + string s=String.Format("<{0:0.000000},{1:0.000000},{2:0.000000}>", vec.x, vec.y, vec.z); + return s; + } + + public static explicit operator Vector3(string s) + { + return new Vector3(s); + } + + public static bool operator ==(Vector3 lhs, Vector3 rhs) + { + return (lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z); + } + + public static bool operator !=(Vector3 lhs, Vector3 rhs) + { + return !(lhs == rhs); + } + + public override int GetHashCode() + { + return (x.GetHashCode() ^ y.GetHashCode() ^ z.GetHashCode()); + } + + public override bool Equals(object o) + { + if (!(o is Vector3)) return false; + + Vector3 vector = (Vector3)o; + + return (x == vector.x && x == vector.x && z == vector.z); + } + + #endregion + + #region Vector & Vector Math + + // Vector-Vector Math + public static Vector3 operator +(Vector3 lhs, Vector3 rhs) + { + return new Vector3(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z); + } + + public static Vector3 operator -(Vector3 lhs, Vector3 rhs) + { + return new Vector3(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z); + } + + public static Vector3 operator *(Vector3 lhs, Vector3 rhs) + { + return new Vector3(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z); + } + + public static Vector3 operator %(Vector3 v1, Vector3 v2) + { + //Cross product + Vector3 tv; + tv.x = (v1.y * v2.z) - (v1.z * v2.y); + tv.y = (v1.z * v2.x) - (v1.x * v2.z); + tv.z = (v1.x * v2.y) - (v1.y * v2.x); + return tv; + } + + #endregion + + #region Vector & Float Math + + // Vector-Float and Float-Vector Math + public static Vector3 operator *(Vector3 vec, float val) + { + return new Vector3(vec.x * val, vec.y * val, vec.z * val); + } + + public static Vector3 operator *(float val, Vector3 vec) + { + return new Vector3(vec.x * val, vec.y * val, vec.z * val); + } + + public static Vector3 operator /(Vector3 v, float f) + { + v.x = v.x / f; + v.y = v.y / f; + v.z = v.z / f; + return v; + } + + #endregion + + #region Vector & Double Math + + public static Vector3 operator *(Vector3 vec, double val) + { + return new Vector3(vec.x * val, vec.y * val, vec.z * val); + } + + public static Vector3 operator *(double val, Vector3 vec) + { + return new Vector3(vec.x * val, vec.y * val, vec.z * val); + } + + public static Vector3 operator /(Vector3 v, double f) + { + v.x = v.x / f; + v.y = v.y / f; + v.z = v.z / f; + return v; + } + + #endregion + + #region Vector & Rotation Math + + // Vector-Rotation Math + public static Vector3 operator *(Vector3 v, Quaternion r) + { + Quaternion vq = new Quaternion(v.x, v.y, v.z, 0); + Quaternion nq = new Quaternion(-r.x, -r.y, -r.z, r.s); + + // adapted for operator * computing "b * a" + Quaternion result = nq * (vq * r); + + return new Vector3(result.x, result.y, result.z); + } + + public static Vector3 operator /(Vector3 v, Quaternion r) + { + r.s = -r.s; + return v * r; + } + + #endregion + + #region Static Helper Functions + + public static double Dot(Vector3 v1, Vector3 v2) + { + return (v1.x * v2.x) + (v1.y * v2.y) + (v1.z * v2.z); + } + + public static Vector3 Cross(Vector3 v1, Vector3 v2) + { + return new Vector3 + ( + v1.y * v2.z - v1.z * v2.y, + v1.z * v2.x - v1.x * v2.z, + v1.x * v2.y - v1.y * v2.x + ); + } + + public static double Mag(Vector3 v) + { + return Math.Sqrt(v.x * v.x + v.y * v.y + v.z * v.z); + } + + public static Vector3 Norm(Vector3 vector) + { + double mag = Mag(vector); + return new Vector3(vector.x / mag, vector.y / mag, vector.z / mag); + } + + #endregion + } + + [Serializable] + public struct Quaternion + { + public double x; + public double y; + public double z; + public double s; + + #region Constructors + + public Quaternion(Quaternion Quat) + { + x = (float)Quat.x; + y = (float)Quat.y; + z = (float)Quat.z; + s = (float)Quat.s; + if (x == 0 && y == 0 && z == 0 && s == 0) + s = 1; + } + + public Quaternion(double X, double Y, double Z, double S) + { + x = X; + y = Y; + z = Z; + s = S; + if (x == 0 && y == 0 && z == 0 && s == 0) + s = 1; + } + + public Quaternion(string str) + { + str = str.Replace('<', ' '); + str = str.Replace('>', ' '); + string[] tmps = str.Split(new Char[] { ',', '<', '>' }); + if (tmps.Length < 4) + { + x=y=z=s=0; + return; + } + bool res; + res = Double.TryParse(tmps[0], out x); + res = res & Double.TryParse(tmps[1], out y); + res = res & Double.TryParse(tmps[2], out z); + res = res & Double.TryParse(tmps[3], out s); + if (x == 0 && y == 0 && z == 0 && s == 0) + s = 1; + } + + #endregion + + #region Overriders + + public override int GetHashCode() + { + return (x.GetHashCode() ^ y.GetHashCode() ^ z.GetHashCode() ^ s.GetHashCode()); + } + + public override bool Equals(object o) + { + if (!(o is Quaternion)) return false; + + Quaternion quaternion = (Quaternion)o; + + return x == quaternion.x && y == quaternion.y && z == quaternion.z && s == quaternion.s; + } + + public override string ToString() + { + string st=String.Format("<{0:0.000000},{1:0.000000},{2:0.000000},{3:0.000000}>", x, y, z, s); + return st; + } + + public static explicit operator string(Quaternion r) + { + string s=String.Format("<{0:0.000000},{1:0.000000},{2:0.000000},{3:0.000000}>", r.x, r.y, r.z, r.s); + return s; + } + + public static explicit operator LSLString(Quaternion r) + { + string s=String.Format("<{0:0.000000},{1:0.000000},{2:0.000000},{3:0.000000}>", r.x, r.y, r.z, r.s); + return new LSLString(s); + } + + public static explicit operator Quaternion(string s) + { + return new Quaternion(s); + } + + public static bool operator ==(Quaternion lhs, Quaternion rhs) + { + // Return true if the fields match: + return lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z && lhs.s == rhs.s; + } + + public static bool operator !=(Quaternion lhs, Quaternion rhs) + { + return !(lhs == rhs); + } + + #endregion + + public static Quaternion operator +(Quaternion a, Quaternion b) + { + return new Quaternion(a.x + b.x, a.y + b.y, a.z + b.z, a.s + b.s); + } + + public static Quaternion operator /(Quaternion a, Quaternion b) + { + b.s = -b.s; + return a * b; + } + + public static Quaternion operator -(Quaternion a, Quaternion b) + { + return new Quaternion(a.x - b.x, a.y - b.y, a.z - b.z, a.s - b.s); + } + + // using the equations below, we need to do "b * a" to be compatible with LSL + public static Quaternion operator *(Quaternion b, Quaternion a) + { + Quaternion c; + c.x = a.s * b.x + a.x * b.s + a.y * b.z - a.z * b.y; + c.y = a.s * b.y + a.y * b.s + a.z * b.x - a.x * b.z; + c.z = a.s * b.z + a.z * b.s + a.x * b.y - a.y * b.x; + c.s = a.s * b.s - a.x * b.x - a.y * b.y - a.z * b.z; + return c; + } + } + + [Serializable] + public class list + { + private object[] m_data; + + public list(params object[] args) + { + m_data = new object[args.Length]; + m_data = args; + } + + public int Length + { + get { + if (m_data == null) + m_data=new Object[0]; + return m_data.Length; + } + } + + public object[] Data + { + get { + if (m_data == null) + m_data=new Object[0]; + return m_data; + } + } + + public static list operator +(list a, list b) + { + object[] tmp; + tmp = new object[a.Length + b.Length]; + a.Data.CopyTo(tmp, 0); + b.Data.CopyTo(tmp, a.Length); + return new list(tmp); + } + + public void Add(object o) + { + object[] tmp; + tmp = new object[m_data.Length + 1]; + m_data.CopyTo(tmp, 0); + tmp[m_data.Length] = o; + m_data = tmp; + } + + public bool Contains(object o) + { + bool ret = false; + foreach (object i in Data) + { + if (i == o) + { + ret = true; + break; + } + } + return ret; + } + + public list DeleteSublist(int start, int end) + { + // Not an easy one + // If start <= end, remove that part + // if either is negative, count from the end of the array + // if the resulting start > end, remove all BUT that part + + Object[] ret; + + if (start < 0) + start=m_data.Length-start; + + if (start < 0) + start=0; + + if (end < 0) + end=m_data.Length-end; + if (end < 0) + end=0; + + if (start > end) + { + if (end >= m_data.Length) + return new list(new Object[0]); + + if (start >= m_data.Length) + start=m_data.Length-1; + + return GetSublist(end, start); + } + + // start >= 0 && end >= 0 here + if (start >= m_data.Length) + { + ret=new Object[m_data.Length]; + Array.Copy(m_data, 0, ret, 0, m_data.Length); + + return new list(ret); + } + + if (end >= m_data.Length) + end=m_data.Length-1; + + // now, this makes the math easier + int remove=end+1-start; + + ret=new Object[m_data.Length-remove]; + if (ret.Length == 0) + return new list(ret); + + int src; + int dest=0; + + for (src = 0; src < m_data.Length; src++) + { + if (src < start || src > end) + ret[dest++]=m_data[src]; + } + + return new list(ret); + } + + public list GetSublist(int start, int end) + { + + object[] ret; + + // Take care of neg start or end's + // NOTE that either index may still be negative after + // adding the length, so we must take additional + // measures to protect against this. Note also that + // after normalisation the negative indices are no + // longer relative to the end of the list. + + if (start < 0) + { + start = m_data.Length + start; + } + + if (end < 0) + { + end = m_data.Length + end; + } + + // The conventional case is start <= end + // NOTE that the case of an empty list is + // dealt with by the initial test. Start + // less than end is taken to be the most + // common case. + + if (start <= end) + { + + // Start sublist beyond length + // Also deals with start AND end still negative + if (start >= m_data.Length || end < 0) + { + return new list(); + } + + // Sublist extends beyond the end of the supplied list + if (end >= m_data.Length) + { + end = m_data.Length - 1; + } + + // Sublist still starts before the beginning of the list + if (start < 0) + { + start = 0; + } + + ret = new object[end - start + 1]; + + Array.Copy(m_data, start, ret, 0, end - start + 1); + + return new list(ret); + + } + + // Deal with the segmented case: 0->end + start->EOL + + else + { + + list result = null; + + // If end is negative, then prefix list is empty + if (end < 0) + { + result = new list(); + // If start is still negative, then the whole of + // the existing list is returned. This case is + // only admitted if end is also still negative. + if (start < 0) + { + return this; + } + + } + else + { + result = GetSublist(0,end); + } + + // If start is outside of list, then just return + // the prefix, whatever it is. + if (start >= m_data.Length) + { + return result; + } + + return result + GetSublist(start, Data.Length); + + } + } + + public list Sort(int stride, int ascending) + { + if (Data.Length == 0) + return new list(); // Don't even bother + + string[] keys; + + if (stride == 1) // The simple case + { + Object[] ret=new Object[Data.Length]; + + Array.Copy(Data, 0, ret, 0, Data.Length); + + keys=new string[Data.Length]; + + for (int k = 0; k < Data.Length; k++) + keys[k] = Data[k].ToString(); + + Array.Sort(keys, ret); + + if (ascending == 0) + Array.Reverse(ret); + return new list(ret); + } + + int src=0; + + int len=(Data.Length+stride-1)/stride; + + keys=new string[len]; + Object[][] vals=new Object[len][]; + + int i; + + while (src < Data.Length) + { + Object[] o=new Object[stride]; + + for (i = 0; i < stride; i++) + { + if (src < Data.Length) + o[i]=Data[src++]; + else + { + o[i]=new Object(); + src++; + } + } + + int idx=src/stride-1; + keys[idx]=o[0].ToString(); + vals[idx]=o; + } + + Array.Sort(keys, vals); + if (ascending == 0) + { + Array.Reverse(vals); + } + + Object[] sorted=new Object[stride*vals.Length]; + + for (i = 0; i < vals.Length; i++) + for (int j = 0; j < stride; j++) + sorted[i*stride+j] = vals[i][j]; + + return new list(sorted); + } + + #region CSV Methods + + public static list FromCSV(string csv) + { + return new list(csv.Split(',')); + } + + public string ToCSV() + { + string ret = ""; + foreach (object o in this.Data) + { + if (ret == "") + { + ret = o.ToString(); + } + else + { + ret = ret + ", " + o.ToString(); + } + } + return ret; + } + + private string ToSoup() + { + string output; + output = String.Empty; + if (m_data.Length == 0) + { + return String.Empty; + } + foreach (object o in m_data) + { + output = output + o.ToString(); + } + return output; + } + + public static explicit operator String(list l) + { + return l.ToSoup(); + } + + public static explicit operator LSLString(list l) + { + return new LSLString(l.ToSoup()); + } + + public override string ToString() + { + return ToSoup(); + } + + #endregion + + #region Statistic Methods + + public double Min() + { + double minimum = double.PositiveInfinity; + double entry; + for (int i = 0; i < Data.Length; i++) + { + if (double.TryParse(Data[i].ToString(), out entry)) + { + if (entry < minimum) minimum = entry; + } + } + return minimum; + } + + public double Max() + { + double maximum = double.NegativeInfinity; + double entry; + for (int i = 0; i < Data.Length; i++) + { + if (double.TryParse(Data[i].ToString(), out entry)) + { + if (entry > maximum) maximum = entry; + } + } + return maximum; + } + + public double Range() + { + return (this.Max() / this.Min()); + } + + public int NumericLength() + { + int count = 0; + double entry; + for (int i = 0; i < Data.Length; i++) + { + if (double.TryParse(Data[i].ToString(), out entry)) + { + count++; + } + } + return count; + } + + public static list ToDoubleList(list src) + { + list ret = new list(); + double entry; + for (int i = 0; i < src.Data.Length - 1; i++) + { + if (double.TryParse(src.Data[i].ToString(), out entry)) + { + ret.Add(entry); + } + } + return ret; + } + + public double Sum() + { + double sum = 0; + double entry; + for (int i = 0; i < Data.Length; i++) + { + if (double.TryParse(Data[i].ToString(), out entry)) + { + sum = sum + entry; + } + } + return sum; + } + + public double SumSqrs() + { + double sum = 0; + double entry; + for (int i = 0; i < Data.Length; i++) + { + if (double.TryParse(Data[i].ToString(), out entry)) + { + sum = sum + Math.Pow(entry, 2); + } + } + return sum; + } + + public double Mean() + { + return (this.Sum() / this.NumericLength()); + } + + public void NumericSort() + { + IComparer Numeric = new NumericComparer(); + Array.Sort(Data, Numeric); + } + + public void AlphaSort() + { + IComparer Alpha = new AlphaCompare(); + Array.Sort(Data, Alpha); + } + + public double Median() + { + return Qi(0.5); + } + + public double GeometricMean() + { + double ret = 1.0; + list nums = ToDoubleList(this); + for (int i = 0; i < nums.Data.Length; i++) + { + ret *= (double)nums.Data[i]; + } + return Math.Exp(Math.Log(ret) / (double)nums.Data.Length); + } + + public double HarmonicMean() + { + double ret = 0.0; + list nums = ToDoubleList(this); + for (int i = 0; i < nums.Data.Length; i++) + { + ret += 1.0 / (double)nums.Data[i]; + } + return ((double)nums.Data.Length / ret); + } + + public double Variance() + { + double s = 0; + list num = ToDoubleList(this); + for (int i = 0; i < num.Data.Length; i++) + { + s += Math.Pow((double)num.Data[i], 2); + } + return (s - num.Data.Length * Math.Pow(num.Mean(), 2)) / (num.Data.Length - 1); + } + + public double StdDev() + { + return Math.Sqrt(this.Variance()); + } + + public double Qi(double i) + { + list j = this; + j.NumericSort(); + + if (Math.Ceiling(this.Length * i) == this.Length * i) + { + return (double)((double)j.Data[(int)(this.Length * i - 1)] + (double)j.Data[(int)(this.Length * i)]) / 2; + } + else + { + return (double)j.Data[((int)(Math.Ceiling(this.Length * i))) - 1]; + } + } + + #endregion + + public string ToPrettyString() + { + string output; + if (m_data.Length == 0) + { + return "[]"; + } + output = "["; + foreach (object o in m_data) + { + if (o is String) + { + output = output + "\"" + o + "\", "; + } + else + { + output = output + o.ToString() + ", "; + } + } + output = output.Substring(0, output.Length - 2); + output = output + "]"; + return output; + } + + public class AlphaCompare : IComparer + { + int IComparer.Compare(object x, object y) + { + return string.Compare(x.ToString(), y.ToString()); + } + } + + public class NumericComparer : IComparer + { + int IComparer.Compare(object x, object y) + { + double a; + double b; + if (!double.TryParse(x.ToString(), out a)) + { + a = 0.0; + } + if (!double.TryParse(y.ToString(), out b)) + { + b = 0.0; + } + if (a < b) + { + return -1; + } + else if (a == b) + { + return 0; + } + else + { + return 1; + } + } + } + + } + + // + // BELOW IS WORK IN PROGRESS... IT WILL CHANGE, SO DON'T USE YET! :) + // + + public struct StringTest + { + // Our own little string + internal string actualString; + public static implicit operator bool(StringTest mString) + { + if (mString.actualString.Length == 0) + return true; + return false; + } + public override string ToString() + { + return actualString; + } + + } + + [Serializable] + public struct key + { + public string value; + + #region Constructors + public key(string s) + { + value = s; + } + + #endregion + + #region Methods + + static public bool Parse2Key(string s) + { + Regex isuuid = new Regex(@"^[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}$", RegexOptions.Compiled); + if (isuuid.IsMatch(s)) + { + return true; + } + else + { + return false; + } + } + + #endregion + + #region Operators + + static public implicit operator Boolean(key k) + { + if (k.value.Length == 0) + { + return false; + } + + if (k.value == "00000000-0000-0000-0000-000000000000") + { + return false; + } + Regex isuuid = new Regex(@"^[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}$", RegexOptions.Compiled); + if (isuuid.IsMatch(k.value)) + { + return true; + } + else + { + return false; + } + } + + static public implicit operator key(string s) + { + return new key(s); + } + + static public implicit operator String(key k) + { + return k.value; + } + + public static bool operator ==(key k1, key k2) + { + return k1.value == k2.value; + } + public static bool operator !=(key k1, key k2) + { + return k1.value != k2.value; + } + + #endregion + + #region Overriders + + public override bool Equals(object o) + { + return o.ToString() == value; + } + + public override int GetHashCode() + { + return value.GetHashCode(); + } + + #endregion + } + + [Serializable] + public struct LSLString + { + public string m_string; + #region Constructors + public LSLString(string s) + { + m_string = s; + } + + public LSLString(int i) + { + m_string=i.ToString(); + } + + public LSLString(double d) + { + string s=String.Format("{0:0.000000}", d); + m_string=s; + } + + #endregion + + #region Operators + static public implicit operator Boolean(LSLString s) + { + if (s.m_string.Length == 0) + { + return false; + } + else + { + return true; + } + } + + + + static public implicit operator String(LSLString s) + { + return s.m_string; + } + + static public implicit operator LSLString(string s) + { + return new LSLString(s); + } + + public static string ToString(LSLString s) + { + return s.m_string; + } + + public override string ToString() + { + return m_string; + } + + public static bool operator ==(LSLString s1, string s2) + { + return s1.m_string == s2; + } + + public static bool operator !=(LSLString s1, string s2) + { + return s1.m_string != s2; + } + + public static explicit operator double(LSLString s) + { + return Convert.ToDouble(s.m_string); + } + + public static explicit operator LSLInteger(LSLString s) + { + return new LSLInteger(Convert.ToInt32(s.m_string)); + } + + public static explicit operator LSLString(int i) + { + return new LSLString(i); + } + + public static explicit operator LSLString(double d) + { + return new LSLString(d); + } + + public static implicit operator Vector3(LSLString s) + { + return new Vector3(s.m_string); + } + + #endregion + + #region Overriders + public override bool Equals(object o) + { + return m_string == o.ToString(); + } + + public override int GetHashCode() + { + return m_string.GetHashCode(); + } + + #endregion + + #region " Standard string functions " + //Clone,CompareTo,Contains + //CopyTo,EndsWith,Equals,GetEnumerator,GetHashCode,GetType,GetTypeCode + //IndexOf,IndexOfAny,Insert,IsNormalized,LastIndexOf,LastIndexOfAny + //Length,Normalize,PadLeft,PadRight,Remove,Replace,Split,StartsWith,Substring,ToCharArray,ToLowerInvariant + //ToString,ToUpper,ToUpperInvariant,Trim,TrimEnd,TrimStart + public bool Contains(string value) { return m_string.Contains(value); } + public int IndexOf(string value) { return m_string.IndexOf(value); } + public int Length { get { return m_string.Length; } } + + + #endregion + } + + [Serializable] + public struct LSLInteger + { + public int value; + + #region Constructors + public LSLInteger(int i) + { + value = i; + } + + public LSLInteger(double d) + { + value = (int)d; + } + + public LSLInteger(Object o) + { + if(!(o is Int32)) + value=0; + else + value = (int)o; + } + + public LSLInteger(string s) + { + value = int.Parse(s); + } + + #endregion + + static public implicit operator int(LSLInteger i) + { + return i.value; + } + + static public implicit operator uint(LSLInteger i) + { + return (uint)i.value; + } + + static public explicit operator LSLString(LSLInteger i) + { + return new LSLString(i.ToString()); + } + + static public explicit operator string(LSLInteger i) + { + return i.ToString(); + } + + static public implicit operator Boolean(LSLInteger i) + { + if (i.value == 0) + { + return false; + } + else + { + return true; + } + } + + static public implicit operator LSLInteger(int i) + { + return new LSLInteger(i); + } + + static public explicit operator LSLInteger(string s) + { + return new LSLInteger(int.Parse(s)); + } + + static public implicit operator LSLInteger(double d) + { + return new LSLInteger(d); + } + + static public bool operator ==(LSLInteger i1, LSLInteger i2) + { + bool ret = i1.value == i2.value; + return ret; + } + + static public bool operator !=(LSLInteger i1, LSLInteger i2) + { + bool ret = i1.value != i2.value; + return ret; + } + + static public LSLInteger operator &(LSLInteger i1, LSLInteger i2) + { + int ret = i1.value & i2.value; + return ret; + } + + public static LSLInteger operator ++(LSLInteger i) + { + i.value++; + return i; + } + + + public static LSLInteger operator --(LSLInteger i) + { + i.value--; + return i; + } + + static public implicit operator System.Double(LSLInteger i) + { + return (double)i.value; + } + + public static bool operator true(LSLInteger i) + { + return i.value != 0; + } + + public static bool operator false(LSLInteger i) + { + return i.value == 0; + } + + #region Overriders + + public override string ToString() + { + return this.value.ToString(); + } + + public override bool Equals(object o) + { + if(o is Int32) + { + return value == (Int32)o; + } + if(o is LSLInteger) + { + return value == ((LSLInteger)o).value; + } + return false; + } + + public override int GetHashCode() + { + return value.GetHashCode(); + } + + #endregion + } + + [Serializable] + public struct LSLFloat + { + public double value; + + #region Constructors + public LSLFloat(int i) + { + this.value = (double)i; + } + + public LSLFloat(double d) + { + this.value = d; + } + + #endregion + + #region Operators + + static public implicit operator Double(LSLFloat f) + { + return f.value; + } + + //static public implicit operator System.Int32(LSLFloat f) + //{ + // return (int)f.value; + //} + + + static public implicit operator Boolean(LSLFloat f) + { + if (f.value == 0) + { + return false; + } + else + { + return true; + } + } + + static public implicit operator LSLFloat(int i) + { + return new LSLFloat(i); + } + + static public implicit operator LSLFloat(double d) + { + return new LSLFloat(d); + } + #endregion + + #region Overriders + public override string ToString() + { + return this.value.ToString(); + } + #endregion + } + } +} diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs new file mode 100644 index 0000000..3ca03b2 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -0,0 +1,1435 @@ +using System; +using System.IO; +using System.Threading; +using System.Collections; +using System.Collections.Generic; +using System.Security.Policy; +using System.Reflection; +using System.Xml; +using libsecondlife; +using log4net; +using Nini.Config; +using Amib.Threading; +using OpenSim.Framework; +using OpenSim.Region.Environment; +using OpenSim.Region.Environment.Scenes; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.ScriptEngine.XEngine.Script; + +namespace OpenSim.Region.ScriptEngine.XEngine +{ + public class XEngine : IRegionModule + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private SmartThreadPool m_ThreadPool; + private int m_MaxScriptQueue; + private Scene m_Scene; + private IConfig m_ScriptConfig; + private Compiler m_Compiler; + private EventManager m_EventManager; + private int m_EventLimit; + private bool m_KillTimedOutScripts; + + private static List m_ScriptEngines = + new List(); + public AsyncCommandManager m_ASYNCLSLCommandManager; + + // Maps the local id to the script inventory items in it + + private Dictionary > m_PrimObjects = + new Dictionary >(); + + // Maps the LLUUID above to the script instance + + private Dictionary m_Scripts = + new Dictionary(); + + // Maps the asset ID to the assembly + + private Dictionary m_Assemblies = + new Dictionary(); + + // This will list AppDomains by script asset + + private Dictionary m_AppDomains = + new Dictionary(); + + // List the scripts running in each appdomain + + private Dictionary > m_DomainScripts = + new Dictionary >(); + + public string ScriptEngineName + { + get { return "XEngine"; } + } + + public Scene World + { + get { return m_Scene; } + } + + public ILog Log + { + get { return m_log; } + } + + public static List ScriptEngines + { + get { return m_ScriptEngines; } + } + + private struct RezScriptParms + { + uint LocalID; + LLUUID ItemID; + string Script; + } + + public IConfig ScriptConfigSource + { + get { return m_ScriptConfig; } + } + + // + // IRegionModule functions + // + public void Initialise(Scene scene, IConfigSource configSource) + { + AppDomain.CurrentDomain.AssemblyResolve += + OnAssemblyResolve; + + m_log.InfoFormat("[XEngine] Initializing scripts in region {0}", + scene.RegionInfo.RegionName); + m_Scene=scene; + + m_ScriptConfig = configSource.Configs["XEngine"]; + + if(m_ScriptConfig == null) + { + m_log.ErrorFormat("[XEngine] No script configuration found. Scripts disabled"); + return; + } + + int minThreads = m_ScriptConfig.GetInt("MinThreads", 2); + int maxThreads = m_ScriptConfig.GetInt("MaxThreads", 2); + int idleTimeout = m_ScriptConfig.GetInt("IdleTimeout", 60); + string priority = m_ScriptConfig.GetString("Priority", "BelowNormal"); + int maxScriptQueue = m_ScriptConfig.GetInt("MaxScriptEventQueue",300); + int stackSize = m_ScriptConfig.GetInt("ThreadStackSize", 262144); + int sleepTime = m_ScriptConfig.GetInt("MaintenanceInterval", + 10)*1000; + m_EventLimit = m_ScriptConfig.GetInt("EventLimit", 30); + m_KillTimedOutScripts = m_ScriptConfig.GetBoolean( + "KillTimedOutScripts", false); + int saveTime = m_ScriptConfig.GetInt("SaveInterval", 300)*1000; + + ThreadPriority prio = ThreadPriority.BelowNormal; + switch(priority) + { + case "Lowest": + prio=ThreadPriority.Lowest; + break; + case "BelowNormal": + prio=ThreadPriority.BelowNormal; + break; + case "Normal": + prio=ThreadPriority.Normal; + break; + case "AboveNormal": + prio=ThreadPriority.AboveNormal; + break; + case "Highest": + prio=ThreadPriority.Highest; + break; + default: + m_log.ErrorFormat("[XEngine] Invalid thread priority: '"+ + priority+"'. Assuming BelowNormal"); + break; + } + + lock(m_ScriptEngines) + { + m_ScriptEngines.Add(this); + } + + m_EventManager = new EventManager(this); + m_ASYNCLSLCommandManager = new AsyncCommandManager(this); + + StartEngine(minThreads, maxThreads, idleTimeout, prio, + maxScriptQueue, stackSize); + + m_Compiler = new Compiler(this); + + m_Scene.EventManager.OnRezScript += OnRezScript; + m_Scene.EventManager.OnRemoveScript += OnRemoveScript; + m_Scene.EventManager.OnScriptReset += OnScriptReset; + + if(sleepTime > 0) + { + m_ThreadPool.QueueWorkItem(new WorkItemCallback( + this.DoMaintenance), new Object[] + { sleepTime }); + } + + if(saveTime > 0) + { + m_ThreadPool.QueueWorkItem(new WorkItemCallback( + this.DoBackup), new Object[] { saveTime }); + } + } + + public void PostInitialise() + { + m_ThreadPool.Start(); + } + + public void Close() + { + lock(m_ScriptEngines) + { + if(m_ScriptEngines.Contains(this)) + m_ScriptEngines.Remove(this); + } + } + + public object DoBackup(object o) + { + Object[] p = (Object[])o; + int saveTime = (int)p[0]; + + System.Threading.Thread.Sleep(saveTime); + +// m_log.Debug("[XEngine] Backing up script states"); + + List instances = new List(); + + lock(m_Scripts) + { + foreach (XScriptInstance instance in m_Scripts.Values) + instances.Add(instance); + } + + foreach (XScriptInstance i in instances) + { + string assembly = String.Empty; + + lock(m_Scripts) + { + if(!m_Assemblies.ContainsKey(i.AssetID)) + continue; + assembly = m_Assemblies[i.AssetID]; + } + + i.SaveState(assembly); + } + + instances.Clear(); + + m_ThreadPool.QueueWorkItem(new WorkItemCallback( + this.DoBackup), new Object[] { saveTime }); + + return 0; + } + + public object DoMaintenance(object p) + { + object[] parms = (object[])p; + int sleepTime = (int)parms[0]; + + foreach (XScriptInstance inst in m_Scripts.Values) + { + if(inst.EventTime() > m_EventLimit) + { + inst.Stop(100); + if(!m_KillTimedOutScripts) + inst.Start(); + } + } + + System.Threading.Thread.Sleep(sleepTime); + + m_ThreadPool.QueueWorkItem(new WorkItemCallback( + this.DoMaintenance), new Object[] + { sleepTime }); + + return 0; + } + + public string Name + { + get { return "XEngine"; } + } + + public bool IsSharedModule + { + get { return false; } + } + + // + // XEngine functions + // + public int MaxScriptQueue + { + get { return m_MaxScriptQueue; } + } + + // + // Hooks + // + public void OnRezScript(uint localID, LLUUID itemID, string script) + { + m_ThreadPool.QueueWorkItem(new WorkItemCallback( + this.DoOnRezScript), new Object[] + { localID, itemID, script}); + } + + private object DoOnRezScript(object parm) + { + Object[] p = (Object[])parm; + uint localID = (uint)p[0]; + LLUUID itemID = (LLUUID)p[1]; + string script =(string)p[2]; + + // Get the asset ID of the script, so we can check if we + // already have it. + + SceneObjectPart part = m_Scene.GetSceneObjectPart(localID); + if(part == null) + return false; + + TaskInventoryItem item = part.GetInventoryItem(itemID); + if(item == null) + return false; + + LLUUID assetID=item.AssetID; + +// m_log.DebugFormat("[XEngine] Compiling script {0} ({1})", +// item.Name, itemID.ToString()); + + string assembly=""; + try + { + assembly=m_Compiler.PerformScriptCompile(script, + assetID.ToString()); + m_log.DebugFormat("[XEngine] Loaded script {0}.{1}", + part.ParentGroup.RootPart.Name, item.Name); + } + catch (Exception e) + { + try + { + // DISPLAY ERROR INWORLD + string text = "Error compiling script:\r\n" + e.Message.ToString(); + if (text.Length > 1400) + text = text.Substring(0, 1400); + World.SimChat(Helpers.StringToField(text), + ChatTypeEnum.DebugChannel, 2147483647, + part.AbsolutePosition, + part.Name, part.UUID, false); + } + catch (Exception e2) // LEGIT: User Scripting + { + m_log.Error("[XEngine]: "+ + "Error displaying error in-world: " + + e2.ToString()); + m_log.Error("[XEngine]: " + + "Errormessage: Error compiling script:\r\n" + + e.Message.ToString()); + } + + return false; + } + + lock(m_Scripts) + { + // Create the object record + + if(!m_PrimObjects.ContainsKey(localID)) + m_PrimObjects[localID] = new List(); + + if(!m_PrimObjects[localID].Contains(itemID)) + m_PrimObjects[localID].Add(itemID); + + if(!m_Assemblies.ContainsKey(assetID)) + m_Assemblies[assetID] = assembly; + + if((!m_Scripts.ContainsKey(itemID)) || + (m_Scripts[itemID].AssetID != assetID)) + { + LLUUID appDomain=assetID; + + if(part.ParentGroup.RootPart.m_IsAttachment) + appDomain=part.ParentGroup.RootPart.UUID; + + if(!m_AppDomains.ContainsKey(appDomain)) + { + try + { + AppDomainSetup appSetup = new AppDomainSetup(); +// appSetup.ApplicationBase = Path.Combine( +// "ScriptEngines", +// m_Scene.RegionInfo.RegionID.ToString()); + + Evidence baseEvidence = + AppDomain.CurrentDomain.Evidence; + Evidence evidence = new Evidence(baseEvidence); + + m_AppDomains[appDomain] = + AppDomain.CreateDomain( + m_Scene.RegionInfo.RegionID.ToString(), + evidence, appSetup); + + m_AppDomains[appDomain].AssemblyResolve += + new ResolveEventHandler( + AssemblyResolver.OnAssemblyResolve); + m_DomainScripts[appDomain] = new List(); + } + catch (Exception e) + { + m_log.Error("[XEngine] Exception creating app domain:\n"+e.ToString()); + return false; + } + } + m_DomainScripts[appDomain].Add(itemID); + + + XScriptInstance instance = new XScriptInstance(this,localID, + part.UUID, itemID, assetID, assembly, + m_AppDomains[appDomain]); + + instance.AppDomain = appDomain; + + m_Scripts[itemID] = instance; + } + } + return true; + } + + public void OnRemoveScript(uint localID, LLUUID itemID) + { + lock(m_Scripts) + { + // Do we even have it? + if(!m_Scripts.ContainsKey(itemID)) + return; + + m_ASYNCLSLCommandManager.RemoveScript(localID, itemID); + + XScriptInstance instance=m_Scripts[itemID]; + m_Scripts.Remove(itemID); + + instance.ClearQueue(); + instance.Stop(0); + + SceneObjectPart part = + m_Scene.GetSceneObjectPart(localID); + + if(part != null) + part.RemoveScriptEvents(itemID); + + // Remove the script from it's prim + if(m_PrimObjects.ContainsKey(localID)) + { + // Remove inventory item record + if(m_PrimObjects[localID].Contains(itemID)) + m_PrimObjects[localID].Remove(itemID); + + // If there are no more scripts, remove prim + if(m_PrimObjects[localID].Count == 0) + { + m_PrimObjects.Remove(localID); + } + } + + m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); + if(m_DomainScripts[instance.AppDomain].Count == 0) + { + m_DomainScripts.Remove(instance.AppDomain); + UnloadAppDomain(instance.AppDomain); + } + + instance = null; + + CleanAssemblies(); + } + } + + public void OnScriptReset(uint localID, LLUUID itemID) + { + ResetScript(itemID); + } + + private void CleanAssemblies() + { + List assetIDList = new List(m_Assemblies.Keys); + + foreach (XScriptInstance i in m_Scripts.Values) + { + if(assetIDList.Contains(i.AssetID)) + assetIDList.Remove(i.AssetID); + } + + foreach (LLUUID assetID in assetIDList) + { +// m_log.DebugFormat("[XEngine] Removing unreferenced assembly {0}", m_Assemblies[assetID]); + try + { + if(File.Exists(m_Assemblies[assetID])) + File.Delete(m_Assemblies[assetID]); + if(File.Exists(m_Assemblies[assetID]+".state")) + File.Delete(m_Assemblies[assetID]+".state"); + if(File.Exists(m_Assemblies[assetID]+".mdb")) + File.Delete(m_Assemblies[assetID]+".mdb"); + } + catch (Exception e) + { + } + m_Assemblies.Remove(assetID); + } + } + + private void UnloadAppDomain(LLUUID id) + { + if(m_AppDomains.ContainsKey(id)) + { + AppDomain domain=m_AppDomains[id]; + m_AppDomains.Remove(id); + + AppDomain.Unload(domain); + domain = null; +// m_log.DebugFormat("[XEngine] Unloaded app domain {0}", id.ToString()); + } + } + + // + // Start processing + // + private void StartEngine(int minThreads, int maxThreads, + int idleTimeout, ThreadPriority threadPriority, + int maxScriptQueue, int stackSize) + { + m_MaxScriptQueue=maxScriptQueue; + + STPStartInfo startInfo = new STPStartInfo(); + startInfo.IdleTimeout = idleTimeout; + startInfo.MaxWorkerThreads = maxThreads; + startInfo.MinWorkerThreads = minThreads; + startInfo.ThreadPriority = threadPriority; + startInfo.StackSize = stackSize; + startInfo.StartSuspended = true; + + m_ThreadPool = new SmartThreadPool(startInfo); + } + + // + // Used by script instances to queue event handler jobs + // + public IWorkItemResult QueueEventHandler(object parms) + { + return m_ThreadPool.QueueWorkItem(new WorkItemCallback( + this.ProcessEventHandler), parms); + } + + // + // The main script engine worker + // + private object ProcessEventHandler(object parms) + { + XScriptInstance instance=(XScriptInstance)parms; + + return instance.EventProcessor(); + } + + // + // Post event to an entire prim + // + public bool PostObjectEvent(uint localID, XEventParams p) + { + bool result = false; + + if(!m_PrimObjects.ContainsKey(localID)) + return false; + + foreach (LLUUID itemID in m_PrimObjects[localID]) + { + if(m_Scripts.ContainsKey(itemID)) + { + XScriptInstance instance = m_Scripts[itemID]; + if(instance != null) + { + instance.PostEvent(p); + result = true; + } + } + } + return result; + } + + // + // Post an event to a single script + // + public bool PostScriptEvent(LLUUID itemID, XEventParams p) + { + if(m_Scripts.ContainsKey(itemID)) + { + XScriptInstance instance = m_Scripts[itemID]; + if(instance != null) + instance.PostEvent(p); + return true; + } + return false; + } + + public Assembly OnAssemblyResolve(object sender, + ResolveEventArgs args) + { + if(!(sender is System.AppDomain)) + return null; + + string[] pathList=new string[] {"bin", "ScriptEngines", + Path.Combine("ScriptEngines", + m_Scene.RegionInfo.RegionID.ToString())}; + + string assemblyName = args.Name; + if(assemblyName.IndexOf(",") != -1) + assemblyName=args.Name.Substring(0, args.Name.IndexOf(",")); + + foreach (string s in pathList) + { + string path=Path.Combine(Directory.GetCurrentDirectory(), + Path.Combine(s, assemblyName))+".dll"; + + if(File.Exists(path)) + return Assembly.LoadFrom(path); + } + + return null; + } + + private XScriptInstance GetInstance(LLUUID itemID) + { + XScriptInstance instance; + lock(m_Scripts) + { + if(!m_Scripts.ContainsKey(itemID)) + return null; + instance = m_Scripts[itemID]; + } + return instance; + } + + public void SetScriptState(LLUUID itemID, bool running) + { + XScriptInstance instance = GetInstance(itemID); + if(instance != null) + { + if(running) + instance.Start(); + else + instance.Stop(500); + } + } + + public bool GetScriptState(LLUUID itemID) + { + XScriptInstance instance = GetInstance(itemID); + if(instance != null) + return instance.Running; + return false; + } + + public void ResetScript(LLUUID itemID) + { + XScriptInstance instance = GetInstance(itemID); + if(instance != null) + instance.ResetScript(); + } + + public XDetectParams GetDetectParams(LLUUID itemID, int idx) + { + XScriptInstance instance = GetInstance(itemID); + if(instance != null) + return instance.GetDetectParams(idx); + return new XDetectParams(); + } + + public LLUUID GetDetectID(LLUUID itemID, int idx) + { + XScriptInstance instance = GetInstance(itemID); + if(instance != null) + return instance.GetDetectID(idx); + return LLUUID.Zero; + } + } + + public struct XDetectParams + { + public LLUUID Key; + public LSL_Types.Vector3 OffsetPos; + } + + public class XEventParams + { + public XEventParams(string eventName, Object[] eventParams, XDetectParams[] detectParams) + { + EventName=eventName; + Params=eventParams; + DetectParams=detectParams; + } + + public string EventName; + public Object[] Params; + public XDetectParams[] DetectParams; + } + + public class XScriptInstance + { + private XEngine m_Engine; + private IWorkItemResult m_CurrentResult=null; + private Queue m_EventQueue=new Queue(32); + private bool m_RunEvents=false; + private LLUUID m_ItemID; + private uint m_LocalID; + private LLUUID m_ObjectID; + private LLUUID m_AssetID; + private IScript m_Script; + private LSL_ScriptCommands m_LSLCommands; + private OSSL_ScriptCommands m_OSSLCommands; + private Executor m_Executor; + private LLUUID m_AppDomain; + private XDetectParams[] m_DetectParams; + private bool m_TimerQueued; + private DateTime m_EventStart; + private bool m_InEvent; + + // Script state + private string m_State="default"; + + public Object[] PluginData = new Object[0]; + + public bool Running + { + get { return m_RunEvents; } + } + + public string State + { + get { return m_State; } + set { m_State = value; } + } + + public XEngine Engine + { + get { return m_Engine; } + } + + public LLUUID AppDomain + { + get { return m_AppDomain; } + set { m_AppDomain = value; } + } + + public LLUUID ItemID + { + get { return m_ItemID; } + } + + public LLUUID ObjectID + { + get { return m_ObjectID; } + } + + public uint LocalID + { + get { return m_LocalID; } + } + + public LLUUID AssetID + { + get { return m_AssetID; } + } + + public Queue EventQueue + { + get { return m_EventQueue; } + } + + public void ClearQueue() + { + m_TimerQueued = false; + m_EventQueue.Clear(); + } + + public XScriptInstance(XEngine engine, uint localID, LLUUID objectID, + LLUUID itemID, LLUUID assetID, string assembly, AppDomain dom) + { + m_Engine=engine; + + m_LocalID = localID; + m_ObjectID = objectID; + m_ItemID = itemID; + m_AssetID = assetID; + + SceneObjectPart part=engine.World.GetSceneObjectPart(localID); + if(part == null) + { + engine.Log.Error("[XEngine] SceneObjectPart unavailable. Script NOT started."); + return; + } + + m_LSLCommands = new LSL_ScriptCommands(engine, this, part, localID, + itemID); + m_OSSLCommands = new OSSL_ScriptCommands(engine, this, part, + localID, itemID); + + try + { + m_Script = (IScript)dom.CreateInstanceAndUnwrap( + Path.GetFileNameWithoutExtension(assembly), + "SecondLife.Script"); + } + catch (Exception e) + { + m_Engine.Log.ErrorFormat("[XEngine] Error loading assembly {0}\n"+e.ToString(), assembly); + } + + try + { + m_Script.Start(m_LSLCommands, m_OSSLCommands); + + m_Executor = new Executor(m_Script); + +// m_Engine.Log.Debug("[XEngine] Script instance created"); + + part.SetScriptEvents(m_ItemID, + (int)m_Executor.GetStateEventFlags()); + } + catch (Exception e) + { + m_Engine.Log.Error("Error loading script instance\n"+e.ToString()); + } + + string savedState = assembly+".state"; + if(File.Exists(savedState)) + { + string xml = String.Empty; + + try + { + FileInfo fi = new FileInfo(savedState); + int size=(int)fi.Length; + if(size < 130000) + { + using (FileStream fs = File.Open(savedState, + FileMode.Open, FileAccess.Read, FileShare.None)) + { + System.Text.ASCIIEncoding enc = + new System.Text.ASCIIEncoding(); + + Byte[] data=new Byte[size]; + fs.Read(data, 0, size); + + xml=enc.GetString(data); + + ScriptSerializer.Deserialize(xml, this); + + m_Engine.m_ASYNCLSLCommandManager.CreateFromData( + m_LocalID, m_ItemID, m_ObjectID, + PluginData); + } + } + else + { + m_Engine.Log.Error("Unable to load script state: Memory limit exceeded"); + PostEvent(new XEventParams("state_entry", + new Object[0], new XDetectParams[0])); + } + } + catch (Exception e) + { + m_Engine.Log.ErrorFormat("Unable to load script state from xml: {0}\n"+e.ToString(), xml); + PostEvent(new XEventParams("state_entry", + new Object[0], new XDetectParams[0])); + } + } + else + { + PostEvent(new XEventParams("state_entry", + new Object[0], new XDetectParams[0])); + } + Start(); + } + + public void VarDump(Dictionary vars) + { + Console.WriteLine("Variable dump for script {0}", m_ItemID.ToString()); + foreach (KeyValuePair v in vars) + { + Console.WriteLine("Variable: {0} = '{1}'", v. Key, + v.Value.ToString()); + } + } + + public void Start() + { + lock(m_EventQueue) + { + if(Running) + return; + + m_RunEvents=true; + + if(m_EventQueue.Count > 0) + { + if(m_CurrentResult == null) + m_CurrentResult=m_Engine.QueueEventHandler(this); + } + } + } + + public bool Stop(int timeout) + { + IWorkItemResult result; + + lock(m_EventQueue) + { + if(!Running) + return true; + + if(m_CurrentResult == null) + { + m_RunEvents=false; + return true; + } + + if(m_CurrentResult.Cancel()) + { + m_CurrentResult=null; + m_RunEvents=false; + return true; + } + + result=m_CurrentResult; + m_RunEvents=false; + } + + if(SmartThreadPool.WaitAll(new IWorkItemResult[] {result}, new TimeSpan((long)timeout*100000), false)) + { + return true; + } + + lock(m_EventQueue) + { + if(m_CurrentResult != null) + m_CurrentResult.Abort(); + else + return true; + } + + return true; + } + + public void SetState(string state) + { + PostEvent(new XEventParams("state_exit", new Object[0], + new XDetectParams[0])); + PostEvent(new XEventParams("state", new Object[] { state }, + new XDetectParams[0])); + PostEvent(new XEventParams("state_entry", new Object[0], + new XDetectParams[0])); + } + + public void PostEvent(XEventParams data) + { + lock(m_EventQueue) + { + if(m_EventQueue.Count >= m_Engine.MaxScriptQueue) + return; + + m_EventQueue.Enqueue(data); + if(data.EventName == "timer") + { + if(m_TimerQueued) + return; + m_TimerQueued = true; + } + + if(!m_RunEvents) + return; + + if(m_CurrentResult == null) + { + m_CurrentResult=m_Engine.QueueEventHandler(this); + } + } + } + + public object EventProcessor() + { + XEventParams data=null; + + lock(m_EventQueue) + { + data=(XEventParams)m_EventQueue.Dequeue(); + if(data == null) // Shouldn't happen + { + m_CurrentResult=null; + return 0; + } + if(data.EventName == "timer") + m_TimerQueued = false; + } + + m_DetectParams=data.DetectParams; + + if(data.EventName == "state") // Hardcoded state change + { + m_State=data.Params[0].ToString(); + m_Engine.m_ASYNCLSLCommandManager.RemoveScript( + m_LocalID, m_ItemID); + + SceneObjectPart part=m_Engine.World.GetSceneObjectPart( + m_LocalID); + if(part != null) + { + part.SetScriptEvents(m_ItemID, + (int)m_Executor.GetStateEventFlags()); + } + } + else + { +// m_Engine.Log.DebugFormat("[XEngine] Processed event {0}", data.EventName); + SceneObjectPart part=m_Engine.World.GetSceneObjectPart( + m_LocalID); + try + { + m_EventStart = DateTime.Now; + m_InEvent = true; + m_Executor.ExecuteEvent(data.EventName, data.Params); + m_InEvent = false; + } + catch (Exception e) + { + m_InEvent = false; + if(e is System.Threading.ThreadAbortException) + { + lock(m_EventQueue) + { + if((m_EventQueue.Count > 0) && m_RunEvents) + { + m_CurrentResult=m_Engine.QueueEventHandler(this); + } + else + { + m_CurrentResult=null; + } + } + + m_DetectParams=null; + + return 0; + } + + try + { + // DISPLAY ERROR INWORLD + string text = "Runtime error:\n" + e.ToString(); + if (text.Length > 1400) + text = text.Substring(0, 1400); + m_Engine.World.SimChat(Helpers.StringToField(text), + ChatTypeEnum.DebugChannel, 2147483647, + part.AbsolutePosition, + part.Name, part.UUID, false); + } + catch (Exception e2) // LEGIT: User Scripting + { + m_Engine.Log.Error("[XEngine]: "+ + "Error displaying error in-world: " + + e2.ToString()); + m_Engine.Log.Error("[XEngine]: " + + "Errormessage: Error compiling script:\r\n" + + e.ToString()); + } + } + } + + lock(m_EventQueue) + { + if((m_EventQueue.Count > 0) && m_RunEvents) + { + m_CurrentResult=m_Engine.QueueEventHandler(this); + } + else + { + m_CurrentResult=null; + } + } + + m_DetectParams=null; + + return 0; + } + + public int EventTime() + { + if(!m_InEvent) + return 0; + + return (DateTime.Now - m_EventStart).Seconds; + } + + public void ResetScript() + { + Stop(0); + m_Engine.m_ASYNCLSLCommandManager.RemoveScript(m_LocalID, m_ItemID); + m_EventQueue.Clear(); + m_Script.ResetVars(); + m_State = "default"; + Start(); + PostEvent(new XEventParams("state_entry", + new Object[0], new XDetectParams[0])); + } + + public Dictionary GetVars() + { + return m_Script.GetVars(); + } + + public void SetVars(Dictionary vars) + { + m_Script.SetVars(vars); + } + + public XDetectParams GetDetectParams(int idx) + { + if(idx < 0 || idx >= m_DetectParams.Length) + return new XDetectParams(); + + return m_DetectParams[idx]; + } + + public LLUUID GetDetectID(int idx) + { + if(idx < 0 || idx >= m_DetectParams.Length) + return LLUUID.Zero; + + return m_DetectParams[idx].Key; + } + + public void SaveState(string assembly) + { + PluginData = + m_Engine.m_ASYNCLSLCommandManager.GetSerializationData( + m_ItemID); + + string xml=ScriptSerializer.Serialize(this); + + try + { + FileStream fs = File.Create(assembly+".state"); + System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); + Byte[] buf=enc.GetBytes(xml); + fs.Write(buf, 0, buf.Length); + fs.Close(); + } + catch(Exception) + { + return; + } + } + } + + public class ScriptSerializer + { + public static string Serialize(XScriptInstance instance) + { + instance.Stop(50); + + XmlDocument xmldoc = new XmlDocument(); + + XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration, + "", ""); + xmldoc.AppendChild(xmlnode); + + XmlElement rootElement = xmldoc.CreateElement("", "ScriptState", + ""); + xmldoc.AppendChild(rootElement); + + XmlElement state = xmldoc.CreateElement("", "State", ""); + state.AppendChild(xmldoc.CreateTextNode(instance.State)); + + rootElement.AppendChild(state); + + Dictionary vars = instance.GetVars(); + + XmlElement variables = xmldoc.CreateElement("", "Variables", ""); + + foreach (KeyValuePair var in vars) + WriteTypedValue(xmldoc, variables, "Variable", var.Key, + var.Value); + + rootElement.AppendChild(variables); + + XmlElement queue = xmldoc.CreateElement("", "Queue", ""); + + int count = instance.EventQueue.Count; + + while(count > 0) + { + XEventParams ep = (XEventParams)instance.EventQueue.Dequeue(); + instance.EventQueue.Enqueue(ep); + count--; + + XmlElement item = xmldoc.CreateElement("", "Item", ""); + XmlAttribute itemEvent = xmldoc.CreateAttribute("", "event", + ""); + itemEvent.Value=ep.EventName; + item.Attributes.Append(itemEvent); + + XmlElement parms = xmldoc.CreateElement("", "Params", ""); + + foreach (Object o in ep.Params) + WriteTypedValue(xmldoc, parms, "Param", String.Empty, o); + + item.AppendChild(parms); + + XmlElement detect = xmldoc.CreateElement("", "Detected", ""); + + foreach (XDetectParams det in ep.DetectParams) + { + XmlElement objectElem = xmldoc.CreateElement("", "Object", + ""); + XmlAttribute pos = xmldoc.CreateAttribute("", "pos", ""); + pos.Value=det.OffsetPos.ToString(); + objectElem.Attributes.Append(pos); + objectElem.AppendChild( + xmldoc.CreateTextNode(det.Key.ToString())); + + detect.AppendChild(objectElem); + } + + item.AppendChild(detect); + + queue.AppendChild(item); + } + + rootElement.AppendChild(queue); + + XmlNode plugins = xmldoc.CreateElement("", "Plugins", ""); + if(instance.PluginData.Length > 0) + DumpList(xmldoc, plugins, + new LSL_Types.list(instance.PluginData)); + + rootElement.AppendChild(plugins); + + instance.Start(); + + return xmldoc.InnerXml; + } + + public static void Deserialize(string xml, XScriptInstance instance) + { + XmlDocument doc = new XmlDocument(); + + Dictionary vars = instance.GetVars(); + + instance.PluginData = new Object[0]; + + doc.LoadXml(xml); + + XmlNodeList rootL = doc.GetElementsByTagName("ScriptState"); + if(rootL.Count != 1) + { + return; + } + XmlNode rootNode = rootL[0]; + + if(rootNode != null) + { + object varValue; + XmlNodeList partL = rootNode.ChildNodes; + + foreach (XmlNode part in partL) + { + switch(part.Name) + { + case "State": + instance.State=part.InnerText; + break; + case "Variables": + XmlNodeList varL = part.ChildNodes; + foreach (XmlNode var in varL) + { + string varName; + varValue=ReadTypedValue(var, out varName); + + if(vars.ContainsKey(varName)) + vars[varName] = varValue; + } + instance.SetVars(vars); + break; + case "Queue": + XmlNodeList itemL = part.ChildNodes; + foreach (XmlNode item in itemL) + { + List parms = new List(); + List detected = + new List(); + + string eventName = + item.Attributes.GetNamedItem("event").Value; + XmlNodeList eventL = item.ChildNodes; + foreach (XmlNode evt in eventL) + { + switch(evt.Name) + { + case "Params": + XmlNodeList prms = evt.ChildNodes; + foreach (XmlNode pm in prms) + parms.Add(ReadTypedValue(pm)); + + break; + case "Detected": + XmlNodeList detL = evt.ChildNodes; + foreach (XmlNode det in detL) + { + string vect = + det.Attributes.GetNamedItem( + "pos").Value; + LSL_Types.Vector3 v = + new LSL_Types.Vector3(vect); + LLUUID uuid = new LLUUID(); + LLUUID.TryParse(det.InnerText, + out uuid); + + XDetectParams d; + d.Key = uuid; + d.OffsetPos = v; + + detected.Add(d); + } + break; + } + } + XEventParams ep = new XEventParams( + eventName, parms.ToArray(), + detected.ToArray()); + instance.EventQueue.Enqueue(ep); + } + break; + case "Plugins": + instance.PluginData = ReadList(part).Data; + break; + } + } + } + } + + private static void DumpList(XmlDocument doc, XmlNode parent, + LSL_Types.list l) + { + foreach (Object o in l.Data) + WriteTypedValue(doc, parent, "ListItem", "", o); + } + + private static LSL_Types.list ReadList(XmlNode parent) + { + List olist = new List(); + + XmlNodeList itemL = parent.ChildNodes; + foreach(XmlNode item in itemL) + olist.Add(ReadTypedValue(item)); + + return new LSL_Types.list(olist.ToArray()); + } + + private static void WriteTypedValue(XmlDocument doc, XmlNode parent, + string tag, string name, object value) + { + Type t=value.GetType(); + XmlAttribute typ = doc.CreateAttribute("", "type", ""); + XmlNode n = doc.CreateElement("", tag, ""); + + if(value is LSL_Types.list) + { + typ.Value = "list"; + n.Attributes.Append(typ); + + DumpList(doc, n, (LSL_Types.list) value); + + if(name != String.Empty) + { + XmlAttribute nam = doc.CreateAttribute("", "name", ""); + nam.Value = name; + n.Attributes.Append(nam); + } + + parent.AppendChild(n); + return; + } + + n.AppendChild(doc.CreateTextNode(value.ToString())); + + typ.Value = t.ToString(); + n.Attributes.Append(typ); + if(name != String.Empty) + { + XmlAttribute nam = doc.CreateAttribute("", "name", ""); + nam.Value = name; + n.Attributes.Append(nam); + } + + parent.AppendChild(n); + } + + private static object ReadTypedValue(XmlNode tag, out string name) + { + name = tag.Attributes.GetNamedItem("name").Value; + + return ReadTypedValue(tag); + } + + private static object ReadTypedValue(XmlNode tag) + { + Object varValue; + string assembly; + + string itemType = tag.Attributes.GetNamedItem("type").Value; + + if(itemType == "list") + return ReadList(tag); + + if(itemType == "libsecondlife.LLUUID") + { + LLUUID val = new LLUUID(); + LLUUID.TryParse(tag.InnerText, out val); + + return val; + } + + Type itemT = Type.GetType(itemType); + if(itemT == null) + { + Object[] args = + new Object[] { tag.InnerText }; + + assembly = itemType+", OpenSim.Region.ScriptEngine.XEngine.Script"; + itemT = Type.GetType(assembly); + if(itemT == null) + return null; + + varValue = Activator.CreateInstance(itemT, args); + + if(varValue == null) + return null; + } + else + { + varValue = Convert.ChangeType(tag.InnerText, itemT); + } + return varValue; + } + } +} -- cgit v1.1