Add TOCLIENT_SHOW_FORMSPEC to display formspecs at client from lua
authorsapier <Sapier at GMX dot net>
Wed, 2 Jan 2013 19:45:04 +0000 (19:45 +0000)
committerPerttu Ahola <celeron55@gmail.com>
Wed, 2 Jan 2013 18:59:37 +0000 (20:59 +0200)
doc/lua_api.txt
src/client.cpp
src/client.h
src/clientserver.h
src/game.cpp
src/scriptapi.cpp
src/server.cpp
src/server.h

index 117d4b24e9624511e603e353ecd1b60e109c69b3..ebad1dad2c62ceaca1319afd8272659e9e51314c 100644 (file)
@@ -888,6 +888,9 @@ minetest.get_inventory(location) -> InvRef
 minetest.create_detached_inventory(name, callbacks) -> InvRef
 ^ callbacks: See "Detached inventory callbacks"
 ^ Creates a detached inventory. If it already exists, it is cleared.
+minetest.show_formspec(playername, formspec)
+^ playername: name of player to show formspec
+^ formspec: formspec to display
 
 Item handling:
 minetest.inventorycube(img1, img2, img3)
index cb7afe29f8fe8bc5ed0bc39e5d5dd95c07938c48..216d86cd412c6d0ffa0e9ae3cd1d8593614887e5 100644 (file)
@@ -1900,6 +1900,20 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
                }
                inv->deSerialize(is);
        }
+       else if(command == TOCLIENT_SHOW_FORMSPEC)
+       {
+               std::string datastring((char*)&data[2], datasize-2);
+               std::istringstream is(datastring, std::ios_base::binary);
+
+               std::string formspec = deSerializeLongString(is);
+
+               ClientEvent event;
+               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);
+               m_client_event_queue.push_back(event);
+       }
        else
        {
                infostream<<"Client: Ignoring unknown command "
index 155b4386bd74ffac8c05c1698d180472bc997273..e46da6b0ec840fa168f7ab7f3e697bd289a5ebd3 100644 (file)
@@ -154,7 +154,8 @@ enum ClientEventType
        CE_PLAYER_DAMAGE,
        CE_PLAYER_FORCE_MOVE,
        CE_DEATHSCREEN,
-       CE_TEXTURES_UPDATED
+       CE_TEXTURES_UPDATED,
+       CE_SHOW_FORMSPEC
 };
 
 struct ClientEvent
@@ -176,6 +177,9 @@ struct ClientEvent
                        f32 camera_point_target_y;
                        f32 camera_point_target_z;
                } deathscreen;
+               struct{
+                       std::string* formspec;
+               } show_formspec;
                struct{
                } textures_updated;
        };
index db551a90c410c37164a8de69e80c4a352047c3a2..bb7e1181efafbe16b688530de51b3962af922127 100644 (file)
@@ -77,9 +77,11 @@ SharedBuffer<u8> makePacket_TOCLIENT_TIME_OF_DAY(u16 time, float time_speed);
                GENERIC_CMD_SET_ATTACHMENT
        PROTOCOL_VERSION 15:
                Serialization format changes
+       PROTOCOL_VERSION 16:
+               TOCLIENT_SHOW_FORMSPEC
 */
 
-#define LATEST_PROTOCOL_VERSION 15
+#define LATEST_PROTOCOL_VERSION 16
 
 // Server's supported network protocol range
 #define SERVER_PROTOCOL_VERSION_MIN 13
@@ -354,6 +356,12 @@ enum ToClientCommand
                u8[len] name
                [2] serialized inventory
        */
+       TOCLIENT_SHOW_FORMSPEC = 0x44,
+       /*
+               [0] u16 command
+               u16 len
+               u8[len] formspec
+       */
 };
 
 enum ToServerCommand
index 541127f5db065f1edb4685cc64035cf8172feaac..15bf3f09f60e759ffceac470a1b9704a50e05011 100644 (file)
@@ -192,6 +192,32 @@ public:
        Client *m_client;
 };
 
+class FormspecFormSource: public IFormSource
+{
+public:
+       FormspecFormSource(std::string formspec,FormspecFormSource** game_formspec)
+       {
+               m_formspec = formspec;
+               m_game_formspec = game_formspec;
+       }
+
+       ~FormspecFormSource()
+       {
+               *m_game_formspec = 0;
+       }
+
+       void setForm(std::string formspec) {
+               m_formspec = formspec;
+       }
+
+       std::string getForm()
+       {
+               return m_formspec;
+       }
+
+       std::string m_formspec;
+       FormspecFormSource** m_game_formspec;
+};
 /*
        Hotbar draw routine
 */
