C# scripting in OpenSim

Friday, November 21, 2008
By justincc

c-script-small2A month ago, I wrote a short article about how to add an OSSL (OpenSimulator Scripting Language) function to OpenSim. This assumed that you were writing a script using the Linden Scripting Language (LSL).

However, in principle LSL is not the only language that you can write scripts in for OpenSim.  LSL scripts in OpenSim are actually translated into C# before being compiled and executed.  Therefore, it’s possible to bypass LSL and instead write in C# directly (or in Visual Basic, Javascript or any language which has a .net compiler that can be added to OpenSim).  Indeed, some OSSL functions (such as osParseJSON()) will not currently work in LSL at all - the data it returns cannot be easily stuffed into any LSL data type.  Unfortunately, there is a

major caveat with allowing OpenSim to directly execute C# and other non-LSL scripts.  We’ll cover this later on.

But first of all, how does one write and execute a C# script in OpenSim?  The first step is to make sure that OpenSim is allowed to compile C#.  In your OpenSim.ini file, you will need the entry

AllowedCompilers = lsl, cs

in either the [ScriptEngine.DotNetEngine] or [XEngine] sections depending on which script engine your using (or both, if you want to be sure).

Now that this is done, we can enter a C# script.  Here is a very short example.

//c#
// justincc's short test script

string message = "Hello avatar!";
string xml = "<tag>ribbit</tag>";

public void default_event_state_entry()
{
    llSay(0, message);
}

public void default_event_touch_start(
    LSL_Types.LSLInteger total_number)
{
    System.IO.StringReader sr
        = new System.IO.StringReader(xml);
    System.Xml.XmlTextReader reader
        = new System.Xml.XmlTextReader(sr);

    llSay(0, reader.ReadElementString("tag"));
}

You can copy and paste this into a normal Second Life script within OpenSim.

As you can see, the structure is quite different from that of an LSL script.  The first line

//c#

is always required to tell OpenSim that the script should be compiled as a C# script.  WIthout this, the LSL compiler would be used instead (unless you’ve changed the default compiler in OpenSim.ini).

In the subsequent lines you can see that we don’t have the ‘default’ state section that one would find in an LSL script.  Instead, the functions that receive events need to have names in the format <state>_event_<event function>.  For instance,


state_entry() in the default state an LSL script
becomes public void default_event_state_entry().

touch_start(integer total_number)
becomes default_event_touch_start(LSLType.LSLInteger total_number).

We need to use LSLType.LSLInteger instead of C#’s int since this is the method signature that the script engine expects).

There is a more complex example of a C# script that uses osParseJSON() here.

So what are the advantages of writing scripts directly in C#?  The major one is that one gets can use the .NET APIs directly.  We can’t use C#’s using directives in the script so they need to be accessed using their full names (e.g. System.IO.StringReader rather than StringReader).  Among other things, this allows one to use much richer data types in C# that aren’t available in LSL, such as System.Collections.Generic.Dictionary.  One could also do such things as parsing XML using .NET (or mono’s) bundled XML parsers, as shown in the example above.

However, this advantage also forms C# scripting’s current major weakness.  At the moment, as well being able to use such helpful classes as System.Collections.Generic.Dictionary, it’s also possible to call methods such as System.File.IO.Delete(”path/to/really/important/system/file”).  Mantis 2610 has some more details of why this is.  Hopefully, this can be fixed at some stage, but at the moment I would have to recommend that you don’t enable C# scripting on a server unless you really, really, really trust everybody who has access to it.

Alternatively, one may also be able to prevent non-administrators from creating or editing scripts at all.  I hope to write about this at a later date, though these OpenSim facilities are still very experimental.

30 Responses to “C# scripting in OpenSim”

  1. Robert

    AllowedCompilers = lsl,cs
    doesn’t work in OpenSimulator Server 0.6.1.8108

    I am getting error: “Primitive: Error compiling script:
    The compiler for language “cs” is not in list of allowed compilers. Script will not be executed!”

    #156
  2. @Robert - Perhaps you could post (if it’s small) or e-mail me your script and I can give it a quick try?

    #157
  3. Linda

    So where do we go from here? Is there any documentation eg. how to set a LSLType.LSLList variable in C#? Are all events named consistantly (eg default_event_sensor, default_event_link_message)?

    Linda

    #164
  4. @Linda - this is a problem, afaik there is no wiki documentation on this at the moment.

    #165
  5. Linda

    So how did you learn to use something like LSL_Types.LSLInteger? :)
    Linda

    #166
  6. Good question :) As far as I remember, this was mainly from looking at some previous code examples such as Rob Smart’s osParseJSON() demonstration code at

    http://robsmart.co.uk/2008/09/14/opensim-web-20-contribution/

    In addition, I did some direct experimentation with OpenSim. There is a setting in OpenSim.ini which will save out the C# code of any script, which should be useful in working some stuff out. Also, you can use the knowledge that all compiled scripts have LSL_Stub.cs as a base class (and hence effectively just call classes and methods referenced there).

    #167
  7. Linda

    Thanks, I will look into that :)
    Linda

    #168
  8. Starky Rubble

    I have been playing with this today.

    I started by setting the flag in the DotNetEngine block of the ini file that writes out the C# that LSL is converted to before compiling:
    WriteScriptSourceToDebugFile=true

    Then each time you compile an LSL script a C# source is stored in your /bin/ScriptEngines folder.

    Here is what NewScript looks like in that file:
    using OpenSim.Region.ScriptEngine.Shared;
    using System.Collections.Generic;
    namespace SecondLife
    {
    public class Script : OpenSim.Region.ScriptEngine.Shared.ScriptBase.ScriptBaseClass
    {
    public Script()
    {
    }

    public void default_event_state_entry()
    {
    llSay(new LSL_Types.LSLInteger(0), new LSL_Types.LSLString(”Script running”));
    }
    }
    }

    Here is the eqivalent compilable C# New Script
    //c#

    public void default_event_state_entry()
    {
    llSay(0, “Script running”);
    }

    using the LSL types as shown in the generated code may be better - I am not the one to ask about that.

    #162
  9. Cliff

    So how do you get c# scripts to work.

    I am using Open Simulator 0.6.3.8730 and using JJ sample script I am getting the following error:

    Primitive: Error compiling script:
    Line (16,11): Error CS0234: The type or namespace name ‘Xml’ does not exist in the namespace ‘System’ (are you missing an assembly reference?)
    Line (17,21): Error CS0234: The type or namespace name ‘Xml’ does not exist in the namespace ‘System’ (are you missing an assembly reference?)

    Ini settings:-

    DefaultScriptEngine = “ScriptEngine.DotNetEngine”

    [ScriptEngine.DotNetEngine]
    Enabled = true

    DefaultCompileLanguage=cs

    AllowedCompilers=lsl,cs

    #159
  10. Cliff

    Furthermore…When I try the default LSL script i get

    Primitive: Error compiling script:
    Line (0,0): Error CS1619: Cannot create temporary file ‘c:\Program Files\OpenSim\ScriptEngines\77b62ee3-7997-4c3b-a0b0-db44ef29ce14′ — The directory name is invalid.

    I have set the permissions on the OpenSim to full control.

    #160
  11. I’m not sure what you mean by the JJ Sample script, Cliff.

    Your other error on compiling the default LSL sounds like some kind of bug - you might want to check the wiki and our Mantis bug tracking system for similar issues and solutions.

    #161
  12. Cliff

    Thanks for the reply Justin.

    I was refering to the blog and code shown at
    http://justincc.wordpress.com/2008/11/21/c-scripting-in-opensim/

    I copied the c# sharp code from this blog and it produce the error shown in my previous note.

    regarding lsl i was referring to the default script that is created when you created a new script.

    Both of these scripts (lsl default and your c# script) are as supplied - no changes - so given this, what do the errors mean?

    #158
  13. I must admit, I can’t explain the first error. If you’re copying the script verbatim (with

    System.Xml.XmlTextReader reader
    = new System.Xml.XmlTextReader(sr);

    ) then it shouldn’t come up with that error.

    The second error sounds more like some kind of problem with your system rather than OpenSim itself. You might want to check that you can create the directory listed in the error manually.

    #163
  14. Takis

    Hello justincc,

    First of all thank you very much for your helpful posts all around internet;)

    I have spent the last few days trying to make this work on my OpenSim server with no success yet, hence I am writing this post.

    I keep getting the same error:

    Primitive: Error compiling script:
    Line (16,11): Error CS0234: The type or namespace name ‘Xml’ does not exist in the namespace ‘System’ (are you missing an assembly reference?)
    Line (17,21): Error CS0234: The type or namespace name ‘Xml’ does not exist in the namespace ‘System’ (are you missing an assembly reference?)

    It is exactly the same with the second error reported by Cliff few posts earlier.

    Tried with both XEngine and Dotnetengine, tweaked every possibly relative option but no luck. All .Net frameworks, SDK etc are installed, MS Visual Studio 2008 and Windows Standard Server 2008. I have some C# programming experience and even tried editing OpenSim source code (Compiler.cs and some other files) but no luck whatsoever.

    I have reached a deadend, and I really need C# functionality in opensim scripts, mainly for database access. I know this may not be the perfect place to post this, but you are one of the few that may be aware of a solution to this problem.

    Thank you very much in advance,
    Desperate developer
    Takis

    #169
  15. @Takis - how curious. I’ll try to remember to give this a try myself tomorrow on the latest OpenSim code. You might also want to try opening an OpenSim bug report so that other developers are aware of this.

    If I haven’t posted in the next few days here again feel free to give me a poke :)

    #170
  16. PipVolta

    hi, with regard to the Xml problem described above it seems to be a problem in the Mono compiler. If you put the code into monoDev and try to compile it you also get the Xml does not exist error message, even though you can put ‘using System.Xml;’ at the top, and the references block admits to the existence of System.Xml.
    It seems that some libraries just arent available on Mono I guess.
    Hope this helps
    Pip

    #485
  17. su

    Hi justincc,
    Do you know of any good C# scripting tutorial that we can use to code in Opensim?

    #502
  18. @PipVolta : that’s very strange - my original testing of the scripts was done on Mono so everything should work fine there. It looks like I might need to go back and take a look.

    @su: Unfortunately I don’t know of any good OpenSim C# scripting tutorial out there.

    #514
  19. PipVolta

    Hi justincc
    I was testing with MonoDev 2.0 by the way. I am continuing to write scripts in C#, but have met another imponderable. Do you happen to know how to switch states - the statement ’state newstate’ doesn’t have any very obvious equivalent in C# - presumably there is a function call of some sort? or do we have to do the complete C# event handler setup process?
    Regards
    Pip

    #515
  20. su

    I’m also getting the same error as Cliff and Takis. Strange that it recognizes System.IO, but cannot recognize System.XML. So anyone found the reason for this?
    @justincc- is there any place where we can add additional assemblies to OpenSim .NET environment?

    Rgds,
    Su

    #523
  21. su

    Hi justincc,
    I installed Opensim in my machine in standalone mode and set
    AllowedCompilers = lsl,cs

    I am also getting the same error that Robert got: “Primitive: Error compiling script:
    The compiler for language “cs” is not in list of allowed compilers. Script will not be executed!”

    I am using OpenSimulator Server 0.6.6.
    Were you being able to figure out the reason for this?

    Rgds,
    Su

    #527
  22. su

    I was able to resolve the second error. problem there was with the Script Engine. In my case, when the script engine was “XEngine”, it did not work. Then I changed it to “ScriptEngine.DotNetEngine” and now the compiler detects C#. but the error with the compiler not being able to detect System.Xml is still there

    #529
  23. su

    i reported a bug to mantis (http://opensimulator.org/mantis/view.php?id=4137) and according to the response I got from Melanie, the allowed references are hardcoded into the compiler. But since it is working for you, does it mean that you can change the compiler settings to include the references needed?

    #674
  24. @su - Hmm, thanks for the data, I’ll go back and give this a test when I can. It sounds a little strange to me.

    #697
  25. @su - I just tried the script I have in the blogpost on the most uptodate OpenSim (97c18caa766e2dd72b152b78827ef554f2054f8c, 22nd Sept 2009) and it works fine (and this under XEngine). Are you using the full names of types (e.g. System.Xml.XmlTextReader rather than just XmlTextReader)? Unfortunately, C#’s normal using statements will not work with OpenSim’s C# ’scripts’.

    #847
  26. su

    @justincc- yes i was using the full names. Sine my own code was not working, I just copy-pasted your example code. Is there anything else we have to add to your code?

    #1027
  27. @su - Not to my knowledge. But I’d be happy to take a look at your code if you e-mail me your OpenSim.ini and the exact text of what you’re trying to run.

    #1060
  28. Dimple

    Justin/Su,

    I am getting same System.XML error (Error CS0234: The type or namespace name ‘Xml’ does not exist in the namespace ‘System’ (are you missing an assembly reference?)
    , it recognizes System.IO, but cannot recognize System.XML.

    I am working on 0.6.7 opensim. Any ideas? Please Help!!!

    Regards,
    Dimple

    #2322
  29. @Dimple. I just spent a bit of time investigating this and found out that it works fine under Mono (on Linux) and only fails under .NET on Windows. I’m thinking of a more radical fix in the trunk line (possibly by allowing a full class to be used including using statements).

    Unfortunately, in 0.6.7 things are a little more difficult since I don’t really want to start putting in arbitrary hardcoded references. If you’re desparate, in Compiler.cs in the OpenSim.Region.ScriptEngine.Shared.CodeTools project, you could try adding an extra reference in the CompileFromDotNetText() method. That is, where you see

    parameters.ReferencedAssemblies.Add(Path.Combine(rootPath,
    “OpenSim.Region.ScriptEngine.Shared.dll”));
    parameters.ReferencedAssemblies.Add(Path.Combine(rootPath,
    “OpenSim.Region.ScriptEngine.Shared.Api.Runtime.dll”));

    you could try adding something like

    parameters.ReferencedAssemblies.Add(”System.Xml.dll”);

    though I couldn’t guarantee this will work. If you try it, I’d be interested in the feedback.

    #2351
  30. Dimple

    Hey Justin,

    It works!!! You add the reference and wallah ….

    Thanks alot for your timely help!!!

    Regards,
    Dimple

    #2362

Leave a Reply

About me

Hi, I'm Justin Clark-Casey, an OpenSim core developer and professional software engineer.

On the Linden Lab grid I go by the name of Lulworth Beaumont. On other grids I'm just plain old Justin Clark-Casey.

I'm currently working as a freelance consultant specializing in OpenSim. If you're interested in learning more then please read the Hire Me page. Thanks!

Twitter Updates

Posting tweet...

Powered by Twitter Tools