/* * 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 OpenSimulator 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.Globalization; using System.Reflection; using System.Text; using System.Threading; using log4net; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.ScriptEngine.Interfaces; using OpenSim.Region.ScriptEngine.Shared.ScriptBase; using OpenSim.ScriptEngine.Shared; namespace OpenSim.ScriptEngine.Components.DotNetEngine.Scheduler { public partial class ScriptManager { private Queue<LoadUnloadStructure> LUQueue = new Queue<LoadUnloadStructure>(); private int LoadUnloadMaxQueueSize = 500; private Object scriptLock = new Object(); //private Dictionary<InstanceData, DetectParams[]> detparms = new Dictionary<InstanceData, DetectParams[]>(); // Load/Unload structure public void AddScript(ScriptStructure script) { lock (LUQueue) { if ((LUQueue.Count >= LoadUnloadMaxQueueSize)) { m_log.ErrorFormat("[{0}] ERROR: Load queue count is at {1} of max {2}. Ignoring load request for script LocalID: {3}, ItemID: {4}.", Name, LUQueue.Count, LoadUnloadMaxQueueSize, script.LocalID, script.ItemID); return; } LoadUnloadStructure ls = new LoadUnloadStructure(); ls.Script = script; ls.Action = LoadUnloadStructure.LUType.Load; LUQueue.Enqueue(ls); } } public void RemoveScript(uint localID, UUID itemID) { LoadUnloadStructure ls = new LoadUnloadStructure(); // See if we can find script if (!TryGetScript(localID, itemID, ref ls.Script)) { // Set manually ls.Script.LocalID = localID; ls.Script.ItemID = itemID; } ls.Script.StartParam = 0; ls.Action = LoadUnloadStructure.LUType.Unload; ls.PostOnRez = false; lock (LUQueue) { LUQueue.Enqueue(ls); } } internal bool DoScriptLoadUnload() { bool ret = false; // if (!m_started) // return; lock (LUQueue) { if (LUQueue.Count > 0) { LoadUnloadStructure item = LUQueue.Dequeue(); ret = true; if (item.Action == LoadUnloadStructure.LUType.Unload) { _StopScript(item.Script.LocalID, item.Script.ItemID); RemoveScript(item.Script.LocalID, item.Script.ItemID); } else if (item.Action == LoadUnloadStructure.LUType.Load) { m_log.DebugFormat("[{0}] Loading script", Name); _StartScript(item); } } } return ret; } //public void _StartScript(uint localID, UUID itemID, string Script, int startParam, bool postOnRez) private void _StartScript(LoadUnloadStructure ScriptObject) { m_log.DebugFormat( "[{0}]: ScriptManager StartScript: localID: {1}, itemID: {2}", Name, ScriptObject.Script.LocalID, ScriptObject.Script.ItemID); // We will initialize and start the script. // It will be up to the script itself to hook up the correct events. SceneObjectPart m_host = ScriptObject.Script.RegionInfo.Scene.GetSceneObjectPart(ScriptObject.Script.LocalID); if (null == m_host) { m_log.ErrorFormat( "[{0}]: Could not find scene object part corresponding " + "to localID {1} to start script", Name, ScriptObject.Script.LocalID); return; } //UUID assetID = UUID.Zero; TaskInventoryItem taskInventoryItem = new TaskInventoryItem(); //if (m_host.TaskInventory.TryGetValue(ScriptObject.Script.ItemID, out taskInventoryItem)) // assetID = taskInventoryItem.AssetID; ScenePresence presence = ScriptObject.Script.RegionInfo.Scene.GetScenePresence(taskInventoryItem.OwnerID); CultureInfo USCulture = new CultureInfo("en-US"); Thread.CurrentThread.CurrentCulture = USCulture; try { // // Compile script to an assembly // //TODO: DEBUG BaseClassFactory.MakeBaseClass(ScriptObject.Script); m_log.DebugFormat("[{0}] Compiling script {1}", Name, ScriptObject.Script.Name); string fileName = ""; try { IScriptCompiler compiler = ScriptObject.Script.RegionInfo.FindCompiler(ScriptObject.Script.ScriptMetaData); //RegionInfoStructure currentRegionInfo = ScriptObject.Script.RegionInfo; fileName = compiler.Compile(ScriptObject.Script.ScriptMetaData, ref ScriptObject.Script.Source); ScriptObject.Script.AssemblyFileName = fileName; } catch (Exception e) { m_log.ErrorFormat("[{0}] Internal error while compiling \"{1}\": {2}", Name, ScriptObject.Script.Name, e.ToString()); } m_log.DebugFormat("[{0}] Compiled \"{1}\" to assembly: \"{2}\".", Name, ScriptObject.Script.Name, fileName); // Add it to our script memstruct MemAddScript(ScriptObject.Script); ScriptAssemblies.IScript CompiledScript; CompiledScript = CurrentRegion.ScriptLoader.LoadScript(ScriptObject.Script); ScriptObject.Script.State = "default"; ScriptObject.Script.ScriptObject = CompiledScript; ScriptObject.Script.Disabled = false; ScriptObject.Script.Running = true; //id.LineMap = LSLCompiler.LineMap(); //id.Script = CompiledScript; //id.Source = item.Script.Script; //item.StartParam = startParam; // TODO: Fire the first start-event //int eventFlags = // m_scriptEngine.m_ScriptManager.GetStateEventFlags( // localID, itemID); //m_host.SetScriptEvents(itemID, eventFlags); ScriptObject.Script.RegionInfo.Executors_Execute(ScriptObject.Script, new EventParams(ScriptObject.Script.LocalID, ScriptObject.Script.ItemID, "state_entry", new object[] { }, new Region.ScriptEngine.Shared.DetectParams[0]) ); if (ScriptObject.PostOnRez) { ScriptObject.Script.RegionInfo.Executors_Execute(ScriptObject.Script, new EventParams(ScriptObject.Script.LocalID, "on_rez", new object[] {new Region.ScriptEngine.Shared.LSL_Types.LSLInteger(ScriptObject.StartParam) }, new Region.ScriptEngine.Shared.DetectParams[0])); } } catch (Exception e) // LEGIT: User Scripting { if (presence != null && (!ScriptObject.PostOnRez)) presence.ControllingClient.SendAgentAlertMessage( "Script saved with errors, check debug window!", false); try { // DISPLAY ERROR INWORLD string text = "Error compiling script:\n" + e.Message.ToString(); if (text.Length > 1100) text = text.Substring(0, 1099); ScriptObject.Script.RegionInfo.Scene.SimChat(Utils.StringToBytes(text), ChatTypeEnum.DebugChannel, 2147483647, m_host.AbsolutePosition, m_host.Name, m_host.UUID, false); } catch (Exception e2) // LEGIT: User Scripting { m_log.Error("[" + Name + "]: Error displaying error in-world: " + e2.ToString()); m_log.Error("[" + Name + "]: " + "Errormessage: Error compiling script:\r\n" + e2.Message.ToString()); } } } public void _StopScript(uint localID, UUID itemID) { ScriptStructure ss = new ScriptStructure(); if (!TryGetScript(localID, itemID, ref ss)) return; m_log.DebugFormat("[{0}] Unloading script", Name); // Stop long command on script //AsyncCommandManager.RemoveScript(ss); try { // Get AppDomain // Tell script not to accept new requests ss.Running = false; ss.Disabled = true; //AppDomain ad = ss.AppDomain; // Remove from internal structure MemRemoveScript(localID, itemID); // TODO: Tell AppDomain that we have stopped script } catch (Exception e) // LEGIT: User Scripting { m_log.Error("[" + Name + "]: Exception stopping script localID: " + localID + " LLUID: " + itemID.ToString() + ": " + e.ToString()); } } } }