Formspecs: Introduce formspec_version to mods
authorSmallJoker <mk939@ymail.com>
Tue, 10 Sep 2019 19:18:42 +0000 (21:18 +0200)
committerSmallJoker <mk939@ymail.com>
Sat, 14 Sep 2019 17:43:08 +0000 (19:43 +0200)
builtin/game/features.lua
doc/lua_api.txt
src/client/client.cpp
src/client/game.cpp
src/gui/guiFormSpecMenu.cpp
src/gui/guiFormSpecMenu.h
src/network/networkprotocol.h
src/network/serverpackethandler.cpp
src/remoteplayer.h
src/script/lua_api/l_server.cpp
src/server.cpp

index cf21303c7c74420f68ef9d765561e3a5b3a01591..51d21e86c8a2825fc01115ec14c4c8a74b824efe 100644 (file)
@@ -13,6 +13,7 @@ core.features = {
        object_use_texture_alpha = true,
        object_independent_selectionbox = true,
        httpfetch_binary_data = true,
+       formspec_version_element = true,
 }
 
 function core.has_feature(arg)
index 7fae206034f8bdbffbc987b50c7a83d31472a2a1..b809e18c3d70dd0cbb4911551f2a288bec3b3c4d 100644 (file)
@@ -1959,6 +1959,15 @@ Examples
 Elements
 --------
 
+### `formspec_version[<version>]`
+
+* Set the formspec version to a certain number. If not specified,
+  version 1 is assumed.
+* Must be specified before `size` element.
+* Clients older than this version can neither show newer elements nor display
+  elements with new arguments correctly.
+* Available since feature `formspec_version_element`.
+
 ### `size[<W>,<H>,<fixed_size>]`
 
 * Define the size of the menu in inventory slots
@@ -1995,6 +2004,7 @@ Elements
 
 ### `real_coordinates[<bool>]`
 
+* INFORMATION: Enable it automatically using `formspec_version` version 2 or newer.
 * When set to true, all following formspec elements will use the new coordinate system.
 * If used immediately after `size`, `position`, `anchor`, and `no_prepend` elements
   (if present), the form size will use the new coordinate system.
@@ -2114,6 +2124,7 @@ Elements
   image shall be sized 8 times 16px  times  4 times 16px
 * If `auto_clip` is `true`, the background is clipped to the formspec size
   (`x` and `y` are used as offset values, `w` and `h` are ignored)
+* Available since formspec version 2
 
 ### `pwdfield[<X>,<Y>;<W>,<H>;<name>;<label>]`
 
@@ -3788,6 +3799,8 @@ Utilities
           -- Specifies whether binary data can be uploaded or downloaded using
           -- the HTTP API (5.1.0)
           httpfetch_binary_data = true,
+          -- Whether formspec_version[<version>] may be used (5.1.0)
+          formspec_version_element = true,
       }
 
 * `minetest.has_feature(arg)`: returns `boolean, missing_features`
@@ -3807,6 +3820,7 @@ Utilities
           avg_jitter = 0.03,         -- average packet time jitter
           connection_uptime = 200,   -- seconds since client connected
           protocol_version = 32,     -- protocol version used by client
+          formspec_version = 2,      -- supported formspec version
           -- following information is available on debug build only!!!
           -- DO NOT USE IN MODS
           --ser_vers = 26,             -- serialization version used by client
index 9535acc8e57ebcd18af6bc1bd374cf7cc94ddd6c..f6be3186fbab0b959c0f63fb62d1f42d6fcc4aa8 100644 (file)
@@ -1222,12 +1222,13 @@ void Client::sendRespawn()
 void Client::sendReady()
 {
        NetworkPacket pkt(TOSERVER_CLIENT_READY,
-                       1 + 1 + 1 + 1 + 2 + sizeof(char) * strlen(g_version_hash));
+                       1 + 1 + 1 + 1 + 2 + sizeof(char) * strlen(g_version_hash) + 2);
 
        pkt << (u8) VERSION_MAJOR << (u8) VERSION_MINOR << (u8) VERSION_PATCH
                << (u8) 0 << (u16) strlen(g_version_hash);
 
        pkt.putRawString(g_version_hash, (u16) strlen(g_version_hash));
