noxworld-dev / opennox

OpenNox main repository.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

NS3: Allow calling into legacy NoxScript runtime

dennwc opened this issue · comments

Currently the interop between new and old scripts is very limited. It is allowed to only share the data via the map itself, e.g. operate on the same objects on the map (given their name/ID).

It is also possible to have either a legacy NoxScript trigger or a new NS3/4 trigger function. But not both.

It would useful to allow at least calling from new NS scripts to the legacy script runtime.

So far it seems we will need 3 new functions:

// CallFunc calls the function in the legacy NoxScript runtime.
// It will automatically convert arguments to the corresponding NoxScript equivalents.
func CallFunc(name string, args ...any) Value

// GetGlobalVar returns a global NoxScript variables by its index.
// The Value return type can be converted to a desired Go type.
func GetGlobalVar(gvar int) Value

// GetFuncVar returns a function local NoxScript variables by its index and function name.
// The Value return type can be converted to a desired Go type.
func GetFuncVar(fnc string, vari int) Value

All the string/float conversions can be hidden behind the Value type. We don't have any limit on the string table size, thus it should be safe to just convert values back and forth.

For example, to get a string variable:

s := GetGlobalVar(10).String()

Will all there functions, it would be possible to slowly migrate existing maps to NS scripts - one (top level) function at a time. And call legacy functions as needed:

CallFunc("SomeLegacyFunc", obj1, "some string")

Functions calls might be frequent, so it might be necessary to allow optimizations like caching the function handle first and then calling it:

// store function handle
var SomeLegacyFunc = GetFunc("SomeLegacyFunc")

func DoSomething() {
   SomeLegacyFunc.Call(obj, "some text")
}

It could be even easier with generics:

// real Go function!
var SomeLegacyFunc = GetFunc[func(Obj, string)]("SomeLegacyFunc")

func DoSomething() {
   SomeLegacyFunc(obj, "some text")
}

...but I don't think our Go interpretter supports generics, unfortunately.