feat(lua): added delay global + fixed issues with waiting
This commit is contained in:
parent
13cad8e01a
commit
626be7107f
3 changed files with 43 additions and 24 deletions
|
@ -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;
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue