Search code examples
javanashorn

Using multiple ScriptEngines


I have a folder which can contain an arbitrary number of scripts which function as spells. The code in these script files is quite minimal for most of them.

A simple spell might contain:

  • Return name
  • Return damage
  • Display effect
  • Launch/control projectile

The more advanced ones might alter the terrain or something like that.

The Spell class on the Java side calls the cast function in the script.

What I would like to know is the different ways of doing this and their pros & cons. The way I'm seeing this right now is: create a new ScriptEngine object when the spell is cast, destroy it when it's done.

I don't think it's possible to set a new ScriptContext on an existing ScriptEngine because the spell might not have finished casting yet, before the next spell is cast unless I implement some kind of queuing system.


Solution

  • Instead of creating a new script engine each time, maintain a single ScriptEngine instance and just create a new context (with new globals) each time. Then evaluate your script in that context:

    ScriptContext context = new SimpleScriptContext();
    context.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE);
    
    engine.eval(script, context);
    

    If your scripts aren't dealing with mutable-state in the global scope (JavaScript global scope), then you can simply create a new context and use the engine's same globals:

    ScriptContext engineContext = engine.getContext()
    
    ScriptContext context = new SimpleScriptContext();
    context.setBindings(
        engineContext.getBindings(ScriptContext.ENGINE_SCOPE),
        ScriptContext.ENGINE_SCOPE
    );
    
    engine.eval(myScript, myContext);