(Untested) Scripts are individually loaded into objects (on rez), and event fired likewise. Bugfixes coming in next commit.
This commit is contained in:
@@ -37,6 +37,7 @@ using OpenSim.Region.Environment.Scenes.Scripting;
|
||||
using OpenSim.Region.ScriptEngine.DotNetEngine.Compiler;
|
||||
using OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL;
|
||||
using OpenSim.Region.ScriptEngine.Common;
|
||||
using libsecondlife;
|
||||
|
||||
namespace OpenSim.Region.ScriptEngine.DotNetEngine
|
||||
{
|
||||
@@ -53,7 +54,6 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
|
||||
public ScriptManager(ScriptEngine scriptEngine)
|
||||
{
|
||||
m_scriptEngine = scriptEngine;
|
||||
m_scriptEngine.Log.Verbose("ScriptEngine", "ScriptManager Start");
|
||||
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
|
||||
// Object<string, Script<string, script>>
|
||||
// IMPORTANT: Types and MemberInfo-derived objects require a LOT of memory.
|
||||
// Instead use RuntimeTypeHandle, RuntimeFieldHandle and RunTimeHandle (IntPtr) instead!
|
||||
internal Dictionary<IScriptHost, Dictionary<string, LSL_BaseClass>> Scripts = new Dictionary<IScriptHost, Dictionary<string, LSL_BaseClass>>();
|
||||
internal Dictionary<uint, Dictionary<LLUUID, LSL_BaseClass>> Scripts = new Dictionary<uint, Dictionary<LLUUID, LSL_BaseClass>>();
|
||||
public Scene World
|
||||
{
|
||||
get
|
||||
@@ -79,75 +79,75 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
|
||||
}
|
||||
|
||||
|
||||
internal Dictionary<string, LSL_BaseClass>.KeyCollection GetScriptKeys(IScriptHost ObjectID)
|
||||
internal Dictionary<LLUUID, LSL_BaseClass>.KeyCollection GetScriptKeys(uint localID)
|
||||
{
|
||||
if (Scripts.ContainsKey(ObjectID) == false)
|
||||
if (Scripts.ContainsKey(localID) == false)
|
||||
return null;
|
||||
|
||||
Dictionary<string, LSL_BaseClass> Obj;
|
||||
Scripts.TryGetValue(ObjectID, out Obj);
|
||||
Dictionary<LLUUID, LSL_BaseClass> Obj;
|
||||
Scripts.TryGetValue(localID, out Obj);
|
||||
|
||||
return Obj.Keys;
|
||||
|
||||
}
|
||||
|
||||
internal LSL_BaseClass GetScript(IScriptHost ObjectID, string ScriptID)
|
||||
internal LSL_BaseClass GetScript(uint localID, LLUUID itemID)
|
||||
{
|
||||
if (Scripts.ContainsKey(ObjectID) == false)
|
||||
if (Scripts.ContainsKey(localID) == false)
|
||||
return null;
|
||||
|
||||
Dictionary<string, LSL_BaseClass> Obj;
|
||||
Scripts.TryGetValue(ObjectID, out Obj);
|
||||
if (Obj.ContainsKey(ScriptID) == false)
|
||||
Dictionary<LLUUID, LSL_BaseClass> Obj;
|
||||
Scripts.TryGetValue(localID, out Obj);
|
||||
if (Obj.ContainsKey(itemID) == false)
|
||||
return null;
|
||||
|
||||
// Get script
|
||||
LSL_BaseClass Script;
|
||||
Obj.TryGetValue(ScriptID, out Script);
|
||||
Obj.TryGetValue(itemID, out Script);
|
||||
|
||||
return Script;
|
||||
|
||||
}
|
||||
internal void SetScript(IScriptHost ObjectID, string ScriptID, LSL_BaseClass Script)
|
||||
internal void SetScript(uint localID, LLUUID itemID, LSL_BaseClass Script)
|
||||
{
|
||||
// Create object if it doesn't exist
|
||||
if (Scripts.ContainsKey(ObjectID) == false)
|
||||
if (Scripts.ContainsKey(localID) == false)
|
||||
{
|
||||
Scripts.Add(ObjectID, new Dictionary<string, LSL_BaseClass>());
|
||||
Scripts.Add(localID, new Dictionary<LLUUID, LSL_BaseClass>());
|
||||
}
|
||||
|
||||
// Delete script if it exists
|
||||
Dictionary<string, LSL_BaseClass> Obj;
|
||||
Scripts.TryGetValue(ObjectID, out Obj);
|
||||
if (Obj.ContainsKey(ScriptID) == true)
|
||||
Obj.Remove(ScriptID);
|
||||
Dictionary<LLUUID, LSL_BaseClass> Obj;
|
||||
Scripts.TryGetValue(localID, out Obj);
|
||||
if (Obj.ContainsKey(itemID) == true)
|
||||
Obj.Remove(itemID);
|
||||
|
||||
// Add to object
|
||||
Obj.Add(ScriptID, Script);
|
||||
Obj.Add(itemID, Script);
|
||||
|
||||
}
|
||||
internal void RemoveScript(IScriptHost ObjectID, string ScriptID)
|
||||
internal void RemoveScript(uint localID, LLUUID itemID)
|
||||
{
|
||||
// Don't have that object?
|
||||
if (Scripts.ContainsKey(ObjectID) == false)
|
||||
if (Scripts.ContainsKey(localID) == false)
|
||||
return;
|
||||
|
||||
// Delete script if it exists
|
||||
Dictionary<string, LSL_BaseClass> Obj;
|
||||
Scripts.TryGetValue(ObjectID, out Obj);
|
||||
if (Obj.ContainsKey(ScriptID) == true)
|
||||
Obj.Remove(ScriptID);
|
||||
Dictionary<LLUUID, LSL_BaseClass> Obj;
|
||||
Scripts.TryGetValue(localID, out Obj);
|
||||
if (Obj.ContainsKey(itemID) == true)
|
||||
Obj.Remove(itemID);
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// Fetches, loads and hooks up a script to an objects events
|
||||
/// </summary>
|
||||
/// <param name="ScriptID"></param>
|
||||
/// <param name="ObjectID"></param>
|
||||
public void StartScript(string ScriptID, IScriptHost ObjectID)
|
||||
/// <param name="itemID"></param>
|
||||
/// <param name="localID"></param>
|
||||
public void StartScript(uint localID, LLUUID itemID, string Script)
|
||||
{
|
||||
//IScriptHost root = host.GetRoot();
|
||||
m_scriptEngine.Log.Verbose("ScriptEngine", "ScriptManager StartScript: ScriptID: " + ScriptID + ", ObjectID: " + ObjectID);
|
||||
m_scriptEngine.Log.Verbose("ScriptEngine", "ScriptManager StartScript: localID: " + localID + ", itemID: " + itemID);
|
||||
|
||||
// We will initialize and start the script.
|
||||
// It will be up to the script itself to hook up the correct events.
|
||||
@@ -157,59 +157,39 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
|
||||
{
|
||||
|
||||
|
||||
// * Fetch script from server
|
||||
// DEBUG - ScriptID is an actual filename during debug
|
||||
// (therefore we can also check type by looking at extension)
|
||||
FileName = ScriptID;
|
||||
|
||||
// * Does script need compile? Send it to LSL compiler first. (TODO: Use (and clean) compiler cache)
|
||||
//myScriptEngine.m_logger.Verbose("ScriptEngine", "ScriptManager Script extension: " + System.IO.Path.GetExtension(FileName).ToLower());
|
||||
switch (System.IO.Path.GetExtension(FileName).ToLower())
|
||||
{
|
||||
case ".txt":
|
||||
case ".lsl":
|
||||
case ".cs":
|
||||
m_scriptEngine.Log.Verbose("ScriptEngine", "ScriptManager Script is CS/LSL, compiling to .Net Assembly");
|
||||
// Create a new instance of the compiler (currently we don't want reuse)
|
||||
OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.Compiler LSLCompiler = new OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.Compiler();
|
||||
// Compile
|
||||
FileName = LSLCompiler.Compile(FileName);
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Unknown script type.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
m_scriptEngine.Log.Verbose("ScriptEngine", "Compilation done");
|
||||
// Create a new instance of the compiler (currently we don't want reuse)
|
||||
OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.Compiler LSLCompiler = new OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.Compiler();
|
||||
// Compile (We assume LSL)
|
||||
FileName = LSLCompiler.CompileFromLSLText(Script);
|
||||
m_scriptEngine.Log.Verbose("ScriptEngine", "Compilation of " + FileName + " done");
|
||||
// * Insert yield into code
|
||||
FileName = ProcessYield(FileName);
|
||||
|
||||
|
||||
//OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSO.LSL_BaseClass Script = LoadAndInitAssembly(FreeAppDomain, FileName);
|
||||
|
||||
//OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.LSL_BaseClass Script = LoadAndInitAssembly(FreeAppDomain, FileName, ObjectID);
|
||||
//OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.LSL_BaseClass Script = LoadAndInitAssembly(FreeAppDomain, FileName, localID);
|
||||
long before;
|
||||
before = GC.GetTotalMemory(true);
|
||||
LSL_BaseClass Script = m_scriptEngine.myAppDomainManager.LoadScript(FileName);
|
||||
Console.WriteLine("Script occupies {0} bytes", GC.GetTotalMemory(true) - before);
|
||||
LSL_BaseClass CompiledScript = m_scriptEngine.myAppDomainManager.LoadScript(FileName);
|
||||
Console.WriteLine("Script " + itemID + " occupies {0} bytes", GC.GetTotalMemory(true) - before);
|
||||
before = GC.GetTotalMemory(true);
|
||||
Script = m_scriptEngine.myAppDomainManager.LoadScript(FileName);
|
||||
Console.WriteLine("Script occupies {0} bytes", GC.GetTotalMemory(true) - before);
|
||||
//Script = m_scriptEngine.myAppDomainManager.LoadScript(FileName);
|
||||
//Console.WriteLine("Script occupies {0} bytes", GC.GetTotalMemory(true) - before);
|
||||
//before = GC.GetTotalMemory(true);
|
||||
//Script = m_scriptEngine.myAppDomainManager.LoadScript(FileName);
|
||||
//Console.WriteLine("Script occupies {0} bytes", GC.GetTotalMemory(true) - before);
|
||||
|
||||
|
||||
// Add it to our temporary active script keeper
|
||||
//Scripts.Add(FullScriptID, Script);
|
||||
SetScript(ObjectID, ScriptID, Script);
|
||||
//Scripts.Add(FullitemID, Script);
|
||||
SetScript(localID, itemID, CompiledScript);
|
||||
// We need to give (untrusted) assembly a private instance of BuiltIns
|
||||
// this private copy will contain Read-Only FullScriptID so that it can bring that on to the server whenever needed.
|
||||
LSL_BuiltIn_Commands LSLB = new LSL_BuiltIn_Commands(this, ObjectID);
|
||||
// this private copy will contain Read-Only FullitemID so that it can bring that on to the server whenever needed.
|
||||
LSL_BuiltIn_Commands LSLB = new LSL_BuiltIn_Commands(this, World.GetSceneObjectPart(localID));
|
||||
|
||||
// Start the script - giving it BuiltIns
|
||||
Script.Start(LSLB);
|
||||
CompiledScript.Start(LSLB);
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -219,16 +199,16 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
|
||||
|
||||
|
||||
}
|
||||
public void StopScript(string ScriptID, IScriptHost ObjectID)
|
||||
public void StopScript(uint localID, LLUUID itemID)
|
||||
{
|
||||
// Stop script
|
||||
|
||||
// Get AppDomain
|
||||
AppDomain ad = GetScript(ObjectID, ScriptID).Exec.GetAppDomain();
|
||||
AppDomain ad = GetScript(localID, itemID).Exec.GetAppDomain();
|
||||
// Tell script not to accept new requests
|
||||
GetScript(ObjectID, ScriptID).Exec.StopScript();
|
||||
GetScript(localID, itemID).Exec.StopScript();
|
||||
// Remove from internal structure
|
||||
RemoveScript(ObjectID, ScriptID);
|
||||
RemoveScript(localID, itemID);
|
||||
// Tell AppDomain that we have stopped script
|
||||
m_scriptEngine.myAppDomainManager.StopScript(ad);
|
||||
}
|
||||
@@ -244,16 +224,16 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
|
||||
/// <summary>
|
||||
/// Execute a LL-event-function in Script
|
||||
/// </summary>
|
||||
/// <param name="ObjectID">Object the script is located in</param>
|
||||
/// <param name="ScriptID">Script ID</param>
|
||||
/// <param name="localID">Object the script is located in</param>
|
||||
/// <param name="itemID">Script ID</param>
|
||||
/// <param name="FunctionName">Name of function</param>
|
||||
/// <param name="args">Arguments to pass to function</param>
|
||||
internal void ExecuteEvent(IScriptHost ObjectID, string ScriptID, string FunctionName, object[] args)
|
||||
internal void ExecuteEvent(uint localID, LLUUID itemID, string FunctionName, object[] args)
|
||||
{
|
||||
|
||||
// Execute a function in the script
|
||||
m_scriptEngine.Log.Verbose("ScriptEngine", "Executing Function ObjectID: " + ObjectID + ", ScriptID: " + ScriptID + ", FunctionName: " + FunctionName);
|
||||
LSL_BaseClass Script = m_scriptEngine.myScriptManager.GetScript(ObjectID, ScriptID);
|
||||
m_scriptEngine.Log.Verbose("ScriptEngine", "Executing Function localID: " + localID + ", itemID: " + itemID + ", FunctionName: " + FunctionName);
|
||||
LSL_BaseClass Script = m_scriptEngine.myScriptManager.GetScript(localID, itemID);
|
||||
|
||||
// Must be done in correct AppDomain, so leaving it up to the script itself
|
||||
Script.Exec.ExecuteEvent(FunctionName, args);
|
||||
|
||||
Reference in New Issue
Block a user