From eeff0d4be05003ee66639352bd61ea025686d457 Mon Sep 17 00:00:00 2001 From: cron Date: Fri, 20 Nov 2020 02:23:13 +0000 Subject: [PATCH] Client: add form interception register_on_receiving_inventory_form(function(formname, formspec)) intercepts forms sent from the server register_on_open_nodemeta_form(function(pos, formname, formspec)) intercepts forms that are to be shown locally nodemeta intecept probably doesn't intercept all ways it can be opened --- builtin/client/register.lua | 4 +++- src/client/game.cpp | 23 +++++++++++--------- src/network/clientpackethandler.cpp | 16 ++++++++------ src/script/cpp_api/s_client.cpp | 33 +++++++++++++++++++++++++++-- src/script/cpp_api/s_client.h | 3 +++ 5 files changed, 59 insertions(+), 20 deletions(-) diff --git a/builtin/client/register.lua b/builtin/client/register.lua index 071220a43..d97ea69f8 100644 --- a/builtin/client/register.lua +++ b/builtin/client/register.lua @@ -53,7 +53,7 @@ function core.override_item(name, redefinition) end local nodedef = core.get_node_def(name) table.combine(itemdef, nodedef) - + for k, v in pairs(redefinition) do rawset(itemdef, k, v) end @@ -94,3 +94,5 @@ core.registered_on_item_use, core.register_on_item_use = make_registration() core.registered_on_modchannel_message, core.register_on_modchannel_message = make_registration() core.registered_on_modchannel_signal, core.register_on_modchannel_signal = make_registration() core.registered_on_inventory_open, core.register_on_inventory_open = make_registration() +core.registered_on_receiving_inventory_form, core.register_on_receiving_inventory_form = make_registration() +core.registered_on_open_nodemeta_form, core.register_on_open_nodemeta_form = make_registration() diff --git a/src/client/game.cpp b/src/client/game.cpp index e77d7c67d..47b5cfec4 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -2624,20 +2624,23 @@ bool Game::nodePlacement(const ItemDefinition &selected_def, if (nodedef_manager->get(map.getNode(nodepos)).rightclickable) client->interact(INTERACT_PLACE, pointed); - infostream << "Launching custom inventory view" << std::endl; + std::string formspec_str = meta->getString("formspec"); + if (!client->getScript()->on_nodemeta_form_open(nodepos, "", formspec_str)) { + infostream << "Launching custom inventory view" << std::endl; - InventoryLocation inventoryloc; - inventoryloc.setNodeMeta(nodepos); + InventoryLocation inventoryloc; + inventoryloc.setNodeMeta(nodepos); - NodeMetadataFormSource *fs_src = new NodeMetadataFormSource( - &client->getEnv().getClientMap(), nodepos); - TextDest *txt_dst = new TextDestNodeMetadata(nodepos, client); + NodeMetadataFormSource *fs_src = new NodeMetadataFormSource( + &client->getEnv().getClientMap(), nodepos); + TextDest *txt_dst = new TextDestNodeMetadata(nodepos, client); - auto *&formspec = m_game_ui->updateFormspec(""); - GUIFormSpecMenu::create(formspec, client, &input->joystick, fs_src, - txt_dst, client->getFormspecPrepend()); + auto *&formspec = m_game_ui->updateFormspec(""); + GUIFormSpecMenu::create(formspec, client, &input->joystick, fs_src, + txt_dst, client->getFormspecPrepend()); - formspec->setFormSpec(meta->getString("formspec"), inventoryloc); + formspec->setFormSpec(formspec_str, inventoryloc); + } return false; } diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp index 5518838a1..a0db81a91 100644 --- a/src/network/clientpackethandler.cpp +++ b/src/network/clientpackethandler.cpp @@ -979,13 +979,15 @@ void Client::handleCommand_ShowFormSpec(NetworkPacket* pkt) *pkt >> formname; - ClientEvent *event = new ClientEvent(); - event->type = CE_SHOW_FORMSPEC; - // pointer is required as event is a struct only! - // adding a std:string to a struct isn't possible - event->show_formspec.formspec = new std::string(formspec); - event->show_formspec.formname = new std::string(formname); - m_client_event_queue.push(event); + if (!m_script->on_receiving_inventory_form(formname, formspec)) { + ClientEvent *event = new ClientEvent(); + event->type = CE_SHOW_FORMSPEC; + // pointer is required as event is a struct only! + // adding a std:string to a struct isn't possible + event->show_formspec.formspec = new std::string(formspec); + event->show_formspec.formname = new std::string(formname); + m_client_event_queue.push(event); + } } void Client::handleCommand_SpawnParticle(NetworkPacket* pkt) diff --git a/src/script/cpp_api/s_client.cpp b/src/script/cpp_api/s_client.cpp index 0d4e21876..8cf6ee587 100644 --- a/src/script/cpp_api/s_client.cpp +++ b/src/script/cpp_api/s_client.cpp @@ -237,17 +237,46 @@ bool ScriptApiClient::on_inventory_open(Inventory *inventory) void ScriptApiClient::open_special_inventory() { SCRIPTAPI_PRECHECKHEADER - + PUSH_ERROR_HANDLER(L); int error_handler = lua_gettop(L) - 1; lua_insert(L, error_handler); - + lua_getglobal(L, "core"); lua_getfield(L, -1, "open_special_inventory"); if (lua_isfunction(L, -1)) lua_pcall(L, 0, 0, error_handler); } +bool ScriptApiClient::on_receiving_inventory_form(std::string formname, std::string formspec) +{ + SCRIPTAPI_PRECHECKHEADER + + lua_getglobal(L, "core"); + lua_getfield(L, -1, "registered_on_receiving_inventory_form"); + + lua_pushstring(L, formname.c_str()); + lua_pushstring(L, formspec.c_str()); + + runCallbacks(2, RUN_CALLBACKS_MODE_OR); + return readParam(L, -1); +} + +bool ScriptApiClient::on_nodemeta_form_open(v3s16 position, std::string formname, std::string formspec) +{ + SCRIPTAPI_PRECHECKHEADER + + lua_getglobal(L, "core"); + lua_getfield(L, -1, "registered_on_nodemeta_form_open"); + + push_v3s16(L, position); + lua_pushstring(L, formname.c_str()); + lua_pushstring(L, formspec.c_str()); + + runCallbacks(2, RUN_CALLBACKS_MODE_OR); + return readParam(L, -1); +} + void ScriptApiClient::setEnv(ClientEnvironment *env) { ScriptApiBase::setEnv(env); diff --git a/src/script/cpp_api/s_client.h b/src/script/cpp_api/s_client.h index 4cdcb42eb..9324aef1d 100644 --- a/src/script/cpp_api/s_client.h +++ b/src/script/cpp_api/s_client.h @@ -61,5 +61,8 @@ public: bool on_inventory_open(Inventory *inventory); void open_special_inventory(); + bool on_receiving_inventory_form(std::string formname, std::string formspec); + bool on_nodemeta_form_open(v3s16 position, std::string formname, std::string formspec); + void setEnv(ClientEnvironment *env); };