29 using System.Reflection;
30 using System.Collections.Generic;
33 using OpenSim.Framework;
34 using OpenSim.Region.Framework.Interfaces;
35 using OpenSim.Region.Framework.Scenes;
39 using System.Linq.Expressions;
43 [Extension(Path =
"/OpenSim/RegionModules", NodeName =
"RegionModule", Id =
"ScriptModuleCommsModule")]
46 private static readonly ILog m_log =
47 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 private static string LogHeader =
"[MODULE COMMS]";
50 private Dictionary<string,object> m_constants =
new Dictionary<string,object>();
52 #region ScriptInvocation
55 public Delegate ScriptInvocationDelegate {
get;
private set; }
56 public string FunctionName {
get;
private set; }
57 public Type[] TypeSignature {
get;
private set; }
58 public Type ReturnType {
get;
private set; }
63 ScriptInvocationDelegate = fn;
64 TypeSignature = callsig;
65 ReturnType = returnsig;
69 private Dictionary<string,ScriptInvocationData> m_scriptInvocation =
new Dictionary<string,ScriptInvocationData>();
75 #region RegionModuleInterface
91 m_scriptModule = scene.RequestModuleInterface<
IScriptModule>();
93 if (m_scriptModule != null)
94 m_log.Info(
"[MODULE COMMANDS]: Script engine found, module active");
99 get {
return "ScriptModuleCommsModule"; }
102 public Type ReplaceableInterface
112 #region ScriptModuleComms
114 public void RaiseEvent(UUID script,
string id,
string module,
string command,
string k)
121 c(script,
id, module, command, k);
126 if (m_scriptModule == null)
131 m_scriptModule.PostScriptEvent(script,
"link_message", args);
134 private static MethodInfo GetMethodInfoFromType(Type target,
string meth,
bool searchInstanceMethods)
136 BindingFlags getMethodFlags =
137 BindingFlags.NonPublic | BindingFlags.Public;
139 if (searchInstanceMethods)
140 getMethodFlags |= BindingFlags.Instance;
142 getMethodFlags |= BindingFlags.Static;
144 return target.GetMethod(meth, getMethodFlags);
149 MethodInfo mi = GetMethodInfoFromType(target.GetType(), meth,
true);
152 m_log.WarnFormat(
"{0} Failed to register method {1}", LogHeader, meth);
156 RegisterScriptInvocation(target, mi);
161 foreach (
string m
in meth)
162 RegisterScriptInvocation(target, m);
169 Type delegateType = typeof(
void);
170 List<Type> typeArgs = mi.GetParameters()
171 .Select(p => p.ParameterType)
174 if (mi.ReturnType == typeof(
void))
176 delegateType = Expression.GetActionType(typeArgs.ToArray());
182 typeArgs.Add(mi.ReturnType);
183 delegateType = Expression.GetFuncType(typeArgs.ToArray());
187 m_log.ErrorFormat(
"{0} Failed to create function signature. Most likely more than 5 parameters. Method={1}. Error={2}",
188 LogHeader, mi.Name, e);
193 if (!(target is
Type))
194 fcall = Delegate.CreateDelegate(delegateType, target, mi);
196 fcall = Delegate.CreateDelegate(delegateType, (Type)target, mi.Name);
198 lock (m_scriptInvocation)
200 ParameterInfo[] parameters = fcall.Method.GetParameters();
201 if (parameters.Length < 2)
205 Type[] parmTypes =
new Type[parameters.Length - 2];
206 for (
int i = 2; i < parameters.Length; i++)
207 parmTypes[i - 2] = parameters[i].ParameterType;
208 m_scriptInvocation[fcall.Method.Name] =
new ScriptInvocationData(fcall.Method.Name, fcall, parmTypes, fcall.Method.ReturnType);
214 foreach (
string method
in methods)
216 MethodInfo mi = GetMethodInfoFromType(target, method,
false);
218 m_log.WarnFormat(
"[MODULE COMMANDS] Failed to register method {0}", method);
220 RegisterScriptInvocation(target, mi);
226 foreach(MethodInfo method
in target.GetType().GetMethods(
227 BindingFlags.Public | BindingFlags.Instance |
228 BindingFlags.Static))
230 if(method.GetCustomAttributes(
234 RegisterScriptInvocation(target.GetType(), method);
236 RegisterScriptInvocation(target, method);
243 List<Delegate> ret =
new List<Delegate>();
245 lock (m_scriptInvocation)
248 ret.Add(d.ScriptInvocationDelegate);
250 return ret.ToArray();
255 lock (m_scriptInvocation)
258 if (m_scriptInvocation.TryGetValue(fname,out sid))
260 if (sid.ReturnType == typeof(
string))
262 else if (sid.ReturnType == typeof(
int))
264 else if (sid.ReturnType == typeof(
float))
266 else if (sid.ReturnType == typeof(
UUID))
268 else if (sid.ReturnType == typeof(OpenMetaverse.Vector3))
270 else if (sid.ReturnType == typeof(OpenMetaverse.Quaternion))
272 else if (sid.ReturnType == typeof(
object[]))
274 else if (sid.ReturnType == typeof(
void))
277 m_log.WarnFormat(
"[MODULE COMMANDS] failed to find match for {0} with return type {1}",fname,sid.ReturnType.Name);
286 lock (m_scriptInvocation)
289 if (m_scriptInvocation.TryGetValue(fname,out sid))
298 lock (m_scriptInvocation)
301 if (m_scriptInvocation.TryGetValue(fname,out sid))
310 lock (m_scriptInvocation)
313 if (m_scriptInvocation.TryGetValue(fname,out sid))
320 public object InvokeOperation(UUID hostid, UUID scriptid,
string fname, params
object[] parms)
322 List<object> olist =
new List<object>();
325 foreach (
object o
in parms)
327 Delegate fn = LookupScriptInvocation(fname);
328 return fn.DynamicInvoke(olist.ToArray());
340 m_constants.Add(cname,value);
346 foreach (FieldInfo field
in target.GetType().GetFields(
347 BindingFlags.Public | BindingFlags.Static |
348 BindingFlags.Instance))
350 if (field.GetCustomAttributes(
353 RegisterConstant(field.Name, field.GetValue(target));
368 if (m_constants.TryGetValue(cname,out value))
380 Dictionary<string, object> ret =
new Dictionary<string, object>();
384 foreach (KeyValuePair<string, object> kvp
in m_constants)
385 ret[kvp.Key] = kvp.Value;
delegate void ScriptCommand(UUID script, string id, string module, string command, string k)
void AddRegion(Scene scene)
This is called whenever a Scene is added. For shared modules, this can happen several times...
Delegate[] GetScriptInvocationList()
Returns an array of all registered script calls
void RegisterConstants(IRegionModuleBase target)
Automatically register all constants on a region module by checking for fields with ScriptConstantAtt...
Delegate LookupScriptInvocation(string fname)
object InvokeOperation(UUID hostid, UUID scriptid, string fname, params object[] parms)
Type[] LookupTypeSignature(string fname)
object LookupModConstant(string cname)
Operation to check for a registered constant
void RegisterConstant(string cname, object value)
Operation to for a region module to register a constant to be used by the script engine ...
void Initialise(IConfigSource config)
This is called to initialize the region module. For shared modules, this is called exactly once...
void RemoveRegion(Scene scene)
This is called whenever a Scene is removed. For shared modules, this can happen several times...
ScriptCommand OnScriptCommand
void RaiseEvent(UUID script, string id, string module, string command, string k)
void RegionLoaded(Scene scene)
This will be called once for every scene loaded. In a shared module this will be multiple times in on...
void RegisterScriptInvocation(Type target, string[] methods)
Register one or more static methods as script calls by method name
Delegate ScriptInvocationDelegate
string LookupModInvocation(string fname)
void RegisterScriptInvocation(object target, string[] meth)
Register one or more instance methods as script calls by method name
Interface for communication between OpenSim modules and in-world scripts
Type LookupReturnType(string fname)
Interactive OpenSim region server
void DispatchReply(UUID script, int code, string text, string k)
Send a link_message event to an in-world script
void Close()
This is the inverse to Initialise. After a Close(), this instance won't be usable anymore...
void RegisterScriptInvocations(IRegionModuleBase target)
Automatically register script invocations by checking for methods with ScriptInvocationAttribute. Should only check public methods.
void RegisterScriptInvocation(object target, MethodInfo mi)
Register a static or instance method as a script call by method info
void RegisterScriptInvocation(object target, string meth)
Register an instance method as a script call by method name
Dictionary< string, object > GetConstants()
Get all registered constants
ScriptInvocationData(string fname, Delegate fn, Type[] callsig, Type returnsig)