Design Decision: Scripting

Hey Guys,
I have come to a point where I don’t know how to proceed so I ask my fellow monkeys, maybe someone knows how to get that Banana :smiley:

It’s basically about how to design my Scripting-API/Interface. This is related to everything: The GUI, some Plugins/AddOns and even AI Design.

Being an ex-WoW-Addict and modder for racing games like world racing 2, having scripted some hl2 scripts I want my game to be as open as possible.

What did I achieve so far?
Because I was too lazy to write tons of interfaces/helper functions and because it was AI related I simply made a directory where I threw in all AI Behaviors and they got compiled during runtime.

Currently this isn’t a problem for me because compilation is faster than loading the map, but it also comes with a drawback: I need to package the way bigger jdk over the jre.

Honestly, if somebody with some knowledge in programming wants to create a plugin, he could compile the files and replace/drop them into the jar aswell, I guess you could even set up ant/gradle to do so.

The WoW approach
WoW uses LUA Scripting along with their own wrappers for their GUI (which I like, it’s just quite some work).
This would be good because I currently use Lemur and t0neg0d-side-by-side.

I also like how WoW has the default UI as “Addons”, so I could code “backend-indepently” aswell and maybe reuse that code for other games I plan to do in the future.

The downside of this is I’d need a proper eventManager.registerEvent(Event.OnPlayerDead, thisproc); for each event. When supporting java one could simply access the linked list :stuck_out_tongue: (I know I am lazy :smiley: )

My new Idea
Another thing I see is the lack of libraries, say, one wants to code some window which announces the current stock-exchange values in chat or in a GUI Frame. He would have to code http requests and json parsing in lua (if possible at all) or the GUI in Java, which are things I dislike.

So I thought about allowing both, the lua and the java scripting both using the same interface.
This way one could add his network/json in java and the GUI in lua.
I only wonder how the communication between the two should work?

So I don’t know what I wanted to achieve with this post but I am happy about all input.

I HIGHYL recommend Groovy for scripting. It directly interfaces with Java and the groovy code is compiled to real Java classes at runtime (or precompiled) so you can call groovy objects directly from Java even.

I used it to implement Lemur’s style language. It’s also the backbone of Mythruna. Very easy to add DSL-like features.

On the other side, Java already has JavaScript built in… but if you add groovy-all.jar to your classpath groovy is effectively “built in” also.

3 Likes

If embedding the jre8 is not a problem, you could consider using the javascript interpreter that comes with java8.
iirc it allows the usage of all java classes by default, and you can set a filter that [dis]allow specific classes.

Indeed, and it’s also quite fast.

Here are some examples: http://winterbe.com/posts/2014/04/05/java8-nashorn-tutorial/

I think it may come down to whether you’ve done a lot of Javascript programming before or not. I found groovy to be easier to pick up because it’s based on Java.

The fact that it makes actual Java classes is a nice side benefit as instead of doing all of the invoke stuff as in that Javascript page’s examples, you can simply return an object and call methods directly on it (assuming it implements an interface or you cast to the groovy-generated class name).

This is nice because in Mythruna, I can register groovy code directly as event handlers in my Java-based even bus.

You need to find a balance between what kind of support for scripting you can achieve in Java with speed and what kind of target modders you think you will have, assuming that others should be able to write mods as well as yourself.

Personally I prefer Lua for my projects. Making safe sandbox in JS or Groovy is a pain for me.

By safe sandbox, you mean making it so that modders, for instance, can only interface with the non-scripted Java code in the way you’ve defined?

I’ve wondered about using Lua before, after coming across it for the first time in World of Warcraft. What technology do you use to do Lua with Java?

The other scripting language I’ve thought about using is Python, for which Jython seems to be the standard technology to use for Java.

By safe sandbox I mean that sandboxed code can’t cause any harm to user computer in a first place. Second implication of sandbox is to make so that, for example, AI script can’t alter your save game or alter player in-game resources or create game objects out of thin air - only AI API should be accessible for AI script. It’s a must have if you plan to allow players create and share their own mods and don’t want to deal with angry users harmed by mod from other player. It’s near to impossible to make safe sandbox in language with reflections mechanism avalible - have to parse source or byte code and purge unsafe calls that try to break out of sandbox defined by API.

