如何在java ScriptEngine的每个eval上提供单独的上下文?

时间:2013-08-13 14:23:11

标签: java javascript scriptengine

使用javax.script进行基于java的游戏;

public class AI implements Runnable {
private boolean alive = true;

String scriptStr;
ScriptEngine scriptEngine;
ScriptContext scriptContext;
Bindings engineScope;

public AI() {
    ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
    scriptEngine = scriptEngineManager.getEngineByName("JavaScript");
    scriptContext = new SimpleScriptContext();
    engineScope = scriptContext.getBindings(ScriptContext.ENGINE_SCOPE);
    engineScope.put("scene", Scene.instance);

    try {
        scriptStr = new Scanner(new File(getClass().getResource("ai.js").getPath())).useDelimiter("\\Z").next();
    } catch (FileNotFoundException e) {
        e.printStackTrace(); 
    }
}

@Override
public void run() {
    while (alive) {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        Iterable<IUnit> units = Scene.instance.getUnits();
        for (IUnit unit : units) {
            if (unit.isAlive()) {
                engineScope.put("unit", unit);
                try {
                    scriptEngine.eval(scriptStr, scriptContext);
                } catch (ScriptException e) {
                    e.printStackTrace();  
                }
            }
        }
    }
}
}

在上面的代码中我有一个场景,提供迭代的单位。我想为单位决定做什么的所有单位调用相同的js代码(&#34; ai.js&#34;)。

问题在于我希望每个单元都有自己的上下文数据。所以每当我评估一个单位的ai.js时,他们就不会是无国籍和无记忆的。

正确的方法是什么?

我是否应该为每个单位明确使用类似SpringContext的东西?

或者是否可以像运行Unit类上下文中的函数一样运行ai.js?

1 个答案:

答案 0 :(得分:0)

我使用单个ScriptEngine完成了这个操作,每次执行都带有一个SimpleScriptContext - 虽然它可能是每个线程。

创建上下文后,必须先在该上下文中执行它,然后才能供scriptlet使用。

为了优化重复包含库,我在创建ScriptEngine时将其编译为CompiledScript一次。

我编译每个scriptlet对象,然后使用eval(context)方法执行它们。

在我的测试中,这足以创建线程安全性。