July 8, 2013

Modding KSP with Scala

TL:DR Just use C# for making addons with KSP, it really isn't worth spending all the extra effort to use a JVM language.

Getting Java 1.7 to work as a mod with Kerbal Space Program is 'easy'. However, the same trick appears to not be able to work with Scala 2.10. It looks like the bridge between Scala and C# is just a bit too far. However, it isn't the end of the world because it still works.

IKVM.NET is pretty good, it does the job well and actually makes the whole thing possible. However, there is one big catch that really hurts when working with KSP. I'll quote the author:

First limitation: Currently only custom attributes that have a default constructor or a single one-argument constructor (taking a supported type) are supported.

The second limitation is that not all parameter types are supported, only the Java primitive types (where Java's byte maps to System.Byte), type literals, strings and enumerations are supported (and single dimensional arrays of these types). Custom attribute parameters typed as Object are not supported.

Java

The issue is most things in KSP work by using attributes and thus IKVM.NET will choke on a number of these attributes. However, there is a way around it: inheritance. If you take an attribute and subclass it (to meet the above limitations) IKVM.NET will happily work with the attributes. This does mean you have to write a C# adapter to provide attributes you can use as interfaces in the JVM world. Below is an example of what I mean:

public class EditorAnyAttribute : KSPAddon {
    public EditorAnyAttribute() : base (KSPAddon.Startup.EditorAny, false) {}
}

Doing all that you can compile your java jar into a dll and slap it into the Plugins folder for your mod, just like you would normally put in your C# dll. However, you also need to put in the IKVM.Runtime.dll and the IKVM.OpenJDK.Core.dll (totaling just over 5MB). If you use some of the other classes, you will also have to provide dll for them as well.

This means your plugins folder will look like this:

[mod].dll
[ksp_attribute_layer].dll
IKVM.Runtime.dll
IKVM.OpenJDK.Core.dll

Pretty gross.

Scala

Now if you simply try to apply the same process to Scala, it won't work. There is an issue between the annotations generated for attributes by IKVM.NET and how Scala expects an annotation to work. The end result is scalac will complain the annotation is not defined. It will insist it is not defined and cowardly refuse to believe in it. This means you need another adapter in Java to actually use the annotation and then from the Java code you can call your Scala code. Another nice catch is you will also need to use IKVM.NET on the scala-library.jar to use any of the Scala objects, but out of box this doesn't work.

I'm going to assume I will need to apply proguard onto the scala-library.jar first with my jar file to strip it down only to the tiny bits I'm actually using (sounds very much like the Scala workflow for Android).

This means if you want to use Scala your plugins folder will look like this:

[mod w/ java wrapper].dll
[ksp_attribute_layer].dll
scala-library.dll
IKVM.Runtime.dll
IKVM.OpenJDK.Core.dll
IKVM... (other IKVM libraries depended on by Scala)

At the end of the day, yes you can use Scala to make a mod for KSP, but you are going to have to use 3 languages and 2 tools to make it happen. Your mod is going to be a massive binary blob to even make the simple things run. This means KSP loading time will also be increased by the fact you are now loading a number of extra dlls.


In conclusion, you can do it and in order to keep yourself sane you are going to need to automate the whole process because its going to be painful (Gradle for example). Additionally, you will need to write code to fill in the gaps between C#, Java and Scala. Using Java isn't quite as bad and reduces the number of steps required to build a mod, but you still are going to need to use some C# to hook it up for working with some of the attributes. This basically means you might as well just do the whole thing in C# and not spend the time making things compatible.

No comments :

Post a Comment