feat(lua): added delay global + fixed issues with waiting

This commit is contained in:
maelstrom 2025-05-07 01:46:19 +02:00
parent 13cad8e01a
commit 626be7107f
3 changed files with 43 additions and 24 deletions

View file

@ -8,11 +8,11 @@
#include "objects/datamodel.h"
#include "datatypes/ref.h"
#include "lua.h"
#include <luajit-2.1/lauxlib.h>
#include <luajit-2.1/lua.h>
#include <algorithm>
#include <memory>
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<Workspace>()).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;
}

View file

@ -7,7 +7,6 @@
#include <cstdint>
#include <ctime>
#include <chrono>
#include <luajit-2.1/lua.h>
#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)

View file

@ -58,6 +58,7 @@ ScriptDocument::ScriptDocument(std::shared_ptr<Script> script, QWidget* parent):
scintilla->setMarginsBackgroundColor(palette().window().color());
scintilla->setCaretForegroundColor(palette().text().color());
scintilla->setFont(font);
scintilla->setTabWidth(4);
scintilla->setText(QString::fromStdString(script->source));