287 lines
12 KiB
C#
287 lines
12 KiB
C#
/*
|
|
* 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.Environment.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)
|
|
{
|
|
m_log.DebugFormat("[{0}] Unloading script", Name);
|
|
_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;
|
|
|
|
// 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());
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
}
|