Fix formspec replacement handling for in game formspecs 1240/head
authorsapier <Sapier at GMX dot net>
Sun, 20 Apr 2014 00:40:25 +0000 (02:40 +0200)
committersapier <Sapier at GMX dot net>
Tue, 22 Apr 2014 18:59:01 +0000 (20:59 +0200)
src/game.cpp
src/guiEngine.cpp
src/guiFormSpecMenu.cpp
src/guiFormSpecMenu.h

index 6265c430a1a95a4dd7e1cab2728b7be2c06fb878..58a26e943a17e6f46015c8866fd8d481d4c0ad0e 100644 (file)
@@ -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,&current_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,&current_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(),&current_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"<<std::endl;
                        
-                       GUIFormSpecMenu *menu =
-                               new GUIFormSpecMenu(device, guiroot, -1,
-                                       &g_menumgr,
-                                       &client, gamedef, tsrc);
+                       PlayerInventoryFormSource* fs_src = new PlayerInventoryFormSource(&client);
+                       TextDest* txt_dst = new TextDestPlayerInventory(&client);
+
+                       create_formspec_menu(&current_formspec, &client, gamedef, tsrc, device, fs_src, txt_dst);
 
                        InventoryLocation inventoryloc;
                        inventoryloc.setCurrentPlayer();
-
-                       PlayerInventoryFormSource *src = new PlayerInventoryFormSource(&client);
-                       assert(src);
-                       menu->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(&current_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(&current_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(&current_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(&current_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),&current_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(&current_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(&current_formspec, &client, gamedef,
+                                                       tsrc, device, fs_src, txt_dst);
+
+                                       current_formspec->setFormSpec(meta->getString("formspec"), inventoryloc);
                                }
                                // Otherwise report right click to server
                                else
index bba0006403a5e859a84617e8208469162b8277b5..b929c4f7121295707dbd26aefb3bb3442856788d 100644 (file)
@@ -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
 
index 881b4c5fc01482ccb501ee50fb5ca694de8c63c8..962d151888f3bb2cffd5430c6e8df318a9d5795a 100644 (file)
@@ -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()
index 6f7de158b505572018e379fd572d41ef1afcc976..016eb0e7e968d90d2d80b9ac3a86c73a4bf9becf 100644 (file)
@@ -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<ListDrawSpec> m_inventorylists;
        std::vector<ImageDrawSpec> 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