• Advertisement

Archived

This topic is now archived and is closed to further replies.

[java] Java as a scripting language: using the JNI

This topic is 5799 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, im considering using Java as a scripting language for AI, dialogue and probably effects from spells etc. in a RPG(well, i will probably never finish it, you get the idea In the game ill have the main game logic which manages a bunch of GameObjects, which can be a character or a door for example. All intelligent GameObjects will call an AI script once in a while. Having that script as a Java class isnt a problem as far as i can see when using the JNI. But this this script will want to query the gamelogic back for information, it might want get a handle(i dont want to bother "shipping" objects back and forth) to the nearest hostile GameObject, determine its type calling another method with the handle, and set an AI state. ie, something like this: int handle = getNearestEnemy(); String type = getType(handle); if(type == "DRAGON") setAIState(AI_FLEE); Im a bit confused as to how i expose these methods(int getNearestEnemy() & String getType(int handle)) to the script. Im looking for good places to find info on the JNI, but java.sun.com seems to have some slightly obsolete information, im not sure its tutorials have been updated, and anyway, they confuse me a little So anyone know a place to find a tutorial for something like this?(i already read the old Gamasutra article) Also, for very good reasons i only want the script to have access to a few select of the core java classes(String, Vector etc, but not AWT/Swing or anything like that!). Is such restrictions possible?

Share this post


Link to post
Share on other sites
Advertisement
IIRC, JNI still requires a JVM/JRE. I think you might be better served by using an alternative that you can bundle with your program as a library/dll file. java-script is a good candidate - the js string class is more versatile than java, js arrays are really vectors and the other default classes provide other standard functionalities. The source code is available too - check out the Spider Monkey project at mozilla.org. Other implementations are available too. Look up ECMA script at google.

Share this post


Link to post
Share on other sites
I''m currently developing a complete scripting system using the JNI and Java.

Ignore the above post, java is faster than any other scripting language you can use, and your scripters have countless references to learn java for their programming. Plus you don''t need to distribute the JVM with your game because if you have windows (Internet Explorer) then the system already has a JVM. (although you probably should ''cause you will probably have a better JVM than the IE one).


Anyways, Java put out a book on using the JNI. It''s very good refernece. Otherwise just keep searching the web. Eventually I will put out a tutorial on using the JNI for a scripting engine, but I haven''t gotten around to it. But you are not incorrect in thinking JAva would make a great scripting engine, because it does.

Share this post


Link to post
Share on other sites
quote:
Original post by shaft
I''m currently developing a complete scripting system using the JNI and Java.


I would be interested in seeing this. Have you got a demo?
quote:
Original post by shaft
Ignore the above post, java is faster than any other scripting language you can use, and your scripters have countless references to learn java for their programming.


Java isn''t a scripting language. My suggestion will get you up and running a lot sooner. If you don''t like js, use python, lua, etc. Why reinvent the wheel?

Share this post


Link to post
Share on other sites
quote:
Original post by LessBread
Java isn't a scripting language. My suggestion will get you up and running a lot sooner. If you don't like js, use python, lua, etc. Why reinvent the wheel?



True, Java is a compiled language, but the context in which we're talking about a scripting language here is a language that is not the primary language the app is written in but is used to extend the functionality of the application. And how is using an existing language, API, & VM re-inventing the wheel?

That said, Java is an excellent option thanks to its speed and large industry support. However, using JNI can complicate the design of your system. Here are some suggestions:
- Minimize the amount of JNI code you have to write. I would say keep the majority of the AI sub-system in Java and minimize the interacton with native code.
- If you are able to utilize Java 1.4, do so. The New I/O package offers ways to share memory between Java code and Native code, and can give you some definate speed increases over the pre-1.4 API.
- A descent tutorial is here, although I too recommend buying a book.

As for restricting what classes can be used, there might be some way to do this with a SecurityManager, but I have never tried so don't quote me on that.




"There is no reason good should not triumph at least as often as evil. The triumph of anything is a matter of organization. If there are such things as angels, I hope that they're organized along the lines of the mafia." -Kurt Vonnegut


Edited by - wayfarerx on February 22, 2002 5:20:32 PM

Share this post


Link to post
Share on other sites
quote:
Original post by WayfarerX
True, Java is a compiled language, but the context in which we''re talking about a scripting language here is a language that is not the primary language the app is written in but is used to extend the functionality of the application. And how is using an existing language, API, & VM re-inventing the wheel?


Looks like we have slightly different conceptions of scripting and scripting languages. This approach is not a complete reinvention of the wheel, but it does seem like extending java in a way that it wasn''t necessariy designed for. That''s an obstacle. Plus the jvm dependency also presents an obstacle. These obstacles must be great, otherwise I would expect to find more references to using java in this fashion. I suggested an alternative with fewer obstacles. That''s all. There are other languages expressly written for scripting - languages for which the engine source code is available which would make embedding them easier - as well as restricting their capabilities. I pointed out java-script, but there''s python too and CScript among others.

Ziphnor mentioned the sun tut seemed obsolete and was creating some confusion. I agree that a JNI book would be a worthwhile investment.

A security manager might work, but I would think it more likely that you will have to set up a base class that scripts must use in order to run in your app. Robocode does it this way - but robocode doesn''t appear to use JNI.

Share this post


Link to post
Share on other sites
As far as i know, usually creating a scripting language means creating a virtual machine and compiler etc.
Interpreting directly is supposedly very slow(im currently reading the book "Programming language processors in Java : compilers and interpreters", not that im intending to implement the whole thing myself, im just interested in how its done).
Isnt java-script interpreted directly? But perhaps its still fast enough? Anyway, i havent the faintest idea of how to go about embedding java-script in a C++ application, any links would be much appreciated. The big question is of course how easy it is to make script methods that calls back to where the script was started to query the game logic(those methods cant just be declared seperatly as they extract information from the running C++ app).

The good thing with Java, is that the syntax is very easy for me, and most others(Java is the language of choice for introducing programming to students it seems), but the same goes for java-script i guess. I dont think the JVM dependency is that much of a problem, arent you allowed to distribute the Sun JVM with your program?(all you need is jvm.dll or what ever its called as far as i understand).

I also had a look at Simkin, but that scripting language has an odd syntax, and it seems much more oriented towards xml and small mobile devices.
Btw, what about the Java micro edition, does that include JNI?

Regarding limiting the scripts to specific core classes, i was also intending to force the use of a specific base class, but that still doesnt prevent users from using weird parts of the java classes in the methods i call.

Anyway, thanks for answering.

Share this post


Link to post
Share on other sites
quote:
Original post by Ziphnor
As far as i know, usually creating a scripting language means creating a virtual machine and compiler etc.


That''s what I was thinking.
quote:
Original post by Ziphnor
myself, im just interested in how its done).


Me too. That''s why I wanted to see a demo of shaft''s implementation.
quote:
Original post by Ziphnor
Isnt java-script interpreted directly? But perhaps its still fast enough?


AFAIK, yes. IIRC some early Netscape Foundation Classes used Java to provide a means to "compile" the script the first time it ran so that it could be repeated more quickly. I don''t know where that stands viz current browser implementations. There are also server side implementations - so it must not be too glacial.
quote:
Original post by Ziphnor
embedding java-script in a C++ application, any links would be much appreciated.


FESI - Free EcmaScript Interpreter
SpiderMonkey (java-script-C) Engine
quote:
Original post by Ziphnor
The big question is of course how easy it is to make script methods that calls back to where the script was started to query the game logic(those methods cant just be declared seperatly as they extract information from the running C++ app).


A Bare Bones Tutorial There are three snippets of code demonstrating how to start up a vm, how to call C from js, and how to call js from C.
quote:
Original post by Ziphnor
The good thing with Java, is that the syntax is very easy for me, and most others(Java is the language of choice for introducing programming to students it seems), but the same goes for java-script i guess.


Don''t get me wrong. I think Java is great. java-script is easier because it''s weakly typed - "var" could be a number, a string or an object. java-script is more procedural than Java, but it has primative oop capabilities. As an embedded language the browser tricks wouldn''t be there of course - unless you built them and I guess that''s the goal. java-script offered regular expression string parsing before Java did - but Java does that now. Looking over the spider monkey stuff - I see that scripts can be compiled. Cool.
quote:
Original post by Ziphnor
I dont think the JVM dependency is that much of a problem, arent you allowed to distribute the Sun JVM with your program?(all you need is jvm.dll or what ever its called as far as i understand).


I don''t know about Sun''s redistribution policy. I would assume it is conservative and that they would rather distribute their JVM themselves. If all it takes for a jvm is one dll, I think I will have to rethink my understanding. I might be slightly off base.
quote:
Original post by Ziphnor
Anyway, thanks for answering.


Sure.

Share this post


Link to post
Share on other sites
I''d never even heard of using Java as a scripting language before this post.

I have some questions: When you do this, can the Java code do basically anything it could do in a regular Java application? In other words, can your C++ program limit/determine what the Java code does, or does it have no control over it? That would seem to me to be a major disadvantage.

Also, would it still use the standard Java library or whatever they call it?

And, how does the "script" interact with your program, in terms of things like having the script call an external function located in your C++ program?

~CGameProgrammer( );

Share this post


Link to post
Share on other sites
to CGameProgrammer:
"I''d never even heard of using Java as a scripting language before this post."
Vampire: the masquerade, used java embedded in the game engine too, but i think they let it take over ALL game logic.
Also, think of the scripting found in Quake3 for example, this is also, JUST like java, a Virtual Machine running embedded in Quake 3, and scripts are compiled to this virtual machines "macinecode", before being executed on the virtual machine inside the program.

"can the Java code do basically anything it could do in a regular Java application?"

Yes, i think so, unless you limit the scripts by way of adjusting settings on the JVM itself when you invoke it(its possible to set the class path, that way you could limit the classes the script can use to the one distributed with the game, but of course that doesnt mean people cant just copy the rest into your script dir). Thats also why im interested in ways to limit the script. I would imagine that restricting file I/O is easy, but im not sure about things such as AWT/Swing and the sound system...

to LessBread:
Thanks for the links, ill have a look at it!

Share this post


Link to post
Share on other sites
Just had a quick look at Spider Monkey java-script stuff. It seems to be easier to handle than Java, so im probaby going to try it out.
I have some worries though(but these goes for Java as well), the tutorial shows how to use native methods in JS, but there is something i dont understand.
Say my program executes a java-script, the java-script calls one of the natively defined methods, which might be getNearestEnemy(). What is important is that this method should be called in the program instance(or whatever its called) which launched the script, not a new program instance.

For example:

int number = 0;

int getNumber(/* java-script context etc */)
{
return number;
}

int main()
{
number = 1;
/* setup java-script and call a script*/
}

Now lets say getNumber is called from the script, will it return 0 or 1 as it should? Im sorry if this question is so stupid it makes you laugh but ive been worrying about it.

My second worry is that almost ALL my methods will be contained in classes, and im not sure if either Java or java-script will be able to call functions located in classes...

to CGame Programmer:
As a side note, concerning your question about how the Java program calls external functions. Well it doesnt seem to be to hard you just make something like a prototype function on the Java side(declaring the method as native) and then implement it in C/C++. But as you can see from my confusion just above, im not exactly sure how its done.

Share this post


Link to post
Share on other sites
Pardon me for replying to myself AGAIN
But i just tried out the java-script stuff, i made a method test that changes a variable(number) to 1 on C side and can be called by the script. The program returns the value of the number variable.And it worked, it actually returns 1, ie, number == 1.
(i know return values are a nasty way of doing it, but it was just a quick test

So now it just have to find out whether or not it can call member functions, but if it cant, i can probably find a way out of it(like NOT putting the gamelogic in a class

EDIT: Also notice, that you can compile scripts before executing them, sounds pretty smart. I just hope the whole thing is optimized enough.

Here is the code:

#define XP_PC
#include "jsapi.h"

int number = 0;

static JSBool test(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
number = 1;
return true;
}

int main()
{
JSVersion version;
JSRuntime* runtime;
JSContext* context;
JSObject* global;
JSObject* it;
JSClass global_class =
{
"global",0,
JS_PropertyStub,JS_PropertyStub,JS_PropertyStub,JS_PropertyStub,
JS_EnumerateStub,JS_ResolveStub,JS_ConvertStub,JS_FinalizeStub
};
char* script = "test();";
jsval returnValue;
JSString* str;
JSBool ok;
JSScript* compiledScript;

runtime = JS_NewRuntime(8L * 1024L * 1024L);
if(!runtime) return 1; /* something went wrong */

context = JS_NewContext(runtime, 8192); /* what is 8192? stack size? */
if(context == NULL) return 1;

global = JS_NewObject(context, &global_class, NULL, NULL);
JS_InitStandardClasses(context, global);

JS_DefineFunction(context, global, "test", test, 0, 0);

compiledScript = JS_CompileScript(context, global, script, 7,NULL, NULL);
if(compiledScript == NULL) return 3;
JS_ExecuteScript(context, global, compiledScript, &returnValue);

return number;
}

Edited by - ziphnor on February 23, 2002 12:41:42 PM

Share this post


Link to post
Share on other sites
Cool. I''m glad it worked out for you. If the compiled scripts aren''t optimized enough for you - at least you have access to the source and can hazard a fix if you want. There''s also the jseng newsgroup available to answer more advanced questions.

Share this post


Link to post
Share on other sites
I think im just going to be glad i got it to work, and not make too much of a hassle about the speed of it, its probably 10 times faster than anything i could have written myself

Share this post


Link to post
Share on other sites
I do have some demos of my scripting engine but no "binaray only" yet because I''m using the demos to teach others to use my scripting engine. It''s going to be a retail, so I can''t release the source to anyone other than those I have contracts with. But when I get a chance, I will release some binary only demos to show off the technology.

email me and maybe we can set something up.

But anyways here''s a few tips on creating your own engine. Java to Java code is fast, almost as fast as C++ (I''ve done my own tests do I know this is true). Java to C++ calls are slightly slower, and C++ to Java calls are the slowest. So your goal should be to limit the number of C++ to Java calls. Keep in mind this is all relative, a slow C++ to Java JNI call is still faster than what you can create using lua, or something else, but it is slower than pure C++.

A fairly fast way to do things:
1. Create a Java object manager class. Which keeps track of all the "scripted" java objects floating around in your game.

2. The object manager has a function called TickAllObjects(), which tells the object manager to "Tick" all the scripted objects. Thats really my primary C++ to Java function call.

3. Have the objects each write there pertinant data to the C++ side (Java to C++ calls are fairly fast).

4. Keep a "data module" in C++ memory, that the java objects write their data to. Now your C++ graphics engine can look at that data to know how to render the objects, or whatever.

Now this is an extremely simplified version of what you need to do, but it might give you a place to start.

However, for simplified reasons, you really can get away with making C++ to Java calls. It''s still fairly fast. Meaning you could from the C++ side:
1. Create an instance of the Java scripted object.
2. Tell the object to update. (Tick the object).
3. Make JNI function calls to the various Get and Set routines your object has.
4. And continue on with your game logic.


Now this second approach isn''t as fast as the first approach, but it will still probably execute fast enough to work for a game.

PS: Someone mention version 1.4 adds some stuff for sharing memory between java and C++, I''ll be looking in to that myself.

-Shaft
shaft90210@aol.com

Share this post


Link to post
Share on other sites
What about doing the reverse? Isn''t it possible to put rendering and performance-vital code into a DLL and write the ''main'' portion of your engine in Java. This way you don''t have many, if any, C++ -> Java calls.

No, HTML is not an OO language.

Share this post


Link to post
Share on other sites
No matter how you split your game you have the same problem. Getting the data from one language to the next. So even if everything is in java except the graphics, you still need a way to get the data to the graphics engine.

I whole heartly recommend doing your own tests as far as speed. I say C++ to Java is slower because it is the least optimized by the compiler makers. But newer compilers who knows.

And seriously folks, no matter how you do it, you are probably going to get better performance than lua, or some other scripting language. In every game released so far, the scripting engine is slow. But since computers are so fast, and most graphics are offloaded to the GPU, your scripting engine needs to be EXTREMELY slow for it to affect the performance of your game.

This thread has motivated me to start writing an article on creating a scripting engine in Java. I have a ton of .NET stuff to do at work, but after that I''ll get started. .

Here''s a quick answer to someone else''s question. Yes you can limit what executes in your scripting engine for security purposes. It wouldn''t be to cool to install a MOD and have it delete your hard drive . In fact you have all the security power Netscape and applet machines have. When you load up a new class you get to determine it''s sand box. Most likely when you load up a class you don''t want it to have any system access. A MOD object doesn''t need anything from your system to determine it''s hitpoints or someother game related value.

If you get bored, take a look at a SecurtyManager class in Java. That''s how it''s done. I''ll be sure to include it in my article :0.

Share this post


Link to post
Share on other sites
Hey there.

We are doing exactly what Masonium is saying in a game we are developing. We start the engine from Java, which loads the DLL''s we need and starts up DirectX and other native modules. All the gamelogic and scripting is done from Java through JNI.
This is working pretty good, both programming and speed-wise.

Share this post


Link to post
Share on other sites
Thats what I was considering...
Give us a link Gandalfy!

***Witty Remark Goes Here***

Share this post


Link to post
Share on other sites

  • Advertisement