OSSL Script Library/ModSendCommand

From OpenSimulator

Jump to: navigation, search

You can pass data back and forth between region modules and scripts using a script function called modSendCommand() which was introduced in OpenSimulator 0.6.9. This is an alternative to manually patching in new script functions. Here's an example of how to do this.

See also OSSL_Script_Library/ModInvoke for a later extension of this functionality which allows you to patch in completely new script functions from region modules.

Contents

Enabling modSendCommand()

The first thing is to enable modSendCommand() in OpenSim.ini. Make sure the line

AllowMODFunctions = true

is set to true and uncommented.

The Region Module

Secondly, we need a region module to listen for the data sent by modSendCommand() and send a reply.

using System;
using Nini.Config;
using OpenMetaverse;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;

namespace ModSendCommandExample
{
  public class MyRegionModule : IRegionModule
  {
    Scene m_scene;
    IScriptModuleComms m_commsMod;        

    public string Name { get { return "MyRegionModule"; } }
    public bool IsSharedModule { get { return false; } }
    public void Close() {}

    public void Initialise(Scene scene, IConfigSource source)
    {
       m_scene = scene;
    }

    public void PostInitialise()
    {
      m_commsMod
        = m_scene.RequestModuleInterface<IScriptModuleComms>();
      m_commsMod.OnScriptCommand += ProcessScriptCommand;
    }

    void ProcessScriptCommand(
      UUID scriptId,
      string reqId, string module, string input, string k)
    {
      if ("MYMOD" != module)
        return;

      string[] tokens
          = input.Split(
              new char[] { '|' }, StringSplitOptions.None);

      string command = tokens[0];
      switch (command)
      {
        case "Greet":
          string name = tokens[1];
          m_commsMod.DispatchReply(scriptId, 1, "Hello " + name, "");
          break;
      }
    }
  }
}

The module subscribes to the OnScriptCommand IScriptModuleComms event in PostInitialise(). When a script command event occurs, it checks that the module identifier is correct (MYMOD) and then splits the command into components delimited by a bar (|). This isn’t essential - it’s just one way of invoking arbitrary commands.

In this case, the command name is the first component. If it’s “Greet”, then a reply is sent back using the supplied name argument which is the second component.

The Region Module Revisited

This is an alternate version of the previous region module example. It addresses the new region module mechanism, which has been in place since at least 0.6.9.

Specifically the newer interface INonSharedRegionModule is being used here. The in-world script stays untouched.

using System;
using System.Reflection;
using Mono.Addins;
using Nini.Config;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using OpenMetaverse;
 
[assembly: Addin("MyRegionModule", "0.1")]
[assembly: AddinDependency("OpenSim", "0.5")]
 
namespace ModSendCommandExample
{
	[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
	public class MyRegionModule : INonSharedRegionModule
	{
		private Scene m_scene = null;
		private IScriptModuleComms m_commsMod = null;
 
		public string Name 
		{
			get {
				return "MyRegionModule";
			}
		}
 
		public Type ReplaceableInterface 
		{
			get {
				return null;
			}
		}
 
		public void Initialise(IConfigSource source) {}
 
		public void Close() {}
 
		public void AddRegion(Scene scene) 
		{
			m_scene = scene;
		}
 
		public void RemoveRegion(Scene scene) {}
 
		public void RegionLoaded(Scene scene) 
		{
			m_commsMod = m_scene.RequestModuleInterface<IScriptModuleComms>();
      		        m_commsMod.OnScriptCommand += ProcessScriptCommand;		      		
		}
 
		void ProcessScriptCommand(UUID scriptId, string reqId, string module, string input, string k)
    	        {
			if ("MYMOD" != module)
				return;
 
			string[] tokens = input.Split(new char[] { '|' }, StringSplitOptions.None);
 
			string command = tokens[0];
			switch (command)
			{
				case "Greet":
					string name = tokens[1];
					m_commsMod.DispatchReply(scriptId, 1, "Hello " + name, "");
					break;
			}
		}
 
	}
}

The In-world Script

Here’s the in-world script that makes the call and receives the reply.

default
{
  touch_start(integer total_number)
  {
    modSendCommand("MYMOD", "Greet|World", "");
  }

  link_message(integer sender_num, integer num, string message, key id)
  {
    if (sender_num == -1)
    {
      llSay(0, message);
    }
  }
}

As you can see, a touch triggers the command to the module. The script receives back the link_message event and says the data in-world.

You can download compilable region module source and script code for this example from here.

References

At the moment, this page is a simplified version of this blog post.

Another method for in-world script / region module data exchange is OSSL Script Library/ModInvoke.

Personal tools
About This Wiki