(Untested) Scripts are individually loaded into objects (on rez), and event fired likewise. Bugfixes coming in next commit.

afrisby
Tedd Hansen 2007-08-22 18:09:38 +00:00
parent 283468caa0
commit 5a86fd2c31
8 changed files with 161 additions and 141 deletions

View File

@ -183,8 +183,6 @@ namespace OpenSim
OpenSim.Region.Environment.Scenes.Scripting.ScriptEngineInterface ScriptEngine = ScriptEngineLoader.LoadScriptEngine("DotNetEngine"); OpenSim.Region.Environment.Scenes.Scripting.ScriptEngineInterface ScriptEngine = ScriptEngineLoader.LoadScriptEngine("DotNetEngine");
scene.AddScriptEngine(ScriptEngine, m_log); scene.AddScriptEngine(ScriptEngine, m_log);
// TODO: TEMP load default script
ScriptEngine.StartScript(Path.Combine("ScriptEngines", "Default.lsl"), new OpenSim.Region.Environment.Scenes.Scripting.NullScriptHost());
//Server side object editing permissions checking //Server side object editing permissions checking
if (m_permissions) if (m_permissions)

View File

@ -38,6 +38,6 @@ namespace OpenSim.Region.Environment.Scenes.Scripting
{ {
void InitializeEngine(OpenSim.Region.Environment.Scenes.Scene Sceneworld, OpenSim.Framework.Console.LogBase logger); void InitializeEngine(OpenSim.Region.Environment.Scenes.Scene Sceneworld, OpenSim.Framework.Console.LogBase logger);
void Shutdown(); void Shutdown();
void StartScript(string ScriptID, IScriptHost ObjectID); // void StartScript(string ScriptID, IScriptHost ObjectID);
} }
} }

View File

