diff options
Diffstat (limited to 'indra/newview')
-rw-r--r-- | indra/newview/llluamanager.cpp | 93 | ||||
-rw-r--r-- | indra/newview/llluamanager.h | 30 |
2 files changed, 103 insertions, 20 deletions
diff --git a/indra/newview/llluamanager.cpp b/indra/newview/llluamanager.cpp index 596d8cab56..44c7a6ba3b 100644 --- a/indra/newview/llluamanager.cpp +++ b/indra/newview/llluamanager.cpp @@ -28,6 +28,7 @@ #include "llviewerprecompiledheaders.h" #include "llluamanager.h" +#include "llcoros.h" #include "llerror.h" #include "lleventcoro.h" #include "lua_function.h" @@ -55,6 +56,14 @@ extern LLUIListener sUIListener; #include <string_view> #include <vector> +lua_function(sleep) +{ + F32 seconds = lua_tonumber(L, -1); + lua_pop(L, 1); + llcoro::suspendUntilTimeout(seconds); + return 0; +}; + /* // This function consumes ALL Lua stack arguments and returns concatenated // message string @@ -262,21 +271,34 @@ lua_function(await_event) void LLLUAmanager::runScriptFile(const std::string& filename, script_finished_fn cb) { - std::string desc{ stringize("runScriptFile('", filename, "')") }; - LLCoros::instance().launch(desc, [desc, filename, cb]() - { - LuaState L(desc, cb); + // A script_finished_fn is used to initialize the LuaState. + // It will be called when the LuaState is destroyed. + LuaState L(cb); + runScriptFile(L, filename); +} - auto LUA_sleep_func = [](lua_State *L) - { - F32 seconds = lua_tonumber(L, -1); - lua_pop(L, 1); - llcoro::suspendUntilTimeout(seconds); - return 0; - }; +void LLLUAmanager::runScriptFile(const std::string& filename, script_result_fn cb) +{ + LuaState L; + // A script_result_fn will be called when LuaState::expr() completes. + runScriptFile(L, filename, cb); +} - lua_register(L, "sleep", LUA_sleep_func); +std::pair<int, LLSD> LLLUAmanager::waitScriptFile(LuaState& L, const std::string& filename) +{ + LLCoros::Promise<std::pair<int, LLSD>> promise; + auto future{ LLCoros::getFuture(promise) }; + runScriptFile(L, filename, + [&promise](int count, LLSD result) + { promise.set_value({ count, result }); }); + return future.get(); +} +void LLLUAmanager::runScriptFile(LuaState& L, const std::string& filename, script_result_fn cb) +{ + std::string desc{ stringize("runScriptFile('", filename, "')") }; + LLCoros::instance().launch(desc, [&L, desc, filename, cb]() + { llifstream in_file; in_file.open(filename.c_str()); @@ -284,17 +306,51 @@ void LLLUAmanager::runScriptFile(const std::string& filename, script_finished_fn { std::string text{std::istreambuf_iterator<char>(in_file), std::istreambuf_iterator<char>()}; - L.checkLua(lluau::dostring(L, desc, text)); + auto [count, result] = L.expr(desc, text); + if (cb) + { + cb(count, result); + } } else { - LL_WARNS("Lua") << "unable to open script file '" << filename << "'" << LL_ENDL; + auto msg{ stringize("unable to open script file '", filename, "'") }; + LL_WARNS("Lua") << msg << LL_ENDL; + if (cb) + { + cb(-1, msg); + } } }); } void LLLUAmanager::runScriptLine(const std::string& cmd, script_finished_fn cb) { + // A script_finished_fn is used to initialize the LuaState. + // It will be called when the LuaState is destroyed. + LuaState L(cb); + runScriptLine(L, cmd); +} + +void LLLUAmanager::runScriptLine(const std::string& cmd, script_result_fn cb) +{ + LuaState L; + // A script_result_fn will be called when LuaState::expr() completes. + runScriptLine(L, cmd, cb); +} + +std::pair<int, LLSD> LLLUAmanager::waitScriptLine(LuaState& L, const std::string& cmd) +{ + LLCoros::Promise<std::pair<int, LLSD>> promise; + auto future{ LLCoros::getFuture(promise) }; + runScriptLine(L, cmd, + [&promise](int count, LLSD result) + { promise.set_value({ count, result }); }); + return future.get(); +} + +void LLLUAmanager::runScriptLine(LuaState& L, const std::string& cmd, script_result_fn cb) +{ // find a suitable abbreviation for the cmd string std::string_view shortcmd{ cmd }; const size_t shortlen = 40; @@ -305,10 +361,13 @@ void LLLUAmanager::runScriptLine(const std::string& cmd, script_finished_fn cb) shortcmd = stringize(shortcmd.substr(0, shortlen), "..."); std::string desc{ stringize("runScriptLine('", shortcmd, "')") }; - LLCoros::instance().launch(desc, [desc, cmd, cb]() + LLCoros::instance().launch(desc, [&L, desc, cmd, cb]() { - LuaState L(desc, cb); - L.checkLua(lluau::dostring(L, desc, cmd)); + auto [count, result] = L.expr(desc, cmd); + if (cb) + { + cb(count, result); + } }); } diff --git a/indra/newview/llluamanager.h b/indra/newview/llluamanager.h index 08d9876ce2..bed12e358a 100644 --- a/indra/newview/llluamanager.h +++ b/indra/newview/llluamanager.h @@ -27,19 +27,43 @@ #ifndef LL_LLLUAMANAGER_H #define LL_LLLUAMANAGER_H +#include "llsd.h" #include <functional> #include <string> +#include <utility> // std::pair + +class LuaState; class LLLUAmanager { public: + // Pass a callback with this signature to obtain the error message, if + // any, from running a script or source string. Empty msg means success. typedef std::function<void(std::string msg)> script_finished_fn; + // Pass a callback with this signature to obtain the result, if any, of + // running a script or source string. + // count < 0 means error, and result.asString() is the error message. + // count == 0 with result.isUndefined() means the script returned no results. + // count == 1 means the script returned one result. + // count > 1 with result.isArray() means the script returned multiple + // results, represented as the entries of the result array. + typedef std::function<void(int count, const LLSD& result)> script_result_fn; + + static void runScriptFile(const std::string &filename, script_finished_fn cb = {}); + static void runScriptFile(const std::string &filename, script_result_fn cb); + static void runScriptFile(LuaState& L, const std::string &filename, script_result_fn cb = {}); + // Run a Lua script file, and pause the calling coroutine until it completes. + // The return value is the (count, result) pair described above. + static std::pair<int, LLSD> waitScriptFile(LuaState& L, const std::string& filename); - static void runScriptFile(const std::string &filename, script_finished_fn cb = script_finished_fn()); - static void runScriptLine(const std::string &cmd, script_finished_fn cb = script_finished_fn()); + static void runScriptLine(const std::string &cmd, script_finished_fn cb = {}); + static void runScriptLine(const std::string &cmd, script_result_fn cb); + static void runScriptLine(LuaState& L, const std::string &cmd, script_result_fn cb = {}); + // Run a Lua expression string, and pause the calling coroutine until it completes. + // The return value is the (count, result) pair described above. + static std::pair<int, LLSD> waitScriptLine(LuaState& L, const std::string& cmd); static void runScriptOnLogin(); }; - #endif |