diff --git a/core/src/objects/script.cpp b/core/src/objects/script.cpp index a6dc488..9257f65 100644 --- a/core/src/objects/script.cpp +++ b/core/src/objects/script.cpp @@ -8,11 +8,11 @@ #include "objects/datamodel.h" #include "datatypes/ref.h" #include "lua.h" -#include -#include +#include #include int script_wait(lua_State*); +int script_delay(lua_State*); Script::Script(): Instance(&TYPE) { source = "print \"Hello, world!\"\nwait(1)print \"Wait success! :D\""; @@ -33,18 +33,19 @@ void Script::Run() { // Initialize script globals lua_getglobal(Lt, "_G"); - lua_pushstring(Lt, "game"); Data::InstanceRef(dataModel().value()).PushLuaValue(Lt); - lua_rawset(Lt, -3); + lua_setfield(Lt, -2, "game"); - lua_pushstring(Lt, "workspace"); Data::InstanceRef(dataModel().value()->GetService()).PushLuaValue(Lt); - lua_rawset(Lt, -3); + lua_setfield(Lt, -2, "workspace"); - lua_pushstring(Lt, "wait"); lua_pushlightuserdata(Lt, scriptContext.get()); lua_pushcclosure(Lt, script_wait, 1); - lua_rawset(Lt, -3); + lua_setfield(Lt, -2, "wait"); + + lua_pushlightuserdata(Lt, scriptContext.get()); + lua_pushcclosure(Lt, script_delay, 1); + lua_setfield(Lt, -2, "delay"); lua_pop(Lt, 1); // _G @@ -66,10 +67,27 @@ void Script::Stop() { int script_wait(lua_State* L) { ScriptContext* scriptContext = (ScriptContext*)lua_touserdata(L, lua_upvalueindex(1)); - float secs = luaL_checknumber(L, 1); + float secs = lua_gettop(L) == 0 ? 0.03 : std::max(luaL_checknumber(L, 1), 0.03); scriptContext->PushThreadSleep(L, secs); + lua_pop(L, 1); // pop secs // Yield return lua_yield(L, 0); +} + +int script_delay(lua_State* L) { + ScriptContext* scriptContext = (ScriptContext*)lua_touserdata(L, lua_upvalueindex(1)); + float secs = std::max(luaL_checknumber(L, 1), 0.03); + luaL_checktype(L, 2, LUA_TFUNCTION); + + lua_State* Lt = lua_newthread(L); // Create a new thread + lua_pop(L, 1); // pop the newly created thread so that xmove moves func instead of it into itself + lua_xmove(L, Lt, 1); // move func + lua_pop(L, 1); // pop secs + + // Schedule next run + scriptContext->PushThreadSleep(Lt, secs); + + return 0; } \ No newline at end of file diff --git a/core/src/objects/script/scriptcontext.cpp b/core/src/objects/script/scriptcontext.cpp index 1657dc6..2f240cc 100644 --- a/core/src/objects/script/scriptcontext.cpp +++ b/core/src/objects/script/scriptcontext.cpp @@ -7,7 +7,6 @@ #include #include #include -#include #include "lua.h" static int g_print(lua_State*); @@ -66,13 +65,9 @@ void ScriptContext::InitService() { lua_pop(state, 1); // _G - lua_getregistry(state); - - lua_pushstring(state, "__sleepingThreads"); + lua_pushlightuserdata(state, &sleepingThreads); lua_newtable(state); - lua_rawset(state, -3); - - lua_pop(state, -1); // registry + lua_settable(state, LUA_REGISTRYINDEX); } void ScriptContext::PushThreadSleep(lua_State* thread, float delay) { @@ -88,16 +83,15 @@ void ScriptContext::PushThreadSleep(lua_State* thread, float delay) { // Add to registry so it doesn't get GC'd // https://stackoverflow.com/a/17138663/16255372 - lua_getregistry(state); // registry - lua_pushstring(state, "__sleepingThreads"); - lua_rawget(state, -2); // table + lua_pushlightuserdata(state, &sleepingThreads); + lua_gettable(state, LUA_REGISTRYINDEX); lua_pushthread(thread); // key lua_xmove(thread, state, 1); lua_pushboolean(state, true); // value lua_rawset(state, -3); // set - lua_pop(state, 2); // pop table and registry + lua_pop(state, 1); // pop sleepingThreads } void ScriptContext::RunSleepingThreads() { @@ -109,20 +103,26 @@ void ScriptContext::RunSleepingThreads() { // Time args lua_pushnumber(sleep.thread, float(tu_clock_micros() - sleep.timeYieldedWhen) / 1'000'000); lua_pushnumber(sleep.thread, float(tu_clock_micros()) / 1'000'000); - lua_resume(sleep.thread, 2); + int status = lua_resume(sleep.thread, 2); + if (status > LUA_YIELD) { + Logger::error(lua_tostring(sleep.thread, -1)); + lua_pop(sleep.thread, 1); // Pop return value + } // Remove thread + deleted = true; sleepingThreads.erase(sleepingThreads.begin() + i); // Erase from registry - lua_getregistry(state); // registry - lua_pushstring(state, "__sleepingThreads"); - lua_rawget(state, -2); // table + lua_pushlightuserdata(state, &sleepingThreads); + lua_gettable(state, LUA_REGISTRYINDEX); lua_pushthread(sleep.thread); // key lua_xmove(sleep.thread, state, 1); lua_pushnil(state); lua_rawset(state, -3); // set + + lua_pop(state, 1); // sleepingThreads } if (!deleted) diff --git a/editor/script/scriptdocument.cpp b/editor/script/scriptdocument.cpp index 12fadc3..f873bbe 100644 --- a/editor/script/scriptdocument.cpp +++ b/editor/script/scriptdocument.cpp @@ -58,6 +58,7 @@ ScriptDocument::ScriptDocument(std::shared_ptr