@@ -901,6 +927,7 @@ void the_game(
        bool simple_singleplayer_mode
 )
 {
+       FormspecFormSource* current_formspec = 0;
        video::IVideoDriver* driver = device->getVideoDriver();
        scene::ISceneManager* smgr = device->getSceneManager();
        
@@ -2067,6 +2094,27 @@ void the_game(
                                        player->setPosition(player->getPosition() + v3f(0,-BS,0));
                                        camera.update(player, busytime, screensize);*/
                                }
+                               else if (event.type == CE_SHOW_FORMSPEC)
+                               {
+                                       if (current_formspec == 0)
+                                       {
+                                               /* Create menu */
+                                               current_formspec = new FormspecFormSource(*(event.show_formspec.formspec),&current_formspec);
+
+                                               GUIFormSpecMenu *menu =
+                                                               new GUIFormSpecMenu(device, guiroot, -1,
+                                                                               &g_menumgr,
+                                                                               &client, gamedef);
+                                               menu->setFormSource(current_formspec);
+                                               menu->drop();
+                                       }
+                                       else
+                                       {
+                                               /* update menu */
+                                               current_formspec->setForm(*(event.show_formspec.formspec));
+                                       }
+                                       delete(event.show_formspec.formspec);
+                               }
                                else if(event.type == CE_TEXTURES_UPDATED)
                                {
                                        update_wielded_item_trigger = true;
index d086b7e510549242b6005045df246ac9b9e31958..83987fc9b477818014906895b9eed52480f20641 100644 (file)
@@ -4899,6 +4899,21 @@ static int l_create_detached_inventory_raw(lua_State *L)
        return 1;
 }
 
+// create_detached_formspec_raw(name)
+static int l_show_formspec(lua_State *L)
+{
+       const char *playername = luaL_checkstring(L, 1);
+       const char *formspec = luaL_checkstring(L, 2);
+
+       if(get_server(L)->showFormspec(playername,formspec))
+       {
+               lua_pushboolean(L, true);
+       }else{
+               lua_pushboolean(L, false);
+       }
+       return 1;
+}
+
 // get_dig_params(groups, tool_capabilities[, time_from_last_punch])
 static int l_get_dig_params(lua_State *L)
 {
@@ -5228,6 +5243,7 @@ static const struct luaL_Reg minetest_f [] = {
        {"unban_player_or_ip", l_unban_player_of_ip},
        {"get_inventory", l_get_inventory},
        {"create_detached_inventory_raw", l_create_detached_inventory_raw},
+       {"show_formspec", l_show_formspec},
        {"get_dig_params", l_get_dig_params},
        {"get_hit_params", l_get_hit_params},
        {"get_current_modname", l_get_current_modname},
index 39407f961f4d80236f1a1bcb036c070fb6ec96fc..f4b5ee872a80c5848ee86463039fe6fc4caca026 100644 (file)
@@ -3638,6 +3638,24 @@ void Server::SendChatMessage(u16 peer_id, const std::wstring &message)
        // Send as reliable
        m_con.Send(peer_id, 0, data, true);
 }
+void Server::SendShowFormspecMessage(u16 peer_id, const std::string formspec)
+{
+       DSTACK(__FUNCTION_NAME);
+
+       std::ostringstream os(std::ios_base::binary);
+       u8 buf[12];
+
+       // Write command
+       writeU16(buf, TOCLIENT_SHOW_FORMSPEC);
+       os.write((char*)buf, 2);
+       os<<serializeLongString(formspec);
+
+       // Make data buffer
+       std::string s = os.str();
+       SharedBuffer<u8> data((u8*)s.c_str(), s.size());
+       // Send as reliable
+       m_con.Send(peer_id, 0, data, true);
+}
 
 void Server::BroadcastChatMessage(const std::wstring &message)
 {
@@ -4578,6 +4596,20 @@ void Server::notifyPlayer(const char *name, const std::wstring msg)
        SendChatMessage(player->peer_id, std::wstring(L"Server: -!- ")+msg);
 }
 
+bool Server::showFormspec(const char *playername, const std::string &formspec)
+{
+       Player *player = m_env->getPlayer(playername);
+
+       if(!player)
+       {
+               infostream<<"showFormspec: couldn't find player:"<<playername<<std::endl;
+               return false;
+       }
+
+       SendShowFormspecMessage(player->peer_id,formspec);
+       return true;
+}
+
 void Server::notifyPlayers(const std::wstring msg)
 {
        BroadcastChatMessage(msg);
index ce826ae529a62dee58cb2a40467a99d85ccc0ece..19c29cbd711353518a832ae7815c8098e833027a 100644 (file)
@@ -583,6 +583,7 @@ public:
                m_async_fatal_error.set(error);
        }
 
+       bool showFormspec(const char *name, const std::string &formspec);
 private:
 
        // con::PeerHandler implementation.
@@ -620,6 +621,7 @@ private:
        void SendMovePlayer(u16 peer_id);
        void SendPlayerPrivileges(u16 peer_id);
        void SendPlayerInventoryFormspec(u16 peer_id);
+       void SendShowFormspecMessage(u16 peer_id, const std::string formspec);
        /*
                Send a node removal/addition event to all clients except ignore_id.
                Additionally, if far_players!=NULL, players further away than