64 lines
1.8 KiB
JavaScript
64 lines
1.8 KiB
JavaScript
import { lua, lauxlib, lualib, to_luastring } from "fengari";
|
|
import { ScriptSchedulerService } from "./ScriptSchedulerService.js";
|
|
import { Instance } from "./Instance.js"; // your engine's instance class
|
|
|
|
// Import interop from fengari-interop
|
|
import { push, luaopen_js } from "fengari-interop";
|
|
|
|
export class Script extends Instance {
|
|
constructor(sourceCode) {
|
|
super("Script");
|
|
this.Source = sourceCode;
|
|
this.LuaState = null;
|
|
}
|
|
|
|
Run() {
|
|
const L = lauxlib.luaL_newstate();
|
|
luaopen_js(L);
|
|
lualib.luaL_openlibs(L);
|
|
|
|
// Bridge all engine APIs
|
|
this._registerGlobals(L);
|
|
|
|
// Compile the source
|
|
const status = lauxlib.luaL_loadstring(L, to_luastring(this.Source));
|
|
if (status !== lua.LUA_OK) {
|
|
const err = lua.lua_tojsstring(L, -1);
|
|
throw new Error("Lua load error: " + err);
|
|
}
|
|
|
|
// Create a coroutine thread
|
|
const thread = lua.lua_newthread(L);
|
|
|
|
// Schedule with scheduler
|
|
this._getScheduler().scheduleFengariCoroutine(thread, L);
|
|
this.LuaState = L;
|
|
}
|
|
|
|
_registerGlobals(L) {
|
|
// game global
|
|
push(L, globalThis.game);
|
|
lua.lua_setglobal(L, to_luastring("game"));
|
|
|
|
// task + wait bridge
|
|
lua.lua_pushjsfunction(L, () => {
|
|
const secs = lua.lua_isnumber(L, 1) ? lua.lua_tonumber(L, 1) : 0;
|
|
const yieldVal = JSON.stringify({ wait: secs });
|
|
lua.lua_pushstring(L, to_luastring(yieldVal));
|
|
return lua.lua_yield(L, 1);
|
|
});
|
|
lua.lua_setglobal(L, to_luastring("task_wait"));
|
|
|
|
// Lua API helpers
|
|
lua.lua_pushjsfunction(L, () => {
|
|
const inst = new Instance("Part"); // example
|
|
return inst.LuaBridge(); // converts to Lua table/proxy
|
|
});
|
|
lua.lua_setglobal(L, to_luastring("Instance_new"));
|
|
}
|
|
|
|
_getScheduler() {
|
|
return game.GetService("ScriptSchedulerService");
|
|
}
|
|
}
|