From 368d066cc7e3de4ce8c7bfc5990227a6bc6221e0 Mon Sep 17 00:00:00 2001 From: Josh Yelon Date: Sun, 7 Feb 2021 17:26:48 -0500 Subject: [PATCH] Added code to probe 'interface' --- luprex/cpp/luastack.cpp | 7 +++++- luprex/cpp/luastack.hpp | 10 +++++++++ luprex/cpp/viewer.cpp | 10 ++------- luprex/cpp/world.cpp | 50 +++++++++++++++++++++++++++++++++++++++++ luprex/cpp/world.hpp | 5 +++++ 5 files changed, 73 insertions(+), 9 deletions(-) diff --git a/luprex/cpp/luastack.cpp b/luprex/cpp/luastack.cpp index 0c4fee30..fbfe1772 100644 --- a/luprex/cpp/luastack.cpp +++ b/luprex/cpp/luastack.cpp @@ -8,6 +8,11 @@ LuaNilMarker LuaNil; LuaNewTableMarker LuaNewTable; LuaDiscardMarker LuaDiscard; +void LuaStack::clear_tagged_pointer(LuaSlot target) { + TaggedPointer *tp = (TaggedPointer*)lua_touserdata(L_, target.index()); + tp->ptr = 0; +} + void LuaStack::make_tagged_pointer(LuaSlot target, void *ptr, LuaTypeTag tag, LuaDeleterFn del) { TaggedPointer *tp = (TaggedPointer*)lua_newuserdata(L_, sizeof(TaggedPointer)); tp->ptr = ptr; @@ -21,7 +26,7 @@ void LuaStack::make_tagged_pointer(LuaSlot target, void *ptr, LuaTypeTag tag, Lu } int LuaStack::collect_tagged_pointer(lua_State *L) { - LuaStack::TaggedPointer *p = (LuaStack::TaggedPointer*)lua_touserdata(L, 1); + TaggedPointer *p = (TaggedPointer*)lua_touserdata(L, 1); if (p==0) { luaL_error(L, "lua deleter function received a non-userdata"); } diff --git a/luprex/cpp/luastack.hpp b/luprex/cpp/luastack.hpp index 039e43dc..066cdfcb 100644 --- a/luprex/cpp/luastack.hpp +++ b/luprex/cpp/luastack.hpp @@ -372,6 +372,7 @@ private: }; static int collect_tagged_pointer(lua_State *L); void make_tagged_pointer(LuaSlot target, void *ptr, LuaTypeTag tag, LuaDeleterFn del); + void clear_tagged_pointer(LuaSlot target); template static void delete_pointer(void *p) { delete (T*)p; } @@ -449,6 +450,8 @@ public: return (T*)(tp->ptr); } + void clearuserdata(LuaSlot target) { clear_tagged_pointer(target); } + int next(LuaSlot tab, LuaSlot key, LuaSlot value) const; bool isemptytable(LuaSlot s) const; @@ -462,6 +465,13 @@ public: pop_any_value(target); } + template + void gettable(RT &target, LuaSlot tab, KT key) const { + push_any_value(key); + lua_gettable(L_, tab); + pop_any_value(target); + } + template void rawget(RT &target, LuaSlot tab, KT key) const { push_any_value(key); diff --git a/luprex/cpp/viewer.cpp b/luprex/cpp/viewer.cpp index ad51b51b..0be28186 100644 --- a/luprex/cpp/viewer.cpp +++ b/luprex/cpp/viewer.cpp @@ -13,13 +13,7 @@ int64_t Viewer::get_player_id() { return 1; } -void Viewer::update_gui(int64_t id, Gui *gui) { - gui->clear(); - gui->add_menu_item("north", "north"); - gui->add_menu_item("south", "south"); - gui->add_menu_item("east", "east"); - gui->add_menu_item("west", "west"); - gui->add_menu_item("build", "build"); - gui->add_menu_item("destroy", "destroy"); +void Viewer::update_gui(int64_t place, Gui *gui) { + world_->update_gui(get_player_id(), place, gui); } diff --git a/luprex/cpp/world.cpp b/luprex/cpp/world.cpp index a401fe3f..85381153 100644 --- a/luprex/cpp/world.cpp +++ b/luprex/cpp/world.cpp @@ -2,6 +2,8 @@ #include "world.hpp" #include "idalloc.hpp" #include "animqueue.hpp" +#include "gui.hpp" +#include "traceback.hpp" #include LuaDefineType(World); @@ -131,6 +133,54 @@ World *World::fetch(lua_State *L) { return w; } +void World::update_gui(int64_t actor_id, int64_t place_id, Gui *gui) { + gui->clear(); + lua_State *L = get_lua_state(); + + LuaVar actor, place, ugui, func, tangibles; + LuaStack LS(L, actor, place, ugui, func, tangibles); + + // Get the actor and place. + LS.getfield(tangibles, LuaRegistry, "tangibles"); + LS.rawget(actor, tangibles, actor_id); + LS.rawget(place, tangibles, place_id); + if (!LS.istable(actor) || !LS.istable(place)) { + LS.result(); + return; + } + + // Get the interface closure. + LS.getfield(func, place, "interface"); + if (!LS.isfunction(func)) { + LS.result(); + return; + } + + // Construct the userdata with the GUI pointer. + LS.newpointer(ugui, gui, false); + + // Call the interface function. + lua_pushvalue(L, func.index()); + lua_pushvalue(L, actor.index()); + lua_pushvalue(L, place.index()); + lua_pushvalue(L, ugui.index()); + int status = traceback_pcall(L, 3, 0); + if (status != 0) { + gui->clear(); + std::cerr << lua_tostring(L, -1); + LS.result(); + return; + } + + // Nuke the userdata, in case somebody saved a pointer to it. + LS.clearuserdata(ugui); + + // And we're done. + LS.result(); +} + + + LuaDefine(tangible_get, "c") { LuaArg id; LuaRet database; diff --git a/luprex/cpp/world.hpp b/luprex/cpp/world.hpp index fbc4786a..45a03f72 100644 --- a/luprex/cpp/world.hpp +++ b/luprex/cpp/world.hpp @@ -7,6 +7,7 @@ #include "idalloc.hpp" #include "animqueue.hpp" #include "source.hpp" +#include "gui.hpp" #include #include @@ -106,6 +107,10 @@ public: // void tangible_del(int64_t id); + // Probe the 'interface' function of the specified sprite. + // + void update_gui(int64_t actor_id, int64_t place_id, Gui *gui); + // fetch // // Given a lua state, fetch the world model associated with