diff --git a/luprex/Makefile b/luprex/Makefile index 5dd341f9..d2906f6c 100644 --- a/luprex/Makefile +++ b/luprex/Makefile @@ -71,6 +71,7 @@ OBJ_CORE=\ build/$(OS)/core/planemap.obj\ build/$(OS)/core/pprint.obj\ build/$(OS)/core/luaconsole.obj\ + build/$(OS)/core/luavector.obj\ build/$(OS)/core/idalloc.obj\ build/$(OS)/core/globaldb.obj\ build/$(OS)/core/sched.obj\ diff --git a/luprex/cpp/core/luavector.cpp b/luprex/cpp/core/luavector.cpp new file mode 100644 index 00000000..6a363fbd --- /dev/null +++ b/luprex/cpp/core/luavector.cpp @@ -0,0 +1,41 @@ +#include "luastack.hpp" + +LuaDefine(vec, "(x, y, z)", + "|Create a vector." + "|" + "|The function 'vec' is shorthand for vector.create." + "|") { + LuaRet result; + LuaArg lx, ly, lz; + LuaVar vclass; + LuaDefStack LS(L, result, lx, ly, lz, vclass); + double x = LS.cknumber(lx); + double y = LS.cknumber(ly); + double z = LS.cknumber(lz); + LS.createtable(result, 3, 0); + LS.rawset(result, 1, x); + LS.rawset(result, 2, y); + LS.rawset(result, 3, z); + LS.getclass(vclass, "vector"); + LS.setmetatable(result, vclass); + return LS.result(); +} + +LuaDefine(vector_create, "(x, y, z)", + "|Create a vector." + "|") { + LuaRet result; + LuaArg lx, ly, lz; + LuaVar vclass; + LuaDefStack LS(L, result, lx, ly, lz, vclass); + double x = LS.cknumber(lx); + double y = LS.cknumber(ly); + double z = LS.cknumber(lz); + LS.createtable(result, 3, 0); + LS.rawset(result, 1, x); + LS.rawset(result, 2, y); + LS.rawset(result, 3, z); + LS.getclass(vclass, "vector"); + LS.setmetatable(result, vclass); + return LS.result(); +} diff --git a/luprex/cpp/core/luavector.hpp b/luprex/cpp/core/luavector.hpp new file mode 100644 index 00000000..fa0acdca --- /dev/null +++ b/luprex/cpp/core/luavector.hpp @@ -0,0 +1,6 @@ +/////////////////////////////////////////////////////////////////////// +// +// Lua Vectors - this file contains functions that are entirely +// for lua, no C++ interface, so this header file is empty. +// +/////////////////////////////////////////////////////////////////////// diff --git a/luprex/cpp/core/world-core.cpp b/luprex/cpp/core/world-core.cpp index 2f7e1bf1..32be1723 100644 --- a/luprex/cpp/core/world-core.cpp +++ b/luprex/cpp/core/world-core.cpp @@ -470,6 +470,7 @@ void World::probe_lua_call(int64_t place_id, int64_t actor_id, std::string_view if (!LS.isfunction(lfunc)) return; // Call the closure. + int calltop = lua_gettop(L); lua_pushvalue(L, lfunc.index()); int nargs = 0; try { @@ -482,20 +483,35 @@ void World::probe_lua_call(int64_t place_id, int64_t actor_id, std::string_view } open_lthread_state(actor_id, place_id, 0, false, true); - eng::string msg = traceback_pcall(L, nargs, 1); - + eng::string msg = traceback_pcall(L, nargs, LUA_MULTRET); + LuaExtraArgs returnvalues(calltop + 1, lua_gettop(L) - calltop); + // Send any prints to the console. eng::string prints = lthread_prints_->str(); lthread_prints_.reset(); util::dprint(prints); if (msg.empty()) { - lua_replace(L, retvec.index()); - if (LS.istable(retvec)) { - for (int i = 1 ; ; i++) { - LS.rawget(retval, retvec, i); - bool ok = encode_simple_dynamic(LS, retval, retvals); - if (!ok) break; + bool ok = true; + for (int i = 0; ok && (i < returnvalues.size()); i++) { + LS.set(retvec, returnvalues[i]); + + // If it's a general table without an MT, then + // treat it as a list of return values. + bool is_compound = false; + if (LS.xtype(retvec) == LUA_TT_GENERAL) { + LS.getmetatable(mt, retvec); + if (LS.isnil(mt)) is_compound = true; + } + + if (is_compound) { + for (int j = 1; ok; j++) { + LS.rawget(retval, retvec, j); + if (LS.isnil(retval)) break; + ok = encode_simple_dynamic(LS, retval, retvals); + } + } else { + ok = encode_simple_dynamic(LS, retvec, retvals); } } } else { diff --git a/luprex/lua/login.lua b/luprex/lua/login.lua index 99cb59a6..74a0b118 100644 --- a/luprex/lua/login.lua +++ b/luprex/lua/login.lua @@ -30,6 +30,6 @@ function engio.printhi(a1, a2, a3, a4, a5) end function engio.retthree(a1, a2) - return { 5, {3, 4, 5}, "Howdy" } + return 7, vec(8,9,10), "Yo" end