+       pkt << (u16)FORMSPEC_API_VERSION;
        Send(&pkt);
 }
 
index b5508f2cb5d654e55c1940dd7c45b3c9452c6f5f..bc35ade855714ebda9080fe689e199ac1791fc9e 100644 (file)
@@ -4055,7 +4055,7 @@ void Game::showPauseMenu()
        float ypos = simple_singleplayer_mode ? 0.7f : 0.1f;
        std::ostringstream os;
 
-       os << FORMSPEC_VERSION_STRING  << SIZE_TAG
+       os << FORMSPEC_VERSION_STRING << SIZE_TAG
                << "button_exit[4," << (ypos++) << ";3,0.5;btn_continue;"
                << strgettext("Continue") << "]";
 
index e02abf018a422953b579bbb6e42499d2ccf5a6b3..f291b4e877b09747bf4d9632ba4c958638799274 100644 (file)
@@ -2167,6 +2167,9 @@ void GUIFormSpecMenu::parseElement(parserData* data, const std::string &element)
        if (element.empty())
                return;
 
+       if (parseVersionDirect(element))
+               return;
+
        std::vector<std::string> parts = split(element,'[');
 
        // ugly workaround to keep compatibility
@@ -2503,7 +2506,7 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
        }
 
        /* Copy of the "real_coordinates" element for after the form size. */
-       mydata.real_coordinates = false;
+       mydata.real_coordinates = m_formspec_version >= 2;
        for (; i < elements.size(); i++) {
                std::vector<std::string> parts = split(elements[i], '[');
                std::string name = trim(parts[0]);
@@ -2648,10 +2651,14 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
        if (enable_prepends) {
                // Backup the coordinates so that prepends can use the coordinates of choice.
                bool rc_backup = mydata.real_coordinates;
+               bool version_backup = m_formspec_version;
                mydata.real_coordinates = false; // Old coordinates by default.
+
                std::vector<std::string> prepend_elements = split(m_formspec_prepend, ']');
                for (const auto &element : prepend_elements)
                        parseElement(&mydata, element);
+
+               m_formspec_version = version_backup;
                mydata.real_coordinates = rc_backup; // Restore coordinates
        }
 
index e4dc6615199d3ce5fa36e1fa0c1f0d76bef51788..46df0930cc1b9d0993f9e2f26ca8ef429f6e586c 100644 (file)
@@ -472,7 +472,7 @@ protected:
 private:
        IFormSource        *m_form_src;
        TextDest           *m_text_dst;
-       u32                 m_formspec_version = 0;
+       u16                 m_formspec_version = 1;
        std::string         m_focused_element = "";
        JoystickController *m_joystick;
 
@@ -591,7 +591,7 @@ public:
 
        void setForm(const std::string &formspec)
        {
-               m_formspec = FORMSPEC_VERSION_STRING + formspec;
+               m_formspec = formspec;
        }
 
        const std::string &getForm() const
index 05737d0a93dafaf7a7cc11452a80f5e80c69d9e7..f603ed6c5d43fb70ab1086b237ac67bfb5dd85a0 100644 (file)
@@ -198,6 +198,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
        PROTOCOL VERSION 38:
                Incremental inventory sending mode
                Unknown inventory serialization fields no longer throw an error
+               Mod-specific formspec version
 */
 
 #define LATEST_PROTOCOL_VERSION 38
@@ -219,7 +220,16 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #define PASSWORD_SIZE 28       // Maximum password length. Allows for
                                // base64-encoded SHA-1 (27+\0).
 
-#define FORMSPEC_API_VERSION 1
+/*
+       Changes by FORMSPEC_API_VERSION:
+
+       FORMSPEC VERSION 1:
+               (too much)
+       FORMSPEC VERSION 2:
+               Forced real coordinates
+               background[]: 9-slice scaling parameters
+*/
+#define FORMSPEC_API_VERSION 2
 #define FORMSPEC_VERSION_STRING "formspec_version[" TOSTRING(FORMSPEC_API_VERSION) "]"
 
 #define TEXTURENAME_ALLOWED_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_.-"
index 6cb3b3520aeb8a5a447e4dd94be1bb101b25513a..9999a1690ce4fb54ef180d1b29af060fc12dd495 100644 (file)
@@ -386,6 +386,9 @@ void Server::handleCommand_ClientReady(NetworkPacket* pkt)
                        peer_id, major_ver, minor_ver, patch_ver,
                        full_ver);
 
