From e1f3c81cbd20da9b77ac82034f5dc9b38dfc0b58 Mon Sep 17 00:00:00 2001 From: jyelon Date: Wed, 27 May 2026 17:13:32 -0400 Subject: [PATCH] Progress toward implementing redirect --- Docs/TODO-List.md | 8 --- luprex/cpp/core/lpxserver.cpp | 20 ++++--- luprex/cpp/core/world-accessor.cpp | 89 +++++++++++++++++++++--------- luprex/cpp/core/world.hpp | 1 - luprex/cpp/drv/driver.cpp | 4 +- luprex/lua/login.lua | 2 - 6 files changed, 76 insertions(+), 48 deletions(-) diff --git a/Docs/TODO-List.md b/Docs/TODO-List.md index e665bc9c..32d2eecf 100644 --- a/Docs/TODO-List.md +++ b/Docs/TODO-List.md @@ -1,8 +1,6 @@ -* Add a slash-command to reload lua source code. - * Skeletal Mesh Tangible * Implement Interactive Temporary Variables @@ -15,16 +13,10 @@ Secret / semi-secret variables Secret functions -Unicode support for the console - Blockchain integration -GUI that looks for verbs - More sophisticated passage of time -GUI that runs in realtime - Little game demos: The monopoly game (Errands where you pass thru land owned by others with voronoi diagram) diff --git a/luprex/cpp/core/lpxserver.cpp b/luprex/cpp/core/lpxserver.cpp index 99d460d6..4e267b0e 100644 --- a/luprex/cpp/core/lpxserver.cpp +++ b/luprex/cpp/core/lpxserver.cpp @@ -107,17 +107,19 @@ public: delete_client(client); return false; } - // Security check. - if (inv.actor() != client->actor_id_) { - delete_client(client); - return false; - } - // util::dprint("Invoking: ", inv.debug_string()); - world_->invoke(inv); + // Acknowledge the invocation. client->channel_->out()->write_uint8(util::MSG_ACK); client->channel_->out()->write_uint32(0); - client->sync_->invoke(inv); - client->async_diff_ = true; + // Process the invocation. + // + // An invoke with the wrong actor_id is quietly a noop. This is + // to make leeway for clients who have recently been redirected, and + // who may not know their new actor_id yet. + if (inv.actor() == client->actor_id_) { + world_->invoke(inv); + client->sync_->invoke(inv); + client->async_diff_ = true; + } return true; } diff --git a/luprex/cpp/core/world-accessor.cpp b/luprex/cpp/core/world-accessor.cpp index c5d99085..d1d61726 100644 --- a/luprex/cpp/core/world-accessor.cpp +++ b/luprex/cpp/core/world-accessor.cpp @@ -283,22 +283,80 @@ LuaDefine(tangible_delete, "tan", "|Delete the specified tangible." "|" "|This cannot be used to delete player tangibles," - "|To delete a player, use tangible.redirect") { + "|To delete a player, use tangible.redirect" + "|") { LuaArg tanobj; LuaDefStack LS(L, tanobj); World *w = World::fetch_global_pointer(L); Tangible *tan = w->tangible_get(LS, tanobj, true); if (tan == nullptr) { - return LS.result(); + luaL_error(L, "Not a tangible."); + return 0; } - if (tan->is_an_actor()) { - luaL_error(L, "Cannot delete a player using tangible.delete, use tangible.redirect instead."); + if (tan->can_be_controlled_) { + luaL_error(L, "Cannot delete a player using tangible.delete, use tangible.deleteactor instead."); return 0; } w->tangible_delete(tan->id()); return LS.result(); } +LuaDefine(tangible_deleteactor, "tan", + "|Delete an actor tangible, or mark it for deletion on logout." + "|" + "|This function is used to delete an actor tangible." + "|" + "|If the actor is not currently logged in, then the tangible is" + "|immediately deleted. If the actor is logged in, then the tangible" + "|is marked as delete_on_disconnect, and the force_disconnect flag" + "|is set. This will cause the actor to cleanly disconnect, and then" + "|the deletion will take place." + "|") { + LuaArg tanobj; + LuaDefStack LS(L, tanobj); + World *w = World::fetch_global_pointer(L); + Tangible *tan = w->tangible_get(LS, tanobj, true); + if ((tan == nullptr) || (!tan->can_be_controlled_)) { + luaL_error(L, "Tangible is not an actor."); + return 0; + } + if (tan->is_controlled_) { + tan->delete_on_disconnect_ = true; + tan->force_disconnect_ = true; + } else { + w->tangible_delete(tan->id()); + } + return LS.result(); +} + +LuaDefine(tangible_keepactor, "tan", + "|Mark an actor tangible to not 'delete_on_disconnect'." + "|" + "|When a client connects to the server, a login actor is created and the" + "|client is put in control of the login actor. The client typically" + "|controls the login actor just long enough to type his username and password." + "|Then, he is redirected to the real actor." + "|" + "|When the client is redirected to the real actor, the login actor is no longer" + "|needed. The login actor has the flag 'delete_on_disconnect', so when the" + "|client detaches from the login actor, it is garbage collected." + "|" + "|However, if the player clicks 'NEW PLAYER', then it is necessary to" + "|convert the login actor into a permanent actor. The most important step is to" + "|clear the delete_on_disconnect flag. That is what 'keepactor' does." + "|") { + LuaArg tanobj; + LuaDefStack LS(L, tanobj); + World *w = World::fetch_global_pointer(L); + Tangible *tan = w->tangible_get(LS, tanobj, true); + if ((tan == nullptr) || (!tan->can_be_controlled_)) { + luaL_error(L, "Tangible is not an actor."); + return 0; + } + tan->delete_on_disconnect_ = false; + return LS.result(); +} + LuaDefine(tangible_build, "config", "|Build a new tangible object." "|" @@ -398,29 +456,6 @@ LuaDefine(tangible_get, "id", return LS.result(); } -LuaDefine(tangible_redirect, "tan1,tan2,bulldozetan1", - "|Redirect is not working yet") { - LuaArg actor1, actor2, bldz; - LuaDefStack LS(L, actor1, actor2, bldz); - World *w = World::fetch_global_pointer(L); - bool bulldoze = LS.ckboolean(bldz); - Tangible *tan1 = w->tangible_get(LS, actor1, false); - if (!tan1->is_an_actor()) { - luaL_error(L, "redirect source is not an actor"); - } - if (LS.isnil(actor2)) { - w->redirects_[tan1->id()] = 0; - } else { - Tangible *tan2 = w->tangible_get(LS, actor2, false); - tan2->configure_id_pool_for_actor(); - w->redirects_[tan1->id()] = tan2->id(); - } - if (bulldoze) { - w->tangible_delete(tan1->id()); - } - return LS.result(); -} - LuaDefine(tangible_id, "tan", "|Return the tangible's id number." "|This is for debugging only and will be removed" diff --git a/luprex/cpp/core/world.hpp b/luprex/cpp/core/world.hpp index 3b0856fa..d87a31a1 100644 --- a/luprex/cpp/core/world.hpp +++ b/luprex/cpp/core/world.hpp @@ -120,7 +120,6 @@ public: int64_t id() const { return plane_item_.id(); } void update_plane_item(); - bool is_an_actor() { return (id_player_pool_.get_fifo_capacity() > 0); } void configure_id_pool_for_actor() { id_player_pool_.set_fifo_capacity(3); id_player_pool_.refill(); } }; diff --git a/luprex/cpp/drv/driver.cpp b/luprex/cpp/drv/driver.cpp index 2d0efb94..a8532102 100644 --- a/luprex/cpp/drv/driver.cpp +++ b/luprex/cpp/drv/driver.cpp @@ -14,7 +14,9 @@ static ReadlineDevice readline_device; static void dprint_callback(const char *oneline, size_t size) { - readline_device.printline(std::string_view(oneline, size)); + std::string wlog("LOG: "); + wlog += std::string_view(oneline, size); + readline_device.printline(wlog); } static void if_error_print_and_exit(const std::string_view str) { diff --git a/luprex/lua/login.lua b/luprex/lua/login.lua index ce63b5b9..27c68370 100644 --- a/luprex/lua/login.lua +++ b/luprex/lua/login.lua @@ -79,8 +79,6 @@ function engio.getlookat() return "" end -print("Hello from login.lua") - function jp3() tangible.animate{tan=actor, anim={action="play", seq="jump"}} tangible.animate{tan=actor, anim={action="play", seq="jump"}}