For Lua I usually use LuaJ, pure Java implementation of Lua VM. Sometimes I use embedded C implementation, mainly when I need Eris/Pluto Lua persistence library and don’t care much about real cross-platform compatibility (btw, I wanted once to port functionality of this library and contribute it to Luaj but failed badly due to lack of free time).

OP already said he didn’t want to have to register everything to be available for the scripting language so that already sort of rules out a ‘sandbox’ approach.

Games have been very successful that have open modding. Minecraft, for one, sold a few copies I think.

Minecraft don’t have supported modding yet - everything we have is illegal source code decompiled by community and tools built around it, please don’t use Minecraft as example of successful modding support. Only thing Mojang did to support mods - they closed eyes on illegal nature of all current mods. :chimpanzee_wink:

But the point is that it is a HUGELY SUCCESSFUL modding community and being able to ‘do anything’ unsandboxed has not hurt them. With the millions of players and thousands of mods it has not been an issue.

Providing support for something doesn’t automatically make you responsible for the bad stuff people might do with it.

In Java, if you are really paranoid you could always run the scripted stuff (even Groovy) in its own Java security-walled space. You could at least limit access to the system that way and prevent accessing private methods and stuff. It’s kind of a pain, though.

And a lot of harm was made by mods with malicious code inside and continues to be done. Just no huge scandal emerged yet. And it’s just a matter of time when some author of big well known mod will retire and go bonkers, inserting something unbearable in “final” version of his mod.

The danger is precisely the same for every game you download. Any one of them could suddenly do bad things to your system if the creator decides to go bonkers or was hijacked.

One could argue that presenting an aura of safety then DOES make you responsible for bad things that can happen. So if you do provide a sandbox and someone manages to figure out how to exploit some bug then you could be in big trouble.

For an indie game, it might actually be better to take a ‘hands off’ ‘use at your own risk’ approach to modding.

Not many released games are done by 14 years old spoiled kids while many mods are. So with mods danger is much higher.

Regarding sandbox - nothing stops you from going “hands off” even if you have sandbox for mods - you don’t even have to present it as sandbox, just call it modding API or similar and note that players are on their own while dealing with third party mods.

Certainly you could just make Java-based API without a sandbox on top of it but I prefer to have additional layer of protection. It hardly will stop real hackers but it definitely will stop kids from putting knifes into each other.

For me main concern about sandboxed approach is that it’s harder to develop game with sandboxed mods in mind as it requires some twists in game architecture, up to making your game a mod itself around some basic core.

Well, I’m tuning up Gossip Radio here… because I’ve never gone there. But I’ve heard about a java.lang.SecurityException, when code is not allowed to do some things (including loading some classes)… And I’ve also heard about signed jars, that can be used to explicitly allow some actions that an application couldn’t do otherwise.
I’ve also heard rumors that this doesn’t exactly work fine, and I don’t remember why.
And I’ve also seen some measures to protect java classes, by using something called BouncyCastle (back in 2005)…

I think the main issue with scripting is how to interrupt them… Maybe there is something I don’t know, but it is easy to break a program with Denial-of-Service code… A simple while (true) { //do bogus stuff } can do it, if launched directly from the main process, by freezing resources and generating at least a thread leak.

One of the things I’ve got thinking into over and over was the possibility of making a time-sharing engine for scripts (only allow each script to run up to X instructions per second, and/or up to Y instructions total…).

But when you have to use Groovy code on Java, you need to use GroovyClassLoader to get GroovyObjects and call invoke also, don’t you? Or have I misunderstood the cool side of Groovy?

Groovy objects are Java objects. They are real Java class files in memory. (Or you can precompile them.) They can implement Java interfaces and you can call them just like any Java object.

So, you have lots of options. The simplest is just to create the ScriptEngine and eval() the script. Let it return an object you can interact with or give it some things to interact with or let it access static method or whatever. As far as access goes, it’s just like Java code.

But once you have the object you don’t have to do anything special. Every time you invoke Javascript from Java you have to go through the invoker stuff. That’s not true for groovy… because groovy objects are real Java objects.

1 Like

Btw, LuaJ knows how to compile Lua code to Java bytecode if you want it to do so. Not so fancy as with groovy though.

I got it, it’s a clever approach. But since we are talking about Groovy on jME3, another downside that I found by using Groovy is the Groovy Plugin on SDK. At least for me, it didn’t do auto imports (when using Node or Vector3f I had to manually add the import) and most code complete wont work.

The plugin seems to be kinda outdated.