+       if (pkt->getRemainingBytes() >= 2)
+               *pkt >> playersao->getPlayer()->formspec_version;
+
        const std::vector<std::string> &players = m_clients.getPlayerNames();
        NetworkPacket list_pkt(TOCLIENT_UPDATE_PLAYER_LIST, 0, peer_id);
        list_pkt << (u8) PLAYER_LIST_INIT << (u16) players.size();
index 260504fb4379400455a5a77ac139c34a1fb29f0b..831bfe956af7b21cb022be99b35ed29562c2ebab 100644 (file)
@@ -130,6 +130,9 @@ public:
 
        u16 protocol_version = 0;
 
+       // v1 for clients older than 5.1.0-dev
+       u16 formspec_version = 1;
+
        session_t getPeerId() const { return m_peer_id; }
 
        void setPeerId(session_t peer_id) { m_peer_id = peer_id; }
index 6017a5475fda3b017f708b54b75cb1cbc9164e02..7c083e65296d0ee7b47893a2d3e907e5f512c1c7 100644 (file)
@@ -233,6 +233,10 @@ int ModApiServer::l_get_player_information(lua_State *L)
        lua_pushnumber(L, prot_vers);
        lua_settable(L, table);
 
+       lua_pushstring(L, "formspec_version");
+       lua_pushnumber(L, player->formspec_version);
+       lua_settable(L, table);
+
 #ifndef NDEBUG
        lua_pushstring(L,"serialization_version");
        lua_pushnumber(L, ser_vers);
index f6bf491becbdf5bffe31f31ddf75315bc6f7b613..6a51139d9ed6a0db83d00cc36ab3ababe3af482e 100644 (file)
@@ -1568,7 +1568,7 @@ void Server::SendChatMessage(session_t peer_id, const ChatMessage &message)
 void Server::SendShowFormspecMessage(session_t peer_id, const std::string &formspec,
        const std::string &formname)
 {
-       NetworkPacket pkt(TOCLIENT_SHOW_FORMSPEC, 0 , peer_id);
+       NetworkPacket pkt(TOCLIENT_SHOW_FORMSPEC, 0, peer_id);
        if (formspec.empty()){
                //the client should close the formspec
                //but make sure there wasn't another one open in meantime
@@ -1579,7 +1579,7 @@ void Server::SendShowFormspecMessage(session_t peer_id, const std::string &forms
                pkt.putLongString("");
        } else {
                m_formspec_state_data[peer_id] = formname;
-               pkt.putLongString(FORMSPEC_VERSION_STRING + formspec);
+               pkt.putLongString(formspec);
        }
        pkt << formname;
 
@@ -1908,7 +1908,8 @@ void Server::SendPlayerInventoryFormspec(session_t peer_id)
                return;
 
        NetworkPacket pkt(TOCLIENT_INVENTORY_FORMSPEC, 0, peer_id);
-       pkt.putLongString(FORMSPEC_VERSION_STRING + player->inventory_formspec);
+       pkt.putLongString(player->inventory_formspec);
+
        Send(&pkt);
 }
 
@@ -1920,7 +1921,7 @@ void Server::SendPlayerFormspecPrepend(session_t peer_id)
                return;
 
        NetworkPacket pkt(TOCLIENT_FORMSPEC_PREPEND, 0, peer_id);
-       pkt << FORMSPEC_VERSION_STRING + player->formspec_prepend;
+       pkt << player->formspec_prepend;
        Send(&pkt);
 }