I want to add functions to the _G
that can run Java code. I'm using Luaj and it can already run user written Lua code, but I want to add apis that'll allow the user to interact with the game world.
You make a class for each library function and one class to load the functions. You extend the appropriate class depending on how many arguments your function takes (up to three arguments, then you need to make your own FourArgFunction
).
Here's trimmed down example code from MathLib.java file from the luaj source (to be found here: http://sourceforge.net/projects/luaj/files/latest/download):
This is what you need to load when you add you library.
public class MathLib extends OneArgFunction {
public static MathLib MATHLIB = null;
public MathLib() {
MATHLIB = this;
}
public LuaValue call(LuaValue env) {
LuaTable math = new LuaTable(0,30); // I think "new LuaTable()" instead of "(0, 30)" is OK
math.set("abs", new abs());
math.set("max", new max());
env.set("math", math);
env.get("package").get("loaded").set("math", math);
return math;
}
}
You load it like this:
globals.load(new MathLib());
Then you make subclasses of MathLib for each library function. For a function that takes one argument, here's an example:
abstract protected static class UnaryOp extends OneArgFunction {
public LuaValue call(LuaValue arg) {
return valueOf(call(arg.checkdouble()));
}
abstract protected double call(double d);
}
static final class abs extends UnaryOp {
protected double call(double d) {
return Math.abs(d);
}
}
You don't need the abstract class, you could make abs
directly, but it will be obvious if you look at the source that it is more convinient to do it like this when you need to implement a lot of mathematical unary operations.
Here's an example for a function that takes a variable amount of arguments:
static class max extends VarArgFunction {
public Varargs invoke(Varargs args) {
double m = args.checkdouble(1);
for ( int i=2,n=args.narg(); i<=n; ++i )
m = Math.max(m,args.checkdouble(i));
return valueOf(m);
}
From Lua, you do: require('math')
to load the lib and then something like math.abs(-123)
to call a lib function.
I really recommend checking out the source of luaj if this is hard to grasp. Also, my trimmed down code is untested, so I'm not 100 % sure it works.