@ -9,6 +9,7 @@ using OpenSim.Region.Environment.Scenes;
using OpenSim.Region.Environment.Scenes.Scripting; using OpenSim.Region.Environment.Scenes.Scripting;
using OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL; using OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL;
using OpenSim.Region.ScriptEngine.Common; using OpenSim.Region.ScriptEngine.Common;
using libsecondlife;
namespace OpenSim.Region.ScriptEngine.DotNetEngine namespace OpenSim.Region.ScriptEngine.DotNetEngine
{ {

View File

@ -13,39 +13,51 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL
{ {
private LSL2CSConverter LSL_Converter = new LSL2CSConverter(); private LSL2CSConverter LSL_Converter = new LSL2CSConverter();
private CSharpCodeProvider codeProvider = new CSharpCodeProvider(); private CSharpCodeProvider codeProvider = new CSharpCodeProvider();
private int ScriptCompileCounter = 0;
//private ICodeCompiler icc = codeProvider.CreateCompiler(); //private ICodeCompiler icc = codeProvider.CreateCompiler();
public string Compile(string LSOFileName) public string CompileFromFile(string LSOFileName)
{ {
// Output assembly name
string OutFile = Path.Combine("ScriptEngines", Path.GetFileNameWithoutExtension(LSOFileName) + ".dll");
//string OutFile = Path.Combine("ScriptEngines", "SecondLife.Script.dll");
Common.SendToDebug("Reading source code into memory");
// TODO: Add error handling
string CS_Code; string CS_Code;
switch (System.IO.Path.GetExtension(LSOFileName).ToLower()) switch (System.IO.Path.GetExtension(LSOFileName).ToLower())
{ {
case ".txt": case ".txt":
case ".lsl": case ".lsl":
Common.SendToDebug("Source code is LSL, converting to CS"); Common.SendToDebug("Source code is LSL, converting to CS");
CS_Code = LSL_Converter.Convert(File.ReadAllText(LSOFileName)); return CompileFromLSLText(File.ReadAllText(LSOFileName));
break;
case ".cs": case ".cs":
Common.SendToDebug("Source code is CS"); Common.SendToDebug("Source code is CS");
CS_Code = File.ReadAllText(LSOFileName); return CompileFromCSText(File.ReadAllText(LSOFileName));
break;
default: default:
throw new Exception("Unknown script type."); throw new Exception("Unknown script type.");
} }
}
/// <summary>
/// Converts script from LSL to CS and calls CompileFromCSText
/// </summary>
/// <param name="Script">LSL script</param>
/// <returns>Filename to .dll assembly</returns>
public string CompileFromLSLText(string Script)
{
return CompileFromCSText(LSL_Converter.Convert(Script));
}
/// <summary>
/// Compile CS script to .Net assembly (.dll)
/// </summary>
/// <param name="Script">CS script</param>
/// <returns>Filename to .dll assembly</returns>
public string CompileFromCSText(string Script)
{
Common.SendToDebug("Compiling");
// Output assembly name
ScriptCompileCounter++;
string OutFile = Path.Combine("ScriptEngines", "Script_" + ScriptCompileCounter + ".dll");
//string OutFile = Path.Combine("ScriptEngines", "SecondLife.Script.dll");
// DEBUG - write source to disk // DEBUG - write source to disk
try try
{ {
File.WriteAllText(Path.Combine("ScriptEngines", "debug_" + Path.GetFileNameWithoutExtension(LSOFileName) + ".cs"), CS_Code); File.WriteAllText(Path.Combine("ScriptEngines", "debug_" + Path.GetFileNameWithoutExtension(OutFile) + ".cs"), Script);
} }
catch { } catch { }
@ -68,7 +80,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL
//parameters.ReferencedAssemblies.Add("OpenSim.Region.Environment"); //parameters.ReferencedAssemblies.Add("OpenSim.Region.Environment");
parameters.GenerateExecutable = false; parameters.GenerateExecutable = false;
parameters.OutputAssembly = OutFile; parameters.OutputAssembly = OutFile;
CompilerResults results = codeProvider.CompileAssemblyFromSource(parameters, CS_Code); CompilerResults results = codeProvider.CompileAssemblyFromSource(parameters, Script);
// Go through errors // Go through errors
// TODO: Return errors to user somehow // TODO: Return errors to user somehow

View File

@ -42,7 +42,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
class EventManager class EventManager
{ {
private ScriptEngine myScriptEngine; private ScriptEngine myScriptEngine;
public IScriptHost TEMP_OBJECT_ID; //public IScriptHost TEMP_OBJECT_ID;
public EventManager(ScriptEngine _ScriptEngine) public EventManager(ScriptEngine _ScriptEngine)
{ {
myScriptEngine = _ScriptEngine; myScriptEngine = _ScriptEngine;
@ -51,19 +51,47 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
// TODO: ADD SERVER HOOK TO LOAD A SCRIPT THROUGH myScriptEngine.ScriptManager // TODO: ADD SERVER HOOK TO LOAD A SCRIPT THROUGH myScriptEngine.ScriptManager
// Hook up a test event to our test form // Hook up a test event to our test form
myScriptEngine.Log.Verbose("ScriptEngine", "EventManager Hooking up dummy-event: touch_start"); //myScriptEngine.Log.Verbose("ScriptEngine", "EventManager Hooking up to server events");
// TODO: REPLACE THIS WITH A REAL TOUCH_START EVENT IN SERVER
myScriptEngine.World.EventManager.OnObjectGrab += new OpenSim.Region.Environment.Scenes.EventManager.ObjectGrabDelegate(touch_start); myScriptEngine.World.EventManager.OnObjectGrab += new OpenSim.Region.Environment.Scenes.EventManager.ObjectGrabDelegate(touch_start);
//myScriptEngine.World.touch_start += new TempWorldInterfaceEventDelegates.touch_start(touch_start); myScriptEngine.World.EventManager.OnRezScript += new OpenSim.Region.Environment.Scenes.EventManager.NewRezScript(OnRezScript);
} }
public void touch_start(uint localID, LLVector3 offsetPos, IClientAPI remoteClient) public void touch_start(uint localID, LLVector3 offsetPos, IClientAPI remoteClient)
{ {
// Add to queue for all scripts in ObjectID object // Add to queue for all scripts in ObjectID object
//myScriptEngine.m_logger.Verbose("ScriptEngine", "EventManager Event: touch_start"); //myScriptEngine.m_logger.Verbose("ScriptEngine", "EventManager Event: touch_start");
myScriptEngine.myEventQueueManager.AddToObjectQueue(TEMP_OBJECT_ID, "touch_start", new object[] { (int)0 }); myScriptEngine.myEventQueueManager.AddToObjectQueue(localID, "touch_start", new object[] { (int)1 });
} }
public void OnRezScript(uint localID, LLUUID itemID, string script)
{
// TODO: Add code to compile script and wire up script to object
// Either the script is a stand-alone entity with a reference to public host,
// Or the host has a reference to the script because it was in its inventory.
//myScriptEngine.myScriptManager.StartScript(
// Path.Combine("ScriptEngines", "Default.lsl"),
// new OpenSim.Region.Environment.Scenes.Scripting.NullScriptHost()
//);
myScriptEngine.myScriptManager.StartScript(
localID,
itemID,
script
);
}
public void OnDeRezScript(uint localID, LLUUID itemID)
{
//myScriptEngine.myScriptManager.StartScript(
// Path.Combine("ScriptEngines", "Default.lsl"),
// new OpenSim.Region.Environment.Scenes.Scripting.NullScriptHost()
//);
myScriptEngine.myScriptManager.StopScript(
localID,
itemID
);
}
// TODO: Replace placeholders below // TODO: Replace placeholders below
// These needs to be hooked up to OpenSim during init of this class // These needs to be hooked up to OpenSim during init of this class

View File

@ -32,6 +32,7 @@ using System.Text;
using System.Threading; using System.Threading;
using System.Reflection; using System.Reflection;
using OpenSim.Region.Environment.Scenes.Scripting; using OpenSim.Region.Environment.Scenes.Scripting;
using libsecondlife;
namespace OpenSim.Region.ScriptEngine.DotNetEngine namespace OpenSim.Region.ScriptEngine.DotNetEngine
{ {
@ -64,16 +65,16 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
/// </summary> /// </summary>
private struct QueueItemStruct private struct QueueItemStruct
{ {
public IScriptHost ObjectID; public uint localID;
public string ScriptID; public LLUUID itemID;
public string FunctionName; public string FunctionName;
public object[] param; public object[] param;
} }
/// <summary> /// <summary>
/// List of ObjectID locks for mutex processing of script events /// List of localID locks for mutex processing of script events
/// </summary> /// </summary>
private List<IScriptHost> ObjectLocks = new List<IScriptHost>(); private List<uint> ObjectLocks = new List<uint>();
private object TryLockLock = new object(); // Mutex lock object private object TryLockLock = new object(); // Mutex lock object
private ScriptEngine myScriptEngine; private ScriptEngine myScriptEngine;
@ -140,7 +141,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
else else
{ {
// Something in queue, process // Something in queue, process
//myScriptEngine.m_logger.Verbose("ScriptEngine", "Processing event for ObjectID: " + QIS.ObjectID + ", ScriptID: " + QIS.ScriptID + ", FunctionName: " + QIS.FunctionName); //myScriptEngine.m_logger.Verbose("ScriptEngine", "Processing event for localID: " + QIS.localID + ", itemID: " + QIS.itemID + ", FunctionName: " + QIS.FunctionName);
// OBJECT BASED LOCK - TWO THREADS WORKING ON SAME OBJECT IS NOT GOOD // OBJECT BASED LOCK - TWO THREADS WORKING ON SAME OBJECT IS NOT GOOD
lock (QueueLock) lock (QueueLock)
@ -152,7 +153,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
QIS = EventQueue.Dequeue(); QIS = EventQueue.Dequeue();
// Check if object is being processed by someone else // Check if object is being processed by someone else
if (TryLock(QIS.ObjectID) == false) if (TryLock(QIS.localID) == false)
{ {
// Object is already being processed, requeue it // Object is already being processed, requeue it
EventQueue.Enqueue(QIS); EventQueue.Enqueue(QIS);
@ -169,8 +170,14 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
if (GotItem == true) if (GotItem == true)
{ {
// Execute function // Execute function
myScriptEngine.myScriptManager.ExecuteEvent(QIS.ObjectID, QIS.ScriptID, QIS.FunctionName, QIS.param); try
ReleaseLock(QIS.ObjectID); {
myScriptEngine.myScriptManager.ExecuteEvent(QIS.localID, QIS.itemID, QIS.FunctionName, QIS.param);
}
finally
{
ReleaseLock(QIS.localID);
}
} }
} // Something in queue } // Something in queue
@ -183,37 +190,37 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
} }
/// <summary> /// <summary>
/// Try to get a mutex lock on ObjectID /// Try to get a mutex lock on localID
/// </summary> /// </summary>
/// <param name="ObjectID"></param> /// <param name="localID"></param>
/// <returns></returns> /// <returns></returns>
private bool TryLock(IScriptHost ObjectID) private bool TryLock(uint localID)
{ {
lock (TryLockLock) lock (TryLockLock)
{ {
if (ObjectLocks.Contains(ObjectID) == true) if (ObjectLocks.Contains(localID) == true)
{ {
return false; return false;
} }
else else
{ {
ObjectLocks.Add(ObjectID); ObjectLocks.Add(localID);
return true; return true;
} }
} }
} }
/// <summary> /// <summary>
/// Release mutex lock on ObjectID /// Release mutex lock on localID
/// </summary> /// </summary>
/// <param name="ObjectID"></param> /// <param name="localID"></param>
private void ReleaseLock(IScriptHost ObjectID) private void ReleaseLock(uint localID)
{ {
lock (TryLockLock) lock (TryLockLock)
{ {
if (ObjectLocks.Contains(ObjectID) == true) if (ObjectLocks.Contains(localID) == true)
{ {
ObjectLocks.Remove(ObjectID); ObjectLocks.Remove(localID);
} }
} }
} }
@ -221,26 +228,26 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
/// <summary> /// <summary>
/// Add event to event execution queue /// Add event to event execution queue
/// </summary> /// </summary>
/// <param name="ObjectID"></param> /// <param name="localID"></param>
/// <param name="FunctionName">Name of the function, will be state + "_event_" + FunctionName</param> /// <param name="FunctionName">Name of the function, will be state + "_event_" + FunctionName</param>
/// <param name="param">Array of parameters to match event mask</param> /// <param name="param">Array of parameters to match event mask</param>
public void AddToObjectQueue(IScriptHost ObjectID, string FunctionName, object[] param) public void AddToObjectQueue(uint localID, string FunctionName, object[] param)
{ {
// Determine all scripts in Object and add to their queue // Determine all scripts in Object and add to their queue
//myScriptEngine.m_logger.Verbose("ScriptEngine", "EventQueueManager Adding ObjectID: " + ObjectID + ", FunctionName: " + FunctionName); //myScriptEngine.m_logger.Verbose("ScriptEngine", "EventQueueManager Adding localID: " + localID + ", FunctionName: " + FunctionName);
lock (QueueLock) lock (QueueLock)
{ {
foreach (string ScriptID in myScriptEngine.myScriptManager.GetScriptKeys(ObjectID)) foreach (LLUUID itemID in myScriptEngine.myScriptManager.GetScriptKeys(localID))
{ {
// Add to each script in that object // Add to each script in that object
// TODO: Some scripts may not subscribe to this event. Should we NOT add it? Does it matter? // TODO: Some scripts may not subscribe to this event. Should we NOT add it? Does it matter?
// Create a structure and add data // Create a structure and add data
QueueItemStruct QIS = new QueueItemStruct(); QueueItemStruct QIS = new QueueItemStruct();
QIS.ObjectID = ObjectID; QIS.localID = localID;
QIS.ScriptID = ScriptID; QIS.itemID = itemID;
QIS.FunctionName = FunctionName; QIS.FunctionName = FunctionName;
QIS.param = param; QIS.param = param;

View File

@ -64,9 +64,12 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
public void InitializeEngine(OpenSim.Region.Environment.Scenes.Scene Sceneworld, OpenSim.Framework.Console.LogBase logger) public void InitializeEngine(OpenSim.Region.Environment.Scenes.Scene Sceneworld, OpenSim.Framework.Console.LogBase logger)
{ {
World = Sceneworld; World = Sceneworld;
m_log = logger; m_log = logger;
Log.Verbose("ScriptEngine", "DotNet & LSL ScriptEngine initializing");
//m_logger.Status("ScriptEngine", "InitializeEngine"); //m_logger.Status("ScriptEngine", "InitializeEngine");
// Create all objects we'll be using // Create all objects we'll be using
@ -78,30 +81,21 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
// Should we iterate the region for scripts that needs starting? // Should we iterate the region for scripts that needs starting?
// Or can we assume we are loaded before anything else so we can use proper events? // Or can we assume we are loaded before anything else so we can use proper events?
// Event hook for when scripts are dragged to script inventory
World.EventManager.OnRezScript += NewRezScriptHandler;
} }
private void NewRezScriptHandler(uint localID, LLUUID itemID, string script)
{
// TODO: Add code to compile script and wire up script to object
// Either the script is a stand-alone entity with a reference to public host,
// Or the host has a reference to the script because it was in its inventory.
}
public void Shutdown() public void Shutdown()
{ {
// We are shutting down // We are shutting down
} }
// !!!FOR DEBUGGING ONLY!!! (for executing script directly from test app) //// !!!FOR DEBUGGING ONLY!!! (for executing script directly from test app)
[Obsolete("!!!FOR DEBUGGING ONLY!!!")] //[Obsolete("!!!FOR DEBUGGING ONLY!!!")]
public void StartScript(string ScriptID, IScriptHost ObjectID) //public void StartScript(string ScriptID, IScriptHost ObjectID)
{ //{
this.myEventManager.TEMP_OBJECT_ID = ObjectID; // this.myEventManager.TEMP_OBJECT_ID = ObjectID;
Log.Status("ScriptEngine", "DEBUG FUNCTION: StartScript: " + ScriptID); // Log.Status("ScriptEngine", "DEBUG FUNCTION: StartScript: " + ScriptID);
myScriptManager.StartScript(ScriptID, ObjectID); // myScriptManager.StartScript(ScriptID, ObjectID);
} //}
} }
} }

View File

@ -37,6 +37,7 @@ using OpenSim.Region.Environment.Scenes.Scripting;
using OpenSim.Region.ScriptEngine.DotNetEngine.Compiler; using OpenSim.Region.ScriptEngine.DotNetEngine.Compiler;
using OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL; using OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL;
using OpenSim.Region.ScriptEngine.Common; using OpenSim.Region.ScriptEngine.Common;
using libsecondlife;
namespace OpenSim.Region.ScriptEngine.DotNetEngine namespace OpenSim.Region.ScriptEngine.DotNetEngine
{ {
@ -53,7 +54,6 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
public ScriptManager(ScriptEngine scriptEngine) public ScriptManager(ScriptEngine scriptEngine)
{ {
m_scriptEngine = scriptEngine; m_scriptEngine = scriptEngine;
m_scriptEngine.Log.Verbose("ScriptEngine", "ScriptManager Start");
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve); AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
} }
@ -69,7 +69,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
// Object<string, Script<string, script>> // Object<string, Script<string, script>>
// IMPORTANT: Types and MemberInfo-derived objects require a LOT of memory. // IMPORTANT: Types and MemberInfo-derived objects require a LOT of memory.
// Instead use RuntimeTypeHandle, RuntimeFieldHandle and RunTimeHandle (IntPtr) instead! // 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 public Scene World
{ {
get 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; return null;
Dictionary<string, LSL_BaseClass> Obj; Dictionary<LLUUID, LSL_BaseClass> Obj;
Scripts.TryGetValue(ObjectID, out Obj); Scripts.TryGetValue(localID, out Obj);
return Obj.Keys; 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; return null;
Dictionary<string, LSL_BaseClass> Obj; Dictionary<LLUUID, LSL_BaseClass> Obj;
Scripts.TryGetValue(ObjectID, out Obj); Scripts.TryGetValue(localID, out Obj);
if (Obj.ContainsKey(ScriptID) == false) if (Obj.ContainsKey(itemID) == false)
return null; return null;
// Get script // Get script
LSL_BaseClass Script; LSL_BaseClass Script;
Obj.TryGetValue(ScriptID, out Script); Obj.TryGetValue(itemID, out Script);
return 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 // 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 // Delete script if it exists
Dictionary<string, LSL_BaseClass> Obj; Dictionary<LLUUID, LSL_BaseClass> Obj;
Scripts.TryGetValue(ObjectID, out Obj); Scripts.TryGetValue(localID, out Obj);
if (Obj.ContainsKey(ScriptID) == true) if (Obj.ContainsKey(itemID) == true)
Obj.Remove(ScriptID); Obj.Remove(itemID);
// Add to object // 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? // Don't have that object?
if (Scripts.ContainsKey(ObjectID) == false) if (Scripts.ContainsKey(localID) == false)
return; return;
// Delete script if it exists // Delete script if it exists
Dictionary<string, LSL_BaseClass> Obj; Dictionary<LLUUID, LSL_BaseClass> Obj;
Scripts.TryGetValue(ObjectID, out Obj); Scripts.TryGetValue(localID, out Obj);
if (Obj.ContainsKey(ScriptID) == true) if (Obj.ContainsKey(itemID) == true)
Obj.Remove(ScriptID); Obj.Remove(itemID);
} }
/// <summary> /// <summary>
/// Fetches, loads and hooks up a script to an objects events /// Fetches, loads and hooks up a script to an objects events
/// </summary> /// </summary>
/// <param name="ScriptID"></param> /// <param name="itemID"></param>
/// <param name="ObjectID"></param> /// <param name="localID"></param>
public void StartScript(string ScriptID, IScriptHost ObjectID) public void StartScript(uint localID, LLUUID itemID, string Script)
{ {
//IScriptHost root = host.GetRoot(); //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. // We will initialize and start the script.
// It will be up to the script itself to hook up the correct events. // 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) // 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(); OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.Compiler LSLCompiler = new OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.Compiler();
// Compile // Compile (We assume LSL)
FileName = LSLCompiler.Compile(FileName); FileName = LSLCompiler.CompileFromLSLText(Script);
break; m_scriptEngine.Log.Verbose("ScriptEngine", "Compilation of " + FileName + " done");
default:
throw new Exception("Unknown script type.");
}
m_scriptEngine.Log.Verbose("ScriptEngine", "Compilation done");
// * Insert yield into code // * Insert yield into code
FileName = ProcessYield(FileName); FileName = ProcessYield(FileName);
//OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSO.LSL_BaseClass Script = LoadAndInitAssembly(FreeAppDomain, 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; long before;
before = GC.GetTotalMemory(true); before = GC.GetTotalMemory(true);
LSL_BaseClass Script = m_scriptEngine.myAppDomainManager.LoadScript(FileName); LSL_BaseClass CompiledScript = m_scriptEngine.myAppDomainManager.LoadScript(FileName);
Console.WriteLine("Script occupies {0} bytes", GC.GetTotalMemory(true) - before); Console.WriteLine("Script " + itemID + " occupies {0} bytes", GC.GetTotalMemory(true) - before);
before = GC.GetTotalMemory(true); before = GC.GetTotalMemory(true);
Script = m_scriptEngine.myAppDomainManager.LoadScript(FileName); //Script = m_scriptEngine.myAppDomainManager.LoadScript(FileName);
Console.WriteLine("Script occupies {0} bytes", GC.GetTotalMemory(true) - before); //Console.WriteLine("Script occupies {0} bytes", GC.GetTotalMemory(true) - before);
//before = GC.GetTotalMemory(true); //before = GC.GetTotalMemory(true);
//Script = m_scriptEngine.myAppDomainManager.LoadScript(FileName); //Script = m_scriptEngine.myAppDomainManager.LoadScript(FileName);
//Console.WriteLine("Script occupies {0} bytes", GC.GetTotalMemory(true) - before); //Console.WriteLine("Script occupies {0} bytes", GC.GetTotalMemory(true) - before);
// Add it to our temporary active script keeper // Add it to our temporary active script keeper
//Scripts.Add(FullScriptID, Script); //Scripts.Add(FullitemID, Script);
SetScript(ObjectID, ScriptID, Script); SetScript(localID, itemID, CompiledScript);
// We need to give (untrusted) assembly a private instance of BuiltIns // 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. // 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, ObjectID); LSL_BuiltIn_Commands LSLB = new LSL_BuiltIn_Commands(this, World.GetSceneObjectPart(localID));
// Start the script - giving it BuiltIns // Start the script - giving it BuiltIns
Script.Start(LSLB); CompiledScript.Start(LSLB);
} }
catch (Exception e) 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 // Stop script
// Get AppDomain // Get AppDomain
AppDomain ad = GetScript(ObjectID, ScriptID).Exec.GetAppDomain(); AppDomain ad = GetScript(localID, itemID).Exec.GetAppDomain();
// Tell script not to accept new requests // Tell script not to accept new requests
GetScript(ObjectID, ScriptID).Exec.StopScript(); GetScript(localID, itemID).Exec.StopScript();
// Remove from internal structure // Remove from internal structure
RemoveScript(ObjectID, ScriptID); RemoveScript(localID, itemID);
// Tell AppDomain that we have stopped script // Tell AppDomain that we have stopped script
m_scriptEngine.myAppDomainManager.StopScript(ad); m_scriptEngine.myAppDomainManager.StopScript(ad);
} }
@ -244,16 +224,16 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
/// <summary> /// <summary>
/// Execute a LL-event-function in Script /// Execute a LL-event-function in Script
/// </summary> /// </summary>
/// <param name="ObjectID">Object the script is located in</param> /// <param name="localID">Object the script is located in</param>
/// <param name="ScriptID">Script ID</param> /// <param name="itemID">Script ID</param>
/// <param name="FunctionName">Name of function</param> /// <param name="FunctionName">Name of function</param>
/// <param name="args">Arguments to pass to 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 // Execute a function in the script
m_scriptEngine.Log.Verbose("ScriptEngine", "Executing Function ObjectID: " + ObjectID + ", ScriptID: " + ScriptID + ", FunctionName: " + FunctionName); m_scriptEngine.Log.Verbose("ScriptEngine", "Executing Function localID: " + localID + ", itemID: " + itemID + ", FunctionName: " + FunctionName);
LSL_BaseClass Script = m_scriptEngine.myScriptManager.GetScript(ObjectID, ScriptID); LSL_BaseClass Script = m_scriptEngine.myScriptManager.GetScript(localID, itemID);
// Must be done in correct AppDomain, so leaving it up to the script itself // Must be done in correct AppDomain, so leaving it up to the script itself
Script.Exec.ExecuteEvent(FunctionName, args); Script.Exec.ExecuteEvent(FunctionName, args);