From 402ff75d781d6f4e38eee8884d7b4411bb756c9b Mon Sep 17 00:00:00 2001
From: Mic Bowman
Date: Thu, 15 Mar 2012 13:16:02 -0700
Subject: Adds a new script command 'modInvoke' to invoke registered functions
from region modules. The LSL translator is extended to generate the modInvoke
format of commands for directly inlined function calls.
A region module can register a function Test() with the name "Test".
LSL code can call that function as "Test()". The compiler will translate
that invocation into modInvoke("Test", ...)
---
.../Framework/Interfaces/IScriptModuleComms.cs | 10 ++
.../ScriptModuleComms/ScriptModuleCommsModule.cs | 99 ++++++++++++++++++-
.../Shared/Api/Implementation/MOD_Api.cs | 109 +++++++++++++++++++++
.../ScriptEngine/Shared/Api/Interface/IMOD_Api.cs | 9 ++
.../ScriptEngine/Shared/Api/Runtime/MOD_Stub.cs | 15 +++
.../Shared/CodeTools/CSCodeGenerator.cs | 28 +++++-
.../ScriptEngine/Shared/CodeTools/Compiler.cs | 5 +-
7 files changed, 270 insertions(+), 5 deletions(-)
(limited to 'OpenSim')
diff --git a/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs b/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs
index d7fa316..bb4c788 100644
--- a/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs
+++ b/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs
@@ -31,6 +31,7 @@ using OpenMetaverse;
namespace OpenSim.Region.Framework.Interfaces
{
public delegate void ScriptCommand(UUID script, string id, string module, string command, string k);
+ public delegate object ScriptInvocation(UUID script, object[] parms);
///
/// Interface for communication between OpenSim modules and in-world scripts
@@ -45,6 +46,15 @@ namespace OpenSim.Region.Framework.Interfaces
///
event ScriptCommand OnScriptCommand;
+ void RegisterScriptInvocation(string name, ScriptInvocation fn, Type[] csig, Type rsig);
+
+ ScriptInvocation LookupScriptInvocation(string fname);
+ string LookupModInvocation(string fname);
+ Type[] LookupTypeSignature(string fname);
+ Type LookupReturnType(string fname);
+
+ object InvokeOperation(UUID scriptId, string fname, params object[] parms);
+
///
/// Send a link_message event to an in-world script
///
diff --git a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
index 44c9ada..a90362e 100644
--- a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
@@ -27,6 +27,7 @@
using System;
using System.Reflection;
+using System.Collections.Generic;
using Nini.Config;
using log4net;
using OpenSim.Framework;
@@ -35,7 +36,7 @@ using OpenSim.Region.Framework.Scenes;
using Mono.Addins;
using OpenMetaverse;
-namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms
+namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms
{
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ScriptModuleCommsModule")]
class ScriptModuleCommsModule : INonSharedRegionModule, IScriptModuleComms
@@ -43,10 +44,30 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms
private static readonly ILog m_log =
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
- private IScriptModule m_scriptModule = null;
+#region ScriptInvocation
+ protected class ScriptInvocationData
+ {
+ public ScriptInvocation ScriptInvocationFn { get; private set; }
+ public string FunctionName { get; private set; }
+ public Type[] TypeSignature { get; private set; }
+ public Type ReturnType { get; private set; }
+
+ public ScriptInvocationData(string fname, ScriptInvocation fn, Type[] callsig, Type returnsig)
+ {
+ FunctionName = fname;
+ ScriptInvocationFn = fn;
+ TypeSignature = callsig;
+ ReturnType = returnsig;
+ }
+ }
+ private Dictionary m_scriptInvocation = new Dictionary();
+#endregion
+
+ private IScriptModule m_scriptModule = null;
public event ScriptCommand OnScriptCommand;
+#region RegionModuleInterface
public void Initialise(IConfigSource config)
{
}
@@ -81,6 +102,9 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms
public void Close()
{
}
+#endregion
+
+#region ScriptModuleComms
public void RaiseEvent(UUID script, string id, string module, string command, string k)
{
@@ -101,5 +125,76 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms
m_scriptModule.PostScriptEvent(script, "link_message", args);
}
+
+ public void RegisterScriptInvocation(string fname, ScriptInvocation fcall, Type[] csig, Type rsig)
+ {
+ lock (m_scriptInvocation)
+ {
+ m_scriptInvocation[fname] = new ScriptInvocationData(fname,fcall,csig,rsig);
+ }
+ }
+
+ public string LookupModInvocation(string fname)
+ {
+ lock (m_scriptInvocation)
+ {
+ ScriptInvocationData sid;
+ if (m_scriptInvocation.TryGetValue(fname,out sid))
+ {
+ if (sid.ReturnType == typeof(string))
+ return "modInvokeS";
+ else if (sid.ReturnType == typeof(int))
+ return "modInvokeI";
+ else if (sid.ReturnType == typeof(float))
+ return "modInvokeF";
+ }
+ }
+
+ return null;
+ }
+
+ public ScriptInvocation LookupScriptInvocation(string fname)
+ {
+ lock (m_scriptInvocation)
+ {
+ ScriptInvocationData sid;
+ if (m_scriptInvocation.TryGetValue(fname,out sid))
+ return sid.ScriptInvocationFn;
+ }
+
+ return null;
+ }
+
+ public Type[] LookupTypeSignature(string fname)
+ {
+ lock (m_scriptInvocation)
+ {
+ ScriptInvocationData sid;
+ if (m_scriptInvocation.TryGetValue(fname,out sid))
+ return sid.TypeSignature;
+ }
+
+ return null;
+ }
+
+ public Type LookupReturnType(string fname)
+ {
+ lock (m_scriptInvocation)
+ {
+ ScriptInvocationData sid;
+ if (m_scriptInvocation.TryGetValue(fname,out sid))
+ return sid.ReturnType;
+ }
+
+ return null;
+ }
+
+ public object InvokeOperation(UUID scriptid, string fname, params object[] parms)
+ {
+ ScriptInvocation fn = LookupScriptInvocation(fname);
+ return fn(scriptid,parms);
+ }
+#endregion
+
}
}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
index d4facdd..2942104 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
@@ -116,6 +116,115 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
wComm.DeliverMessage(ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.Name, m_host.UUID, message);
}
+ ///
+ ///
+ ///
+ /// The name of the function to invoke
+ /// List of parameters
+ /// string result of the invocation
+ public string modInvokeS(string fname, params object[] parms)
+ {
+ Type returntype = m_comms.LookupReturnType(fname);
+ if (returntype != typeof(string))
+ MODError(String.Format("return type mismatch for {0}",fname));
+
+ return (string)modInvoke(fname,parms);
+ }
+
+ public int modInvokeI(string fname, params object[] parms)
+ {
+ Type returntype = m_comms.LookupReturnType(fname);
+ if (returntype != typeof(int))
+ MODError(String.Format("return type mismatch for {0}",fname));
+
+ return (int)modInvoke(fname,parms);
+ }
+
+ public float modInvokeF(string fname, params object[] parms)
+ {
+ Type returntype = m_comms.LookupReturnType(fname);
+ if (returntype != typeof(float))
+ MODError(String.Format("return type mismatch for {0}",fname));
+
+ return (float)modInvoke(fname,parms);
+ }
+
+ ///
+ /// Invokes a preregistered function through the ScriptModuleComms class
+ ///
+ /// The name of the function to invoke
+ /// List of parameters
+ /// string result of the invocation
+ protected object modInvoke(string fname, params object[] parms)
+ {
+ if (!m_MODFunctionsEnabled)
+ {
+ MODShoutError("Module command functions not enabled");
+ return "";
+ }
+
+ Type[] signature = m_comms.LookupTypeSignature(fname);
+ if (signature.Length != parms.Length)
+ MODError(String.Format("wrong number of parameters to function {0}",fname));
+
+ object[] convertedParms = new object[parms.Length];
+
+ for (int i = 0; i < parms.Length; i++)
+ {
+ if (parms[i] is LSL_String)
+ {
+ if (signature[i] != typeof(string))
+ MODError(String.Format("parameter type mismatch in {0}; expecting {1}",fname,signature[i].Name));
+
+ convertedParms[i] = (string)(LSL_String)parms[i];
+ }
+ else if (parms[i] is LSL_Integer)
+ {
+ if (signature[i] != typeof(int))
+ MODError(String.Format("parameter type mismatch in {0}; expecting {1}",fname,signature[i].Name));
+
+ convertedParms[i] = (int)(LSL_Integer)parms[i];
+ }
+ else if (parms[i] is LSL_Float)
+ {
+ if (signature[i] != typeof(float))
+ MODError(String.Format("parameter type mismatch in {0}; expecting {1}",fname,signature[i].Name));
+
+ convertedParms[i] = (float)(LSL_Float)parms[i];
+ }
+ else if (parms[i] is LSL_Key)
+ {
+ if (signature[i] != typeof(string))
+ MODError(String.Format("parameter type mismatch in {0}; expecting {1}",fname,signature[i].Name));
+
+ convertedParms[i] = (string)(LSL_Key)parms[i];
+ }
+ else if (parms[i] is LSL_Rotation)
+ {
+ if (signature[i] != typeof(string))
+ MODError(String.Format("parameter type mismatch in {0}; expecting {1}",fname,signature[i].Name));
+
+ convertedParms[i] = (string)(LSL_Rotation)parms[i];
+ }
+ else if (parms[i] is LSL_Vector)
+ {
+ if (signature[i] != typeof(string))
+ MODError(String.Format("parameter type mismatch in {0}; expecting {1}",fname,signature[i].Name));
+
+ convertedParms[i] = (string)(LSL_Vector)parms[i];
+ }
+ else
+ {
+ if (signature[i] != parms[i].GetType())
+ MODError(String.Format("parameter type mismatch in {0}; expecting {1}",fname,signature[i].Name));
+
+ convertedParms[i] = parms[i];
+ }
+ }
+
+ return m_comms.InvokeOperation(m_itemID,fname,convertedParms);
+ }
+
public string modSendCommand(string module, string command, string k)
{
if (!m_MODFunctionsEnabled)
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IMOD_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IMOD_Api.cs
index e08eca5..756a59f 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IMOD_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IMOD_Api.cs
@@ -40,6 +40,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
{
public interface IMOD_Api
{
+ // Invocation functions
+ string modInvokeS(string fname, params object[] parms);
+ int modInvokeI(string fname, params object[] parms);
+ float modInvokeF(string fname, params object[] parms);
+ // vector modInvokeV(string fname, params object[] parms);
+ // rotation modInvokeV(string fname, params object[] parms);
+ // key modInvokeK(string fname, params object[] parms);
+ // list modInvokeL(string fname, params object[] parms);
+
//Module functions
string modSendCommand(string modules, string command, string k);
}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/MOD_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/MOD_Stub.cs
index 6525c76..04b7f14 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/MOD_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/MOD_Stub.cs
@@ -58,6 +58,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
m_MOD_Functions = (IMOD_Api)api;
}
+ public string modInvokeS(string fname, params object[] parms)
+ {
+ return m_MOD_Functions.modInvokeS(fname, parms);
+ }
+
+ public int modInvokeI(string fname, params object[] parms)
+ {
+ return m_MOD_Functions.modInvokeI(fname, parms);
+ }
+
+ public float modInvokeF(string fname, params object[] parms)
+ {
+ return m_MOD_Functions.modInvokeF(fname, parms);
+ }
+
public string modSendCommand(string module, string command, string k)
{
return m_MOD_Functions.modSendCommand(module, command, k);
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs
index 65d3b9b..28c031f 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs
@@ -32,6 +32,8 @@ using System.Reflection;
using log4net;
using Tools;
+using OpenSim.Region.Framework.Interfaces;
+
namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
{
public class CSCodeGenerator : ICodeConverter
@@ -45,12 +47,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
private int m_CSharpLine; // the current line of generated C# code
private int m_CSharpCol; // the current column of generated C# code
private List m_warnings = new List();
+ private IScriptModuleComms m_comms = null;
///
/// Creates an 'empty' CSCodeGenerator instance.
///
public CSCodeGenerator()
{
+ m_comms = null;
+ ResetCounters();
+ }
+
+ public CSCodeGenerator(IScriptModuleComms comms)
+ {
+ m_comms = comms;
ResetCounters();
}
@@ -866,8 +876,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
{
string retstr = String.Empty;
- retstr += Generate(String.Format("{0}(", CheckName(fc.Id)), fc);
-
+ string modinvoke = m_comms.LookupModInvocation(fc.Id);
+ if (modinvoke != null)
+ {
+ if (fc.kids[0] is ArgumentList)
+ {
+ if ((fc.kids[0] as ArgumentList).kids.Count == 0)
+ retstr += Generate(String.Format("{0}(\"{1}\"",modinvoke,fc.Id), fc);
+ else
+ retstr += Generate(String.Format("{0}(\"{1}\",",modinvoke,fc.Id), fc);
+ }
+ }
+ else
+ {
+ retstr += Generate(String.Format("{0}(", CheckName(fc.Id)), fc);
+ }
+
foreach (SYMBOL kid in fc.kids)
retstr += GenerateNode(kid);
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
index c10143b..8f2ec49 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
@@ -35,6 +35,7 @@ using Microsoft.CSharp;
//using Microsoft.JScript;
using Microsoft.VisualBasic;
using log4net;
+
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.ScriptEngine.Interfaces;
using OpenMetaverse;
@@ -293,6 +294,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
{
// m_log.DebugFormat("[Compiler]: Compiling script\n{0}", Script);
+ IScriptModuleComms comms = m_scriptEngine.World.RequestModuleInterface();
+
linemap = null;
m_warnings.Clear();
@@ -382,7 +385,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
if (language == enumCompileType.lsl)
{
// Its LSL, convert it to C#
- LSL_Converter = (ICodeConverter)new CSCodeGenerator();
+ LSL_Converter = (ICodeConverter)new CSCodeGenerator(comms);
compileScript = LSL_Converter.Convert(Script);
// copy converter warnings into our warnings.
--
cgit v1.1