From e2f8f4da83206d551f9acebd14d574ea37ca214a Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Mon, 10 Jun 2019 13:01:07 +0200 Subject: [PATCH] Formspecs: Close on metadata removal (#8348) Formspecs will now close as soon the formspec string in the node metadata turns invalid. --- src/client/game.cpp | 91 ++++++++++++++++++++++----------------- src/client/gameui.cpp | 12 ++++++ src/client/gameui.h | 16 +++++++ src/gui/guiFormSpecMenu.h | 5 +++ 4 files changed, 85 insertions(+), 39 deletions(-) diff --git a/src/client/game.cpp b/src/client/game.cpp index 8c0433283..a29b35746 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -827,10 +827,6 @@ private: ChatBackend *chat_backend = nullptr; - GUIFormSpecMenu *current_formspec = nullptr; - //default: "". If other than "", empty show_formspec packets will only close the formspec when the formname matches - std::string cur_formname; - EventManager *eventmgr = nullptr; QuicktuneShortcutter *quicktune = nullptr; bool registration_confirmation_shown = false; @@ -1143,8 +1139,9 @@ void Game::shutdown() driver->setRenderTarget(irr::video::ERT_STEREO_BOTH_BUFFERS); } #endif - if (current_formspec) - current_formspec->quitMenu(); + auto formspec = m_game_ui->getFormspecGUI(); + if (formspec) + formspec->quitMenu(); showOverlayMessage(N_("Shutting down..."), 0, 0, false); @@ -1163,10 +1160,7 @@ void Game::shutdown() g_menumgr.deletingMenu(g_menumgr.m_stack.front()); } - if (current_formspec) { - current_formspec->drop(); - current_formspec = NULL; - } + m_game_ui->deleteFormspec(); chat_backend->addMessage(L"", L"# Disconnected."); chat_backend->addMessage(L"", L""); @@ -1853,8 +1847,9 @@ void Game::processUserInput(f32 dtime) input->step(dtime); #ifdef __ANDROID__ - if (current_formspec != NULL) - current_formspec->getAndroidUIInput(); + auto formspec = m_game_ui->getFormspecGUI(); + if (formspec) + formspec->getAndroidUIInput(); else handleAndroidChatInput(); #endif @@ -2050,10 +2045,11 @@ void Game::openInventory() if (!client->moddingEnabled() || !client->getScript()->on_inventory_open(fs_src->m_client->getInventory(inventoryloc))) { TextDest *txt_dst = new TextDestPlayerInventory(client); - GUIFormSpecMenu::create(current_formspec, client, &input->joystick, fs_src, + auto *&formspec = m_game_ui->updateFormspec(""); + GUIFormSpecMenu::create(formspec, client, &input->joystick, fs_src, txt_dst, client->getFormspecPrepend()); - cur_formname = ""; - current_formspec->setFormSpec(fs_src->getForm(), inventoryloc); + + formspec->setFormSpec(fs_src->getForm(), inventoryloc); } } @@ -2581,9 +2577,10 @@ void Game::handleClientEvent_Deathscreen(ClientEvent *event, CameraOrientation * void Game::handleClientEvent_ShowFormSpec(ClientEvent *event, CameraOrientation *cam) { if (event->show_formspec.formspec->empty()) { - if (current_formspec && (event->show_formspec.formname->empty() - || *(event->show_formspec.formname) == cur_formname)) { - current_formspec->quitMenu(); + auto formspec = m_game_ui->getFormspecGUI(); + if (formspec && (event->show_formspec.formname->empty() + || *(event->show_formspec.formname) == m_game_ui->getFormspecName())) { + formspec->quitMenu(); } } else { FormspecFormSource *fs_src = @@ -2591,9 +2588,9 @@ void Game::handleClientEvent_ShowFormSpec(ClientEvent *event, CameraOrientation TextDestPlayerInventory *txt_dst = new TextDestPlayerInventory(client, *(event->show_formspec.formname)); - GUIFormSpecMenu::create(current_formspec, client, &input->joystick, + auto *&formspec = m_game_ui->updateFormspec(*(event->show_formspec.formname)); + GUIFormSpecMenu::create(formspec, client, &input->joystick, fs_src, txt_dst, client->getFormspecPrepend()); - cur_formname = *(event->show_formspec.formname); } delete event->show_formspec.formspec; @@ -2605,7 +2602,7 @@ void Game::handleClientEvent_ShowLocalFormSpec(ClientEvent *event, CameraOrienta FormspecFormSource *fs_src = new FormspecFormSource(*event->show_formspec.formspec); LocalFormspecHandler *txt_dst = new LocalFormspecHandler(*event->show_formspec.formname, client); - GUIFormSpecMenu::create(current_formspec, client, &input->joystick, + GUIFormSpecMenu::create(m_game_ui->getFormspecGUI(), client, &input->joystick, fs_src, txt_dst, client->getFormspecPrepend()); delete event->show_formspec.formspec; @@ -3272,11 +3269,11 @@ void Game::handlePointingAtNode(const PointedThing &pointed, &client->getEnv().getClientMap(), nodepos); TextDest *txt_dst = new TextDestNodeMetadata(nodepos, client); - GUIFormSpecMenu::create(current_formspec, client, &input->joystick, fs_src, + auto *&formspec = m_game_ui->updateFormspec(""); + GUIFormSpecMenu::create(formspec, client, &input->joystick, fs_src, txt_dst, client->getFormspecPrepend()); - cur_formname.clear(); - current_formspec->setFormSpec(meta->getString("formspec"), inventoryloc); + formspec->setFormSpec(meta->getString("formspec"), inventoryloc); } else { // Report right click to server @@ -3844,14 +3841,28 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime, 1. Delete formspec menu reference if menu was removed 2. Else, make sure formspec menu is on top */ - if (current_formspec) { - if (current_formspec->getReferenceCount() == 1) { - current_formspec->drop(); - current_formspec = NULL; - } else if (isMenuActive()) { - guiroot->bringToFront(current_formspec); + auto formspec = m_game_ui->getFormspecGUI(); + do { // breakable. only runs for one iteration + if (!formspec) + break; + + if (formspec->getReferenceCount() == 1) { + m_game_ui->deleteFormspec(); + break; } - } + + auto &loc = formspec->getFormspecLocation(); + if (loc.type == InventoryLocation::NODEMETA) { + NodeMetadata *meta = client->getEnv().getClientMap().getNodeMetadata(loc.p); + if (!meta || meta->getString("formspec").empty()) { + formspec->quitMenu(); + break; + } + } + + if (isMenuActive()) + guiroot->bringToFront(formspec); + } while (false); /* Drawing begins @@ -4048,7 +4059,7 @@ void Game::extendedResourceCleanup() void Game::showDeathFormspec() { - static std::string formspec = + static std::string formspec_str = std::string(FORMSPEC_VERSION_STRING) + SIZE_TAG "bgcolor[#320000b4;true]" @@ -4059,12 +4070,13 @@ void Game::showDeathFormspec() /* Create menu */ /* Note: FormspecFormSource and LocalFormspecHandler * * are deleted by guiFormSpecMenu */ - FormspecFormSource *fs_src = new FormspecFormSource(formspec); + FormspecFormSource *fs_src = new FormspecFormSource(formspec_str); LocalFormspecHandler *txt_dst = new LocalFormspecHandler("MT_DEATH_SCREEN", client); - GUIFormSpecMenu::create(current_formspec, client, &input->joystick, fs_src, - txt_dst, client->getFormspecPrepend()); - current_formspec->setFocus("btn_respawn"); + auto *&formspec = m_game_ui->getFormspecGUI(); + GUIFormSpecMenu::create(formspec, client, &input->joystick, + fs_src, txt_dst, client->getFormspecPrepend()); + formspec->setFocus("btn_respawn"); } #define GET_KEY_NAME(KEY) gettext(getKeySetting(#KEY).name()) @@ -4188,10 +4200,11 @@ void Game::showPauseMenu() FormspecFormSource *fs_src = new FormspecFormSource(os.str()); LocalFormspecHandler *txt_dst = new LocalFormspecHandler("MT_PAUSE_MENU"); - GUIFormSpecMenu::create(current_formspec, client, &input->joystick, + auto *&formspec = m_game_ui->getFormspecGUI(); + GUIFormSpecMenu::create(formspec, client, &input->joystick, fs_src, txt_dst, client->getFormspecPrepend()); - current_formspec->setFocus("btn_continue"); - current_formspec->doPause = true; + formspec->setFocus("btn_continue"); + formspec->doPause = true; } /****************************************************************************/ diff --git a/src/client/gameui.cpp b/src/client/gameui.cpp index 5533cd119..f3c3fefb6 100644 --- a/src/client/gameui.cpp +++ b/src/client/gameui.cpp @@ -302,3 +302,15 @@ void GameUI::toggleProfiler() showTranslatedStatusText("Profiler hidden"); } } + + +void GameUI::deleteFormspec() +{ + if (m_formspec) + m_formspec->quitMenu(); + + delete m_formspec; + m_formspec = nullptr; + + m_formname.clear(); +} diff --git a/src/client/gameui.h b/src/client/gameui.h index b6b54562a..8d20870d7 100644 --- a/src/client/gameui.h +++ b/src/client/gameui.h @@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #pragma once #include +#include "gui/guiFormSpecMenu.h" #include "util/enriched_string.h" #include "util/pointedthing.h" #include "game.h" @@ -88,6 +89,16 @@ public: void toggleHud(); void toggleProfiler(); + GUIFormSpecMenu *&updateFormspec(const std::string &formname) + { + m_formname = formname; + return m_formspec; + } + + const std::string &getFormspecName() { return m_formname; } + GUIFormSpecMenu *&getFormspecGUI() { return m_formspec; } + void deleteFormspec(); + private: Flags m_flags; @@ -107,4 +118,9 @@ private: gui::IGUIStaticText *m_guitext_profiler = nullptr; // Profiler text u8 m_profiler_current_page = 0; const u8 m_profiler_max_page = 3; + + // Default: "". If other than "": Empty show_formspec packets will only + // close the formspec when the formname matches + std::string m_formname; + GUIFormSpecMenu *m_formspec = nullptr; }; diff --git a/src/gui/guiFormSpecMenu.h b/src/gui/guiFormSpecMenu.h index 33f88d8c0..ccd9cb753 100644 --- a/src/gui/guiFormSpecMenu.h +++ b/src/gui/guiFormSpecMenu.h @@ -304,6 +304,11 @@ public: regenerateGui(m_screensize_old); } + const InventoryLocation &getFormspecLocation() + { + return m_current_inventory_location; + } + void setFormspecPrepend(const std::string &formspecPrepend) { m_formspec_prepend = formspecPrepend; -- 2.25.1