Using Java Scripting API to create game content - java

So, I'll be using the Java Scripting API with JavaScript to do all the scripting for the game. Now, I've read over the documentation I can't seem to figure out how I could do a one time run of some of the scripts to get all the 'different types of objects data' to be fed to Java. I'm actually not quite sure how to save all that data to Java or if I should even try saving it to Java....
QUESTION: How can I import a bunch of scripting information at run-time into my application?

You can basically pass data between scripting environment and Java through the scripting API. For example,
final ScriptEngineManager factory = new ScriptEngineManager();
final ScriptEngine engine = factory.getEngineByName("JavaScript");
engine.eval("greeting='Hello'");
// Returning data from scripting environment to Java.
// The data can also be returned from a function
final String greeting = (String) engine.eval("greeting");
System.out.println(greeting); //prints Hello
//Passing data to scripting environment from Java
engine.put("who", "foo");
final String greetingFoo = (String) engine.eval("greeting + ', ' + who");
System.out.println(greetingFoo); //prints Hello, foo

Related

How to manipulate XML data trough Java scripting API

I am writing something that may be called workflow engine. For that I have created data model for the workflow as XML following specific XML Schema.
Below is an example of XML representing this data model:
<dm:agentModel xmlns:dm="ProcessObjects" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="ProcessObjects agentModel.xsd">
<dm:cfp isList="false" objName="myCFP"></dm:cfp>
<dm:proposal isList="true" objName="receivedProposals"></dm:proposal>
<dm:feedbackList objName="cfpFeedbacks">
<dm:item>
<dm:to>Andrew</dm:to>
<dm:from>Paul</dm:from>
<dm:heading>That is bad</dm:heading>
<dm:body>Fix points a, b and c, please.</dm:body>
</dm:item>
<dm:item>
<dm:to>Frank</dm:to>
<dm:from>Paul</dm:from>
<dm:heading>Very good!</dm:heading>
<dm:body>I see no drawbacks. You can also ask Matthew for additional feedback.</dm:body>
</dm:item>
</dm:feedbackList>
</dm:agentModel>
The workflow definition, which is defined by the user by the means of web editor is the BPMN XML standard. For not going too deep in the details, i need to give user possibility to define some scripting interface. User needs to be able to writhe something like:
/*JavaScript code*/
for(var i=0; i<agentModel.cfpFeedbacks.length; i++) {
if(agentModel.cfpFeedbacks[i].to == "Frank") {
agentModel.cfpFeedbacks[i].to += " Sinatra";
}
}
By now, I wrote Java class (DataModel) that can access data built from XML given above. Because XML may contain many different objects, there are getters and setters that looks like:
/*Java code*/
DataModel agentModel = new DataModel(xmlString);
agentModel.getValue("cfpFeedbacks[1].to");
//returns String "Frank"
agentModel.setValue("cfpFeedbacks[0].from", "Paul Anka");
//obvious
To run user-written script I am trying to use Java Scripting API
/*Java code*/
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("JavaScript");
//binding object
engine.put("agentModel", agentModel);
String script = "var i = 0;"
+ "println(agentModel.getValue(\"cfpFeedbacks[\" + i + \"].from\"));";
engine.eval(script);
Which is more or less working. What I want to archieve is something like this working:
/*Java code*/
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("JavaScript");
//binding object
engine.put("agentModel", agentModel);
String script = "var i = 0;"
+ "println(agentModel.cfpFeedbacks[i].from);";
/**
* any magic operations here
*/
engine.eval(script);
Goal is to provide easiest-possible interface for end users to write their scripts.
I am a little bit lost and I would be grateful for any inspiration. Personally I did consider three scenarios:
Creating Java-Bean style classes, and compiling them instead of working on XML
Parsing script string from second to the first form (which seems to be most easy, but time expensive and definitely not 'clean')
Developing some kind of magic interface to the object where calling object.field is synonym for calling object.getValue("field")
Maybe there is some obvious workaround I don't see.
Thanks in advance for any replies,
PS. If my description is unclear, or you find it is worth to provide more source code I'll clarify question immidiately. Getting it done is right now priority for me.
The best way is deserialize xml to java object and then just put result into engine.
You are able to direct operate on objects putted via engine.put(..) method
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("js");
engine.put("a", 1);
engine.put("b", 5);
engine.eval("a = 2;");
Object result = engine.eval("c = a + b;");
System.out.println("a + b = " + result);
Finally get object from script engine and serialize object to xml, jackson will be useful

Java ScriptEngine - Create dynamic variables in java class

I've using the java ScriptEngine to execute a script that could alter a shared Java class. I'm wondering, if it's possible to support dynamically created variables in the java class?
// create a script engine manager
ScriptEngineManager factory = new ScriptEngineManager();
// create a JavaScript engine
ScriptEngine engine = factory.getEngineByName("JavaScript");
engine.put("javaclass", jClass);
engine.eval("javaclass.propertyThatDoesNotExist = 'test'"); // throws exception
You can register a javascript variable in the engine, by using the ScriptEngine#put(String key, Object value) method. For example:
engine.put("i", 10);
This is how can you retrieve the registered variable:
int i = ((Double) engine.eval("i")).intValue();
System.out.println("JavaScript variable in Java; i = " + i);
Java is not a dynamic language. So you can not add a property/variable to that class/object. For that you need to use a different language like Groovy or Java Script.

User script input in java

I am developing a java app where the user inputs certain functions through a property files. The functions are then evaluated at runtime with variable values provided by the app.
Here a simple example. The user wants to calculate the return on investment for a certain capital allocation over the next n years. He should be able to input not just relevant parameters, but a function that calculates the return year by year.
Can anyone suggest or recommend a scripting language which is simple , so that the user learning curve is not too steep, and for which a standard library providing integration with java code is available?
A related example would be welcome too.
My suggestion is to use ScriptEngine and evaluate Javascript functions. As simple as:
public class TestScriptEngine {
private static final String script = "var customFunction = function(parameter) {\n" +
"\treturn parameter*parameter;\n" +
"};\n" +
"\n" +
"println(customFunction(10));\n";
public static void main(String[] args) {
ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine engine = factory.getEngineByName("JavaScript");
// evaluate JavaScript code User's input
try {
engine.eval(script);
} catch (ScriptException e) {
e.printStackTrace();
}
}
}
I would suggest using javascript. It is simple enough and the Rhino library is integrated with java. Complete information can be found here: Rhino
You could take a look at Groovy. It can be embedded in Java applications and be a useful tool for scripting in applications.
http://groovy.codehaus.org/Embedding+Groovy
You could use JavaScript or Ruby, they should be convenient enough.

Bind method call in JavaScript script in Java Scripting

Suppose I have a Javascript file
function js_main(args){
/* some code */
var x = api_method1(some_argument);
/* some code */
}
And I try to run it with javax.scripting the usual way
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("javascript");
engine.eval(...);
Now the I'd like to handle the call to api_method1 in Javascript with my Java class. I'd like to have some kind of mapping/binding of calls i.e. each time the script calls api_method1(arg) a method
public Object api_method1(Object arg){ ... }
(placed in the same class as the engine) would be called.
Can I achieve this?
use engine.createBindings() to make a Bindings object;
put an object exposing your method into the bindings with some name:
Bindings b = engine.createBindings();
b.put("api", yourApiObject);
engine.setBindings(b, ScriptContext.ENGINE_SCOPE);
Then in JavaScript there'll be a global "api" object you can call:
api.method1( "foo", 14, "whatever" );
The facility is easy to use, but be careful with what you pass back and forth; it doesn't do that much to convert JavaScript types to Java types.

how to use java to get a js file and execute it and then get the result

How can I use java to get a js file located on a web server, then execute the function in the js file and get the result and use the result in java.
Can you guys give me some code snippet? Great thanks.
You can use the scripting engine built into Java:
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
public static void main(String[] args) throws Exception {
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("JavaScript");
Object result = engine.eval("my-java-script-code")
System.out.println("Result returned by Javascript is: " + result);
}
Here is a more elaborate example.
There's three steps to this process:
Fetch the JS file from the server.
Execute some JS function from the file.
Extract the result.
The first step is fairly simple, there are lots of HTTP libraries in Java that will do this - you effectively want to emulate the simple functionality of something like wget or curl. The exact manner in which you do this will vary depending on what format you want the JS file in for the next step, but the process to get hold of the byte stream is straightforward.
The second step will require executing the JS in a Javascript engine. Java itself cannot interpret Javascript, so you'd need to obtain an engine to run it in - Rhino is a common choice for this. Since you'd need to run this outside of Java, you'll likely have to spawn a process for execution in Rhino using ProcessBuilder. Additionally, depending on the format of the Javascript you might need to create your own "wrapper" javascript that functions like a main class in Java and calls the method in question.
Finally you need to get the result out - obviously you don't have direct access to JavaScript objects from your Java program. The easiest way is going to be for the JS program to print the result to standard out (possibly serialising as something like JSON depending on the complexity of the object), which is being streamed directly to your Java app due to the way you launched the Rhino process. This could be another job for your JS wrapper script, if any. Otherwise, if the JS function has observable side effects (creates a file/modifies a database) then you'll be able to query those directly from Java.
Job done.
I hope you realise this question is far too vague to get full answers. Asking the public to design an entire system goes beyond the point where you'll get useful, actionable responses.
There are plenty of examples on the web of how to download a file from a URL.
Suns version of the JDK and JRE includes the Mozilla Rhino scripting engine.
Assuming you have stored the contents of the javascript file in a string called 'script', you can execute scripts as follows
String result = null;
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine jsEngine = mgr.getEngineByName("JavaScript");
try {
jsEngine.eval(script);
result = jsEngine.get("result")
} catch (ScriptException ex) {
ex.printStackTrace();
}
The result will be extracted from the engine and stored in the 'result' variable.
The is a tutorial on scripting in Java that might be useful.

Categories