From 5b19d407fb50f230d90a9562ffaca752ff3c8732 Mon Sep 17 00:00:00 2001 From: Josh Yelon Date: Thu, 3 Jun 2021 13:29:19 -0400 Subject: [PATCH] Fixed traceback issue, improved animqueue primitives --- luprex/core/cpp/animqueue.cpp | 111 +++++++++++++++++----------------- luprex/core/cpp/animqueue.hpp | 8 ++- luprex/core/cpp/traceback.cpp | 1 + luprex/core/cpp/traceback.hpp | 4 +- luprex/core/cpp/world.cpp | 31 ++-------- luprex/core/cpp/world.hpp | 2 +- luprex/core/lua/player.lua | 13 ++-- 7 files changed, 79 insertions(+), 91 deletions(-) diff --git a/luprex/core/cpp/animqueue.cpp b/luprex/core/cpp/animqueue.cpp index 7168b70b..b1f3d6ca 100644 --- a/luprex/core/cpp/animqueue.cpp +++ b/luprex/core/cpp/animqueue.cpp @@ -62,67 +62,64 @@ AnimQueue::AnimQueue() { clear_steps(); } -void AnimStep::from_lua(lua_State *L, int idx) { +void AnimStep::from_lua_store_string(lua_State *L, int idx, std::string *target, int16_t bits, const char *name) { + if ((bits_ & bits)||(*target != "")) { + luaL_error(L, "specified %s twice", name); + } + if (lua_type(L, idx) != LUA_TSTRING) { + luaL_error(L, "Expected %s to be a string", name); + } + *target = lua_tostring(L, idx); + bits_ |= bits; +} + +void AnimStep::from_lua_store_number(lua_State *L, int idx, float *target, float offset, int16_t bits, const char *name) { + if (bits_ & bits) { + luaL_error(L, "specified %s twice", name); + } + if (lua_type(L, idx) != LUA_TNUMBER) { + luaL_error(L, "Expected %s to be a number", name); + } + *target = lua_tonumber(L, idx) + offset; + bits_ |= bits; +} + +void AnimStep::from_lua(lua_State *L, int idx, const AnimStep &qback) { LuaSpecial tab(idx); - LuaVar value; - LuaStack LS(L, value); + LuaVar key, value; + LuaStack LS(L, key, value); if (!LS.istable(tab)) { luaL_error(L, "animation spec must be a table"); } - - LS.rawget(value, tab, "action"); - if (LS.isstring(value)) { - action_ = LS.ckstring(value); - } else if (!LS.isnil(value)) { - luaL_error(L, "animation action must be a string"); - } - - LS.rawget(value, tab, "facing"); - if (LS.isnumber(value)) { - facing_ = LS.cknumber(value); - bits_ |= HAS_FACING; - } else if (!LS.isnil(value)) { - luaL_error(L, "animation facing must be a number"); - } - - LS.rawget(value, tab, "x"); - if (LS.isnumber(value)) { - xyz_.x = LS.cknumber(value); - bits_ |= HAS_X; - } else if (!LS.isnil(value)) { - luaL_error(L, "animation X coordinate must be a number"); - } - - LS.rawget(value, tab, "y"); - if (LS.isnumber(value)) { - xyz_.y = LS.cknumber(value); - bits_ |= HAS_Y; - } else if (!LS.isnil(value)) { - luaL_error(L, "animation Y coordinate must be a number"); - } - - LS.rawget(value, tab, "z"); - if (LS.isnumber(value)) { - xyz_.z = LS.cknumber(value); - bits_ |= HAS_Z; - } else if (!LS.isnil(value)) { - luaL_error(L, "animation Z coordinate must be a number"); - } - - LS.rawget(value, tab, "graphic"); - if (LS.isstring(value)) { - graphic_ = LS.ckstring(value); - bits_ |= HAS_GRAPHIC; - } else if (!LS.isnil(value)) { - luaL_error(L, "animation graphic must be a string"); - } - - LS.rawget(value, tab, "plane"); - if (LS.isstring(value)) { - plane_ = LS.ckstring(value); - bits_ |= HAS_PLANE; - } else if (!LS.isnil(value)) { - luaL_error(L, "animation plane must be a string"); + LS.set(key, LuaNil); + while (LS.next(tab, key, value)) { + if (!LS.isstring(key)) { + luaL_error(L, "animation specs must be key/value where key is a string"); + } + std::string skey = LS.ckstring(key); + if (skey == "action") { + from_lua_store_string(L, value.index(), &action_, 0, "action"); + } else if (skey == "graphic") { + from_lua_store_string(L, value.index(), &graphic_, HAS_GRAPHIC, "graphic"); + } else if (skey == "plane") { + from_lua_store_string(L, value.index(), &plane_, HAS_PLANE, "plane"); + } else if (skey == "x") { + from_lua_store_number(L, value.index(), &xyz_.x, 0.0, HAS_X, "X coordinate"); + } else if (skey == "y") { + from_lua_store_number(L, value.index(), &xyz_.y, 0.0, HAS_Y, "Z coordinate"); + } else if (skey == "z") { + from_lua_store_number(L, value.index(), &xyz_.z, 0.0, HAS_Z, "Z coordinate"); + } else if (skey == "dx") { + from_lua_store_number(L, value.index(), &xyz_.x, qback.xyz().x, HAS_X, "X coordinate"); + } else if (skey == "dy") { + from_lua_store_number(L, value.index(), &xyz_.y, qback.xyz().y, HAS_Y, "Y coordinate"); + } else if (skey == "dz") { + from_lua_store_number(L, value.index(), &xyz_.z, qback.xyz().z, HAS_Z, "Z coordinate"); + } else if (skey == "facing") { + from_lua_store_number(L, value.index(), &facing_, 0.0, HAS_FACING, "facing"); + } else { + luaL_error(L, "Unrecognized animation spec: %s", skey.c_str()); + } } } diff --git a/luprex/core/cpp/animqueue.hpp b/luprex/core/cpp/animqueue.hpp index 9ddcafec..469358ff 100644 --- a/luprex/core/cpp/animqueue.hpp +++ b/luprex/core/cpp/animqueue.hpp @@ -57,6 +57,9 @@ private: std::string graphic_; std::string plane_; + void from_lua_store_string(lua_State *L, int idx, std::string *target, int16_t bits, const char *name); + void from_lua_store_number(lua_State *L, int idx, float *target, float offset, int16_t bits, const char *name); + public: AnimStep(); ~AnimStep(); @@ -103,7 +106,10 @@ public: // graphic: "graphic" // plane: "plane" // - void from_lua(lua_State *L, int idx); + // qback: the animation queue back, from which relative + // moves are computed. + // + void from_lua(lua_State *L, int idx, const AnimStep &qback); // For any values that are unchanged in this step, // echo the values of the previous step. diff --git a/luprex/core/cpp/traceback.cpp b/luprex/core/cpp/traceback.cpp index dea509c3..7f586f8c 100644 --- a/luprex/core/cpp/traceback.cpp +++ b/luprex/core/cpp/traceback.cpp @@ -9,6 +9,7 @@ // The error message is replaced with a traceback. // int traceback_coroutine(lua_State *L) { + lua_checkstack(L, 20); int top = lua_gettop(L); // Convert message to a string diff --git a/luprex/core/cpp/traceback.hpp b/luprex/core/cpp/traceback.hpp index 36577485..20d58f8e 100644 --- a/luprex/core/cpp/traceback.hpp +++ b/luprex/core/cpp/traceback.hpp @@ -22,8 +22,8 @@ int traceback_coroutine(lua_State *L); // traceback_pcall // -// same as lua_pcall, except that it automatically supplies traceback_handler as -// a message handler. +// same as lua_pcall, except that it automatically supplies +// traceback_coroutine as a message handler. // int traceback_pcall(lua_State *L, int narg, int nret); diff --git a/luprex/core/cpp/world.cpp b/luprex/core/cpp/world.cpp index 84cca650..426ff0e0 100644 --- a/luprex/core/cpp/world.cpp +++ b/luprex/core/cpp/world.cpp @@ -194,28 +194,6 @@ World::Redirects World::fetch_redirects() { return std::move(result); } -// void Tangible::be_a_player() { -// if (!id_player_pool_.fifo_enabled()) { -// id_player_pool_.enable_fifo(); - -// AnimStep asinit; -// asinit.set_graphic("player"); -// anim_queue_.add(world_->id_global_pool_.get_one(), asinit); -// anim_queue_.keep_only(1); -// update_plane_item(); - -// LuaVar classtab, mt, place, tangibles; -// LuaStack LS(world_->state(), classtab, mt, place, tangibles); - -// LS.makeclass(classtab, "player"); -// LS.rawget(tangibles, LuaRegistry, "tangibles"); -// LS.rawget(place, tangibles, id()); -// LS.getmetatable(mt, place); -// LS.rawset(mt, "__index", classtab); -// LS.result(); -// } -// } - int64_t World::create_login_actor() { Tangible *tan = tangible_make(state(), 0, true); LuaArg database; @@ -414,7 +392,7 @@ void World::run_scheduled_threads(int64_t clk) { thread_sched_.add(sched.clock() + int64_t(delay), sched.thread_id(), sched.place_id()); std::cerr << "Added to schedule." << std::endl; } - } else if (status == 0) { + } else if (status == LUA_OK) { // Successfully ran to completion. Remove from thread table. std::cerr << "Thread ran to completion." << std::endl; LS.rawset(threads, sched.thread_id(), LuaNil); @@ -511,8 +489,9 @@ LuaDefine(tangible_animate, "c") { World *w = World::fetch_global_pointer(L); Tangible *tan = w->tangible_get(L, tanobj.index()); int64_t id = w->id_global_pool_.alloc_id_for_thread(L); + const AnimStep &prev = tan->anim_queue_.back(); AnimStep step; - step.from_lua(L, config.index()); + step.from_lua(L, config.index(), prev); if (step.action() == "") { luaL_error(L, "animation action must be specified"); } @@ -561,8 +540,8 @@ LuaDefine(tangible_build, "c") { LS.getclass(classtab, classname); // Parse the initial animation step. - AnimStep initstep; - initstep.from_lua(L, config.index()); + AnimStep initstep, blank; + initstep.from_lua(L, config.index(), blank); if (!initstep.has_xyz()) { luaL_error(L, "You must specify (X,Y,Z) for new tangible"); } diff --git a/luprex/core/cpp/world.hpp b/luprex/core/cpp/world.hpp index 8afe77a5..43841a77 100644 --- a/luprex/core/cpp/world.hpp +++ b/luprex/core/cpp/world.hpp @@ -199,7 +199,7 @@ public: void serialize(StreamBuffer *sb); void deserialize(StreamBuffer *sb); - // Snapshot and rollback - temporary. + // Snapshot and rollback. // void snapshot(); void rollback(); diff --git a/luprex/core/lua/player.lua b/luprex/core/lua/player.lua index 5040e9e9..dca9cab3 100644 --- a/luprex/core/lua/player.lua +++ b/luprex/core/lua/player.lua @@ -7,27 +7,32 @@ function player.interface(actor, place) gui.menu_item("west", "Go West") end +function player:printanimstate() + graphic,plane,x,y,z,facing = tangible.animstate(self) + print("Resulting state: ", graphic, plane, x, y, z, facing) +end + function player.action.north(actor, place, dialog) print("Moving north") - x,y,z = tangible.xyz(place); tangible.animate(place, {action="walk", dy=1}) + actor:printanimstate() end function player.action.south(actor, place, dialog) print("Moving south") - x,y,z = tangible.xyz(place); tangible.animate(place, {action="walk", dy=-1}) + actor:printanimstate() end function player.action.east(actor, place, dialog) print("Moving east") - x,y,z = tangible.xyz(place); tangible.animate(place, {action="walk", dx=1}) + actor:printanimstate() end function player.action.west(actor, place, dialog) print("Moving west") - x,y,z = tangible.xyz(place) tangible.animate(place, {action="walk", dx=-1}) + actor:printanimstate() end