From 127f354e7a5e85cfc46304499e7c8619fc9538c8 Mon Sep 17 00:00:00 2001 From: sapier Date: Sun, 20 Apr 2014 02:40:25 +0200 Subject: [PATCH] Fix formspec replacement handling for in game formspecs --- src/game.cpp | 190 ++++++++++++++++++---------------------- src/guiEngine.cpp | 9 +- src/guiFormSpecMenu.cpp | 24 +++-- src/guiFormSpecMenu.h | 25 ++++-- 4 files changed, 125 insertions(+), 123 deletions(-) diff --git a/src/game.cpp b/src/game.cpp index 6265c430..58a26e94 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -122,13 +122,16 @@ struct TextDestPlayerInventory : public TextDest struct LocalFormspecHandler : public TextDest { LocalFormspecHandler(); - LocalFormspecHandler(std::string formname) { + LocalFormspecHandler(std::string formname) : + m_client(0) + { m_formname = formname; } - LocalFormspecHandler(std::string formname,Client *client) { + LocalFormspecHandler(std::string formname, Client *client) : + m_client(client) + { m_formname = formname; - m_client = client; } void gotText(std::wstring message) { @@ -167,25 +170,27 @@ struct LocalFormspecHandler : public TextDest } } if (m_formname == "MT_CHAT_MENU") { + assert(m_client != 0); if ((fields.find("btn_send") != fields.end()) || (fields.find("quit") != fields.end())) { if (fields.find("f_text") != fields.end()) { - if (m_client != 0) { - m_client->typeChatMessage(narrow_to_wide(fields["f_text"])); - } - else { - errorstream << "LocalFormspecHandler::gotText received chat message but m_client is NULL" << std::endl; - } + m_client->typeChatMessage(narrow_to_wide(fields["f_text"])); } return; } } if (m_formname == "MT_DEATH_SCREEN") { + assert(m_client != 0); if ((fields.find("btn_respawn") != fields.end())) { m_client->sendRespawn(); return; } + + if (fields.find("quit") != fields.end()) { + m_client->sendRespawn(); + return; + } } errorstream << "LocalFormspecHandler::gotText unhandled >" << m_formname << "< event" << std::endl; @@ -963,34 +968,47 @@ bool nodePlacementPrediction(Client &client, return false; } -static void show_chat_menu(FormspecFormSource* current_formspec, - TextDest* current_textdest, IWritableTextureSource* tsrc, - IrrlichtDevice * device, Client* client, std::string text) +static inline void create_formspec_menu(GUIFormSpecMenu** cur_formspec, + InventoryManager *invmgr, IGameDef *gamedef, + IWritableTextureSource* tsrc, IrrlichtDevice * device, + IFormSource* fs_src, TextDest* txt_dest + ) { + + if (*cur_formspec == 0) { + *cur_formspec = new GUIFormSpecMenu(device, guiroot, -1, &g_menumgr, + invmgr, gamedef, tsrc, fs_src, txt_dest, cur_formspec ); + (*cur_formspec)->doPause = false; + (*cur_formspec)->drop(); + } + else { + (*cur_formspec)->setFormSource(fs_src); + (*cur_formspec)->setTextDest(txt_dest); + } +} + +static void show_chat_menu(GUIFormSpecMenu** cur_formspec, + InventoryManager *invmgr, IGameDef *gamedef, + IWritableTextureSource* tsrc, IrrlichtDevice * device, + Client* client, std::string text) { std::string formspec = "size[11,5.5,true]" "field[3,2.35;6,0.5;f_text;;" + text + "]" - "button_exit[4,3;3,0.5;btn_send;" + wide_to_narrow(wstrgettext("Proceed")) + "]" + "button_exit[4,3;3,0.5;btn_send;" + wide_to_narrow(wstrgettext("Proceed")) + "]" ; /* Create menu */ /* Note: FormspecFormSource and LocalFormspecHandler * are deleted by guiFormSpecMenu */ - current_formspec = new FormspecFormSource(formspec,¤t_formspec); - current_textdest = new LocalFormspecHandler("MT_CHAT_MENU",client); - GUIFormSpecMenu *menu = - new GUIFormSpecMenu(device, guiroot, -1, - &g_menumgr, - NULL, NULL, tsrc); - menu->doPause = false; - menu->setFormSource(current_formspec); - menu->setTextDest(current_textdest); - menu->drop(); + FormspecFormSource* fs_src = new FormspecFormSource(formspec); + LocalFormspecHandler* txt_dst = new LocalFormspecHandler("MT_CHAT_MENU", client); + + create_formspec_menu(cur_formspec, invmgr, gamedef, tsrc, device, fs_src, txt_dst); } -static void show_deathscreen(FormspecFormSource* current_formspec, - TextDest* current_textdest, IWritableTextureSource* tsrc, - IrrlichtDevice * device, Client* client) +static void show_deathscreen(GUIFormSpecMenu** cur_formspec, + InventoryManager *invmgr, IGameDef *gamedef, + IWritableTextureSource* tsrc, IrrlichtDevice * device, Client* client) { std::string formspec = std::string("") + @@ -1003,24 +1021,18 @@ static void show_deathscreen(FormspecFormSource* current_formspec, /* Create menu */ /* Note: FormspecFormSource and LocalFormspecHandler * are deleted by guiFormSpecMenu */ - current_formspec = new FormspecFormSource(formspec,¤t_formspec); - current_textdest = new LocalFormspecHandler("MT_DEATH_SCREEN",client); - GUIFormSpecMenu *menu = - new GUIFormSpecMenu(device, guiroot, -1, - &g_menumgr, - NULL, NULL, tsrc); - menu->doPause = false; - menu->setFormSource(current_formspec); - menu->setTextDest(current_textdest); - menu->drop(); + FormspecFormSource* fs_src = new FormspecFormSource(formspec); + LocalFormspecHandler* txt_dst = new LocalFormspecHandler("MT_DEATH_SCREEN", client); + + create_formspec_menu(cur_formspec, invmgr, gamedef, tsrc, device, fs_src, txt_dst); } /******************************************************************************/ -static void show_pause_menu(FormspecFormSource* current_formspec, - TextDest* current_textdest, IWritableTextureSource* tsrc, - IrrlichtDevice * device, bool singleplayermode) +static void show_pause_menu(GUIFormSpecMenu** cur_formspec, + InventoryManager *invmgr, IGameDef *gamedef, + IWritableTextureSource* tsrc, IrrlichtDevice * device, + bool singleplayermode) { - std::string control_text = wide_to_narrow(wstrgettext("Default Controls:\n" "- WASD: move\n" "- Space: jump/climb\n" @@ -1046,7 +1058,7 @@ static void show_pause_menu(FormspecFormSource* current_formspec, << wide_to_narrow(wstrgettext("Change Password")) << "]"; } - os << "button_exit[4," << (ypos++) << ";3,0.5;btn_sound;" + os << "button_exit[4," << (ypos++) << ";3,0.5;btn_sound;" << wide_to_narrow(wstrgettext("Sound Volume")) << "]"; os << "button_exit[4," << (ypos++) << ";3,0.5;btn_exit_menu;" << wide_to_narrow(wstrgettext("Exit to Menu")) << "]"; @@ -1061,14 +1073,10 @@ static void show_pause_menu(FormspecFormSource* current_formspec, /* Create menu */ /* Note: FormspecFormSource and LocalFormspecHandler * * are deleted by guiFormSpecMenu */ - current_formspec = new FormspecFormSource(os.str(),¤t_formspec); - current_textdest = new LocalFormspecHandler("MT_PAUSE_MENU"); - GUIFormSpecMenu *menu = - new GUIFormSpecMenu(device, guiroot, -1, &g_menumgr, NULL, NULL, tsrc); - menu->doPause = true; - menu->setFormSource(current_formspec); - menu->setTextDest(current_textdest); - menu->drop(); + FormspecFormSource* fs_src = new FormspecFormSource(os.str()); + LocalFormspecHandler* txt_dst = new LocalFormspecHandler("MT_PAUSE_MENU"); + + create_formspec_menu(cur_formspec, invmgr, gamedef, tsrc, device, fs_src, txt_dst); } /******************************************************************************/ @@ -1080,8 +1088,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, const SubgameSpec &gamespec /* Used for local game */, bool simple_singleplayer_mode) { - FormspecFormSource* current_formspec = 0; - TextDest* current_textdest = 0; + GUIFormSpecMenu* current_formspec = 0; video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); @@ -1911,34 +1918,29 @@ void the_game(bool &kill, bool random_input, InputHandler *input, infostream<<"the_game: " <<"Launching inventory"<doPause = false; - menu->setFormSpec(src->getForm(), inventoryloc); - menu->setFormSource(src); - menu->setTextDest(new TextDestPlayerInventory(&client)); - menu->drop(); + current_formspec->setFormSpec(fs_src->getForm(), inventoryloc); } else if(input->wasKeyDown(EscapeKey)) { - show_pause_menu(current_formspec, current_textdest, tsrc, device, + show_pause_menu(¤t_formspec, &client, gamedef, tsrc, device, simple_singleplayer_mode); } else if(input->wasKeyDown(getKeySetting("keymap_chat"))) { - show_chat_menu(current_formspec, current_textdest, tsrc, device, &client,""); + show_chat_menu(¤t_formspec, &client, gamedef, tsrc, device, + &client,""); } else if(input->wasKeyDown(getKeySetting("keymap_cmd"))) { - show_chat_menu(current_formspec, current_textdest, tsrc, device, &client,"/"); + show_chat_menu(¤t_formspec, &client, gamedef, tsrc, device, + &client,"/"); } else if(input->wasKeyDown(getKeySetting("keymap_console"))) { @@ -2396,8 +2398,8 @@ void the_game(bool &kill, bool random_input, InputHandler *input, } else if(event.type == CE_DEATHSCREEN) { - show_deathscreen(current_formspec, current_textdest, - tsrc, device, &client); + show_deathscreen(¤t_formspec, &client, gamedef, tsrc, + device, &client); chat_backend.addMessage(L"", L"You died."); @@ -2411,29 +2413,14 @@ void the_game(bool &kill, bool random_input, InputHandler *input, } else if (event.type == CE_SHOW_FORMSPEC) { - if (current_formspec == 0) - { - /* Create menu */ - /* Note: FormspecFormSource and TextDestPlayerInventory - * are deleted by guiFormSpecMenu */ - current_formspec = new FormspecFormSource(*(event.show_formspec.formspec),¤t_formspec); - current_textdest = new TextDestPlayerInventory(&client,*(event.show_formspec.formname)); - GUIFormSpecMenu *menu = - new GUIFormSpecMenu(device, guiroot, -1, - &g_menumgr, - &client, gamedef, tsrc); - menu->doPause = false; - menu->setFormSource(current_formspec); - menu->setTextDest(current_textdest); - menu->drop(); - } - else - { - assert(current_textdest != 0); - /* update menu */ - current_textdest->setFormName(*(event.show_formspec.formname)); - current_formspec->setForm(*(event.show_formspec.formspec)); - } + FormspecFormSource* fs_src = + new FormspecFormSource(*(event.show_formspec.formspec)); + TextDestPlayerInventory* txt_dst = + new TextDestPlayerInventory(&client,*(event.show_formspec.formname)); + + create_formspec_menu(¤t_formspec, &client, gamedef, + tsrc, device, fs_src, txt_dst); + delete(event.show_formspec.formspec); delete(event.show_formspec.formname); } @@ -2986,19 +2973,14 @@ void the_game(bool &kill, bool random_input, InputHandler *input, InventoryLocation inventoryloc; inventoryloc.setNodeMeta(nodepos); - /* Create menu */ - - GUIFormSpecMenu *menu = - new GUIFormSpecMenu(device, guiroot, -1, - &g_menumgr, - &client, gamedef, tsrc); - menu->doPause = false; - menu->setFormSpec(meta->getString("formspec"), - inventoryloc); - menu->setFormSource(new NodeMetadataFormSource( - &client.getEnv().getClientMap(), nodepos)); - menu->setTextDest(new TextDestNodeMetadata(nodepos, &client)); - menu->drop(); + NodeMetadataFormSource* fs_src = new NodeMetadataFormSource( + &client.getEnv().getClientMap(), nodepos); + TextDest* txt_dst = new TextDestNodeMetadata(nodepos, &client); + + create_formspec_menu(¤t_formspec, &client, gamedef, + tsrc, device, fs_src, txt_dst); + + current_formspec->setFormSpec(meta->getString("formspec"), inventoryloc); } // Otherwise report right click to server else diff --git a/src/guiEngine.cpp b/src/guiEngine.cpp index bba00064..b929c4f7 100644 --- a/src/guiEngine.cpp +++ b/src/guiEngine.cpp @@ -166,7 +166,7 @@ GUIEngine::GUIEngine( irr::IrrlichtDevice* dev, rect,false,true,0,-1); //create formspecsource - m_formspecgui = new FormspecFormSource("",&m_formspecgui); + m_formspecgui = new FormspecFormSource(""); /* Create menu */ m_menu = @@ -176,12 +176,13 @@ GUIEngine::GUIEngine( irr::IrrlichtDevice* dev, m_menumanager, 0 /* &client */, 0 /* gamedef */, - m_texture_source); + m_texture_source, + m_formspecgui, + m_buttonhandler, + NULL); m_menu->allowClose(false); m_menu->lockSize(true,v2u32(800,600)); - m_menu->setFormSource(m_formspecgui); - m_menu->setTextDest(m_buttonhandler); // Initialize scripting diff --git a/src/guiFormSpecMenu.cpp b/src/guiFormSpecMenu.cpp index 881b4c5f..962d1518 100644 --- a/src/guiFormSpecMenu.cpp +++ b/src/guiFormSpecMenu.cpp @@ -68,20 +68,22 @@ with this program; if not, write to the Free Software Foundation, Inc., GUIFormSpecMenu::GUIFormSpecMenu(irr::IrrlichtDevice* dev, gui::IGUIElement* parent, s32 id, IMenuManager *menumgr, InventoryManager *invmgr, IGameDef *gamedef, - ISimpleTextureSource *tsrc) : + ISimpleTextureSource *tsrc, IFormSource* fsrc, TextDest* tdst, + GUIFormSpecMenu** ext_ptr) : GUIModalMenu(dev->getGUIEnvironment(), parent, id, menumgr), m_device(dev), m_invmgr(invmgr), m_gamedef(gamedef), m_tsrc(tsrc), - m_form_src(NULL), - m_text_dst(NULL), m_selected_item(NULL), m_selected_amount(0), m_selected_dragging(false), m_tooltip_element(NULL), m_allowclose(true), - m_lock(false) + m_lock(false), + m_form_src(fsrc), + m_text_dst(tdst), + m_ext_ptr(ext_ptr) { current_keys_pending.key_down = false; current_keys_pending.key_up = false; @@ -95,8 +97,18 @@ GUIFormSpecMenu::~GUIFormSpecMenu() removeChildren(); delete m_selected_item; - delete m_form_src; - delete m_text_dst; + + if (m_form_src != NULL) { + delete m_form_src; + } + if (m_text_dst != NULL) { + delete m_text_dst; + } + + if (m_ext_ptr != NULL) { + assert(*m_ext_ptr == this); + *m_ext_ptr = NULL; + } } void GUIFormSpecMenu::removeChildren() diff --git a/src/guiFormSpecMenu.h b/src/guiFormSpecMenu.h index 6f7de158..016eb0e7 100644 --- a/src/guiFormSpecMenu.h +++ b/src/guiFormSpecMenu.h @@ -190,7 +190,10 @@ public: IMenuManager *menumgr, InventoryManager *invmgr, IGameDef *gamedef, - ISimpleTextureSource *tsrc + ISimpleTextureSource *tsrc, + IFormSource* fs_src, + TextDest* txt_dst, + GUIFormSpecMenu** ext_ptr ); ~GUIFormSpecMenu(); @@ -206,12 +209,18 @@ public: // form_src is deleted by this GUIFormSpecMenu void setFormSource(IFormSource *form_src) { + if (m_form_src != NULL) { + delete m_form_src; + } m_form_src = form_src; } // text_dst is deleted by this GUIFormSpecMenu void setTextDest(TextDest *text_dst) { + if (m_text_dst != NULL) { + delete m_text_dst; + } m_text_dst = text_dst; } @@ -268,8 +277,6 @@ protected: std::string m_formspec_string; InventoryLocation m_current_inventory_location; - IFormSource *m_form_src; - TextDest *m_text_dst; std::vector m_inventorylists; std::vector m_backgrounds; @@ -305,6 +312,10 @@ protected: video::SColor m_slotbg_h; video::SColor m_slotbordercolor; private: + IFormSource* m_form_src; + TextDest* m_text_dst; + GUIFormSpecMenu** m_ext_ptr; + typedef struct { v2s32 size; s32 helptext_h; @@ -360,16 +371,13 @@ private: class FormspecFormSource: public IFormSource { public: - FormspecFormSource(std::string formspec,FormspecFormSource** game_formspec) + FormspecFormSource(std::string formspec) { m_formspec = formspec; - m_game_formspec = game_formspec; } ~FormspecFormSource() - { - *m_game_formspec = 0; - } + {} void setForm(std::string formspec) { m_formspec = formspec; @@ -381,7 +389,6 @@ public: } std::string m_formspec; - FormspecFormSource** m_game_formspec; }; #endif -- 2.30.2