2021-11-30 21:29:18 -06:00
|
|
|
#include "script.h"
|
|
|
|
|
2022-08-03 17:00:00 -05:00
|
|
|
#include "log.h"
|
2023-05-12 13:22:05 -05:00
|
|
|
#include "stdio.h"
|
2022-06-21 12:48:19 -05:00
|
|
|
|
2023-01-10 14:02:24 -06:00
|
|
|
#include "ffi.h"
|
|
|
|
#include "font.h"
|
2022-06-21 12:48:19 -05:00
|
|
|
|
2023-01-05 15:34:15 -06:00
|
|
|
#include "ftw.h"
|
|
|
|
|
2022-12-19 09:12:34 -06:00
|
|
|
#include "stb_ds.h"
|
|
|
|
|
2023-01-13 13:07:44 -06:00
|
|
|
#include "sys/stat.h"
|
|
|
|
#include "sys/types.h"
|
2023-05-12 13:22:05 -05:00
|
|
|
#include "time.h"
|
2023-01-13 13:07:44 -06:00
|
|
|
|
2023-04-18 14:49:17 -05:00
|
|
|
JSContext *js = NULL;
|
2023-04-18 17:58:44 -05:00
|
|
|
JSRuntime *rt = NULL;
|
2021-11-30 21:29:18 -06:00
|
|
|
|
2023-01-05 15:34:15 -06:00
|
|
|
static int load_prefab(const char *fpath, const struct stat *sb, int typeflag) {
|
2023-05-12 13:22:05 -05:00
|
|
|
if (typeflag != FTW_F)
|
|
|
|
return 0;
|
2023-01-05 15:34:15 -06:00
|
|
|
|
2023-05-12 13:22:05 -05:00
|
|
|
if (!strcmp(".prefab", strrchr(fpath, '.')))
|
|
|
|
script_dofile(fpath);
|
2023-01-05 15:34:15 -06:00
|
|
|
|
2023-05-12 13:22:05 -05:00
|
|
|
return 0;
|
2023-01-05 15:34:15 -06:00
|
|
|
}
|
|
|
|
|
2023-05-12 13:22:05 -05:00
|
|
|
void script_startup() {
|
|
|
|
rt = JS_NewRuntime();
|
|
|
|
JS_SetMaxStackSize(rt, 0);
|
|
|
|
js = JS_NewContext(rt);
|
|
|
|
ffi_load();
|
2023-04-22 14:07:37 -05:00
|
|
|
}
|
2023-01-05 15:34:15 -06:00
|
|
|
|
2023-04-28 12:49:18 -05:00
|
|
|
JSValue num_cache[100] = {0};
|
|
|
|
|
2023-04-22 14:07:37 -05:00
|
|
|
void script_init() {
|
2023-05-12 13:22:05 -05:00
|
|
|
/* Load all prefabs into memory */
|
|
|
|
script_dofile("scripts/engine.js");
|
2023-04-28 12:49:18 -05:00
|
|
|
|
2023-05-12 13:22:05 -05:00
|
|
|
for (int i = 0; i < 100; i++)
|
|
|
|
num_cache[i] = int2js(i);
|
2021-11-30 21:29:18 -06:00
|
|
|
}
|
|
|
|
|
2022-08-01 13:32:58 -05:00
|
|
|
void script_run(const char *script) {
|
2023-04-19 15:16:35 -05:00
|
|
|
JS_FreeValue(js, JS_Eval(js, script, strlen(script), "script", 0));
|
2022-02-06 10:14:57 -06:00
|
|
|
}
|
2022-08-01 13:32:58 -05:00
|
|
|
|
2023-04-28 12:49:18 -05:00
|
|
|
struct callee stacktrace_callee;
|
|
|
|
|
2023-01-13 13:07:44 -06:00
|
|
|
time_t file_mod_secs(const char *file) {
|
2023-05-12 13:22:05 -05:00
|
|
|
struct stat attr;
|
|
|
|
stat(file, &attr);
|
|
|
|
return attr.st_mtime;
|
2023-01-13 13:07:44 -06:00
|
|
|
}
|
|
|
|
|
2023-05-12 13:22:05 -05:00
|
|
|
void js_stacktrace() {
|
2023-04-28 12:49:18 -05:00
|
|
|
call_callee(&stacktrace_callee);
|
|
|
|
return;
|
2023-04-25 11:55:33 -05:00
|
|
|
}
|
|
|
|
|
2023-05-12 13:22:05 -05:00
|
|
|
void js_dump_stack() {
|
2023-04-28 12:49:18 -05:00
|
|
|
js_stacktrace();
|
|
|
|
return;
|
2023-05-12 13:22:05 -05:00
|
|
|
|
2023-04-24 17:22:18 -05:00
|
|
|
JSValue exception = JS_GetException(js);
|
2023-04-25 14:59:26 -05:00
|
|
|
if (JS_IsNull(exception)) return;
|
2023-04-24 17:22:18 -05:00
|
|
|
JSValue val = JS_GetPropertyStr(js, exception, "stack");
|
|
|
|
if (!JS_IsUndefined(val)) {
|
|
|
|
const char *name = JS_ToCString(js, JS_GetPropertyStr(js, exception, "name"));
|
|
|
|
const char *msg = JS_ToCString(js, JS_GetPropertyStr(js, exception, "message"));
|
2023-05-12 13:22:05 -05:00
|
|
|
const char *stack = JS_ToCString(js, val);
|
|
|
|
YughError("%s :: %s\n%s", name, msg, stack);
|
|
|
|
|
|
|
|
JS_FreeCString(js, name);
|
|
|
|
JS_FreeCString(js, msg);
|
|
|
|
JS_FreeCString(js, stack);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int js_print_exception(JSValue v) {
|
|
|
|
if (JS_IsException(v)) {
|
|
|
|
JSValue exception = JS_GetException(js);
|
|
|
|
JSValue val = JS_GetPropertyStr(js, exception, "stack");
|
|
|
|
if (!JS_IsUndefined(val)) {
|
|
|
|
const char *name = JS_ToCString(js, JS_GetPropertyStr(js, exception, "name"));
|
|
|
|
const char *msg = JS_ToCString(js, JS_GetPropertyStr(js, exception, "message"));
|
|
|
|
const char *stack = JS_ToCString(js, val);
|
|
|
|
YughWarn("%s :: %s\n%s", name, msg, stack);
|
|
|
|
|
|
|
|
JS_FreeCString(js, name);
|
|
|
|
JS_FreeCString(js, msg);
|
|
|
|
JS_FreeCString(js, stack);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2023-04-19 15:16:35 -05:00
|
|
|
}
|
|
|
|
|
2022-11-20 15:50:14 -06:00
|
|
|
int script_dofile(const char *file) {
|
2023-05-12 13:22:05 -05:00
|
|
|
YughInfo("Doing script %s", file);
|
|
|
|
const char *script = slurp_text(file);
|
|
|
|
if (!script) {
|
|
|
|
YughError("Can't find file %s.", file);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
JSValue obj = JS_Eval(js, script, strlen(script), file, 0);
|
|
|
|
js_print_exception(obj);
|
|
|
|
JS_FreeValue(js, obj);
|
2023-01-13 13:07:44 -06:00
|
|
|
|
2023-05-12 13:22:05 -05:00
|
|
|
return file_mod_secs(file);
|
2022-08-03 17:00:00 -05:00
|
|
|
}
|
|
|
|
|
2023-02-02 17:52:15 -06:00
|
|
|
/* env is an object in the scripting environment;
|
|
|
|
s is the function to call on that object
|
|
|
|
*/
|
2023-04-18 17:58:44 -05:00
|
|
|
void script_eval_w_env(const char *s, JSValue env) {
|
2023-04-19 15:16:35 -05:00
|
|
|
JSValue v = JS_EvalThis(js, env, s, strlen(s), "internal", 0);
|
|
|
|
js_print_exception(v);
|
|
|
|
JS_FreeValue(js, v);
|
2022-08-07 01:43:45 -05:00
|
|
|
}
|
|
|
|
|
2023-05-12 13:22:05 -05:00
|
|
|
void script_call_sym(JSValue sym) {
|
2023-04-19 16:58:17 -05:00
|
|
|
struct callee c;
|
|
|
|
c.fn = sym;
|
|
|
|
c.obj = JS_GetGlobalObject(js);
|
|
|
|
call_callee(&c);
|
2023-02-28 17:03:28 -06:00
|
|
|
}
|
|
|
|
|
2023-05-12 13:22:05 -05:00
|
|
|
JSValue js_callee_exec(struct callee *c, int argc, JSValue *argv) {
|
2023-04-19 15:16:35 -05:00
|
|
|
JSValue ret = JS_Call(js, c->fn, c->obj, argc, argv);
|
|
|
|
js_print_exception(ret);
|
|
|
|
JS_FreeValue(js, ret);
|
2023-04-28 20:55:24 -05:00
|
|
|
return JS_NULL;
|
2023-01-11 16:57:34 -06:00
|
|
|
}
|
|
|
|
|
2023-02-02 17:52:15 -06:00
|
|
|
void call_callee(struct callee *c) {
|
2023-04-19 15:16:35 -05:00
|
|
|
js_callee_exec(c, 0, NULL);
|
2023-02-02 17:52:15 -06:00
|
|
|
}
|
|
|
|
|
2023-05-12 13:22:05 -05:00
|
|
|
void callee_dbl(struct callee c, double d) {
|
2023-04-18 17:58:44 -05:00
|
|
|
JSValue v = num2js(d);
|
|
|
|
js_callee_exec(&c, 1, &v);
|
2023-04-19 15:16:35 -05:00
|
|
|
JS_FreeValue(js, v);
|
2023-02-02 17:52:15 -06:00
|
|
|
}
|
2023-01-13 22:08:39 -06:00
|
|
|
|
2023-05-12 13:22:05 -05:00
|
|
|
void callee_int(struct callee c, int i) {
|
2023-04-18 17:58:44 -05:00
|
|
|
JSValue v = int2js(i);
|
|
|
|
js_callee_exec(&c, 1, &v);
|
2023-04-19 15:16:35 -05:00
|
|
|
JS_FreeValue(js, v);
|
2023-02-13 08:30:35 -06:00
|
|
|
}
|
|
|
|
|
2023-05-12 13:22:05 -05:00
|
|
|
void callee_vec2(struct callee c, cpVect vec) {
|
2023-04-18 17:58:44 -05:00
|
|
|
JSValue v = vec2js(vec);
|
|
|
|
js_callee_exec(&c, 1, &v);
|
2023-04-19 15:16:35 -05:00
|
|
|
JS_FreeValue(js, v);
|
2023-01-09 07:21:45 -06:00
|
|
|
}
|
|
|
|
|
2023-05-12 13:22:05 -05:00
|
|
|
void script_callee(struct callee c, int argc, JSValue *argv) {
|
2023-04-19 15:16:35 -05:00
|
|
|
js_callee_exec(&c, argc, argv);
|
2022-12-20 19:34:22 -06:00
|
|
|
}
|
|
|
|
|
2023-04-19 15:16:35 -05:00
|
|
|
static struct callee update_callee;
|
|
|
|
void register_update(struct callee c) {
|
|
|
|
update_callee = c;
|
2022-12-20 19:34:22 -06:00
|
|
|
}
|
2023-04-19 15:16:35 -05:00
|
|
|
void call_updates(double dt) {
|
|
|
|
callee_dbl(update_callee, dt);
|
2023-03-17 10:25:35 -05:00
|
|
|
}
|
|
|
|
|
2023-04-19 15:16:35 -05:00
|
|
|
static struct callee gui_callee;
|
|
|
|
void register_gui(struct callee c) { gui_callee = c; }
|
|
|
|
void call_gui() { js_callee_exec(&gui_callee, 0, NULL); }
|
2023-01-19 13:06:32 -06:00
|
|
|
|
2023-04-19 15:16:35 -05:00
|
|
|
static struct callee nk_gui_callee;
|
|
|
|
void register_nk_gui(struct callee c) { nk_gui_callee = c; }
|
|
|
|
void call_nk_gui() { js_callee_exec(&nk_gui_callee, 0, NULL); }
|
2023-03-17 10:25:35 -05:00
|
|
|
|
2023-04-19 15:16:35 -05:00
|
|
|
static struct callee physupdate_callee;
|
2023-05-12 13:22:05 -05:00
|
|
|
void register_physics(struct callee c) { physupdate_callee = c; }
|
2023-04-19 15:16:35 -05:00
|
|
|
void call_physics(double dt) { callee_dbl(physupdate_callee, dt); }
|
|
|
|
|
|
|
|
struct callee debug_callee;
|
|
|
|
void register_debug(struct callee c) { debug_callee = c; }
|
|
|
|
void call_debugs() { JS_Call(js, debug_callee.fn, debug_callee.obj, 0, NULL); }
|