About Me

Michael Zucchi

 B.E. (Comp. Sys. Eng.)

  also known as Zed
  to his mates & enemies!

notzed at gmail >
fosstodon.org/@notzed >

Tags

android (44)
beagle (63)
biographical (104)
blogz (9)
business (1)
code (77)
compilerz (1)
cooking (31)
dez (7)
dusk (31)
esp32 (4)
extensionz (1)
ffts (3)
forth (3)
free software (4)
games (32)
gloat (2)
globalisation (1)
gnu (4)
graphics (16)
gsoc (4)
hacking (459)
haiku (2)
horticulture (10)
house (23)
hsa (6)
humour (7)
imagez (28)
java (231)
java ee (3)
javafx (49)
jjmpeg (81)
junk (3)
kobo (15)
libeze (7)
linux (5)
mediaz (27)
ml (15)
nativez (10)
opencl (120)
os (17)
panamaz (5)
parallella (97)
pdfz (8)
philosophy (26)
picfx (2)
players (1)
playerz (2)
politics (7)
ps3 (12)
puppybits (17)
rants (137)
readerz (8)
rez (1)
socles (36)
termz (3)
videoz (6)
vulkan (3)
wanki (3)
workshop (3)
zcl (4)
zedzone (26)
Tuesday, 05 March 2013, 05:44

Scripting thoughts

So last night I had a bit of a look at how a javascript thing might work for the game engine. It tempered some of my enthusiasm but I also need to adjust my expectations. Security is a pain, and JavaScript itself turns out a bit ugly, although i can probably do something about that. Strangely the script engine doesn't let you implement new functions for the script? That's probably the weirdest thing about it; you can add objects but not top-level functions. The fact the javascript engine keeps variables around between invocations also makes things a bit more interesting, and not all in a good way.

I had a look at how I might implement a simple existing item: absinthe (it's not a drink i'm a fan of btw so the choice is arbitrary).

The existing item is defined over multiple separate files: the item descriptor and one for each script - 3 total files for absinthe.

Object

Obvious is to implement it as a full object with methods. The object name would match the script name, and all objects could be loaded at once into the script engine.

var absinthe = {
    onUse: function(thing) {
        thing.emote('wails: oh, my head!');
        if (thing.getInte() > 10)
            thing.incrInte(-1);
        thing.remove('absinthe');
    },
    onDrop: function(thing) {
        thing.order("get absinthe");
        thing.remove('absinthe');
    }
};

Drawback here is the scaffolding required. It's almost to the point that you may as well just use Java directly. I will probably do that too.

If the script engine were a proper execution container then things could be very interesting - the state could live inside it too, but I don't want to go down that path.

Script fragments

This is similar to the existing system, separate standalone scripts define each action. They are referenced via names in the objects.

absinthe_use:

    thing.emote('wails: oh, my head!');
    if (thing.getInte() > 10)
       thing.incrInte(-1);
    thing.remove('absinthe');

absinthe_drop:

    thing.order("get absinthe");
     thing.remove('absinthe');

It has similar drawbacks and advantages to the existing system - lots of little files to manage, separated logic, but also isolation and simplicity. It does allow for pre-compiled scripts though.

Script of functions

Here the script just defines top-level functions. It makes it a bit easier for the user to develop as they don't need to include all the scaffolding.

var onUse =function(thing) {
    thing.emote('wails: oh, my head!');
    if (thing.getInte() > 10)
        thing.incrInte(-1);
    thing.remove('absinthe');
};
var onDrop = function(thing) {
    thing.order("get absinthe");
    thing.remove('absinthe');
};

This approach has the drawback that the script must be parsed and executed separately, and must be parsed and executed every time.

Scripted actions

A compromise between the first two is to have a single script but also pass the script action to the script and let it decide what to do. e.g. use a switch statement. i.e. lets one put all behaviour in one file, but 'simplifies' the scaffolding.

switch (action) {
case 'use':
    thing.emote('wails: oh, my head!');
    if (thing.getInte() > 10)
       thing.incrInte(-1);
    thing.remove('absinthe');
    break;
case 'drop':
    thing.order("get absinthe");
    thing.remove('absinthe');
    break;
}

Problem is that it doesn't really simplify the scaffolding, although it allows for precompiled scripts.

Thoughts

One problem is i'm thinking about the scripting system from the wrong viewpoint - more of a library of potentially compiled functions rather than thinking of it as scripts. I need to shift my thinking because they really should just be scripts, and not self-contained applications. If I support Java classes to define behaviour as well then efficiency of the scripting language itself isn't of a primary concern.

The fact that Java can't directly define functions sucks a bit - for example the "thing." prefix to every call. But I guess i can hide that with some simple global functions I inject on my own which hide the details for the main target object.

At this point i'm leaning toward the second option - i.e. much the same as the existing system. But I will look at some techniques for simplifying their configuration such as convention-based lookup rather than needing a pile of settings for each object. A convention-based mechanism would let me support multiple mechanisms without needing to change the file formats.

I might need to let this stew a bit for the moment, and whilst that is coalescing have a look at the multi-map/layer stuff which will be more fun to hack on too.

Tagged dusk, hacking, java.
Layers & multiple maps | Binary Protocol
Copyright (C) 2019 Michael Zucchi, All Rights Reserved. Powered by gcc & me!