From 0fe91a7a231ecbf131db593b3cb01392ffb83108 Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Tue, 10 Jun 2025 19:02:30 +0200 Subject: [PATCH] make independent --- doc/lua_api.md | 8 ++++---- src/client/game.cpp | 8 ++------ src/client/game_formspec.cpp | 13 ++++++++++--- src/client/game_formspec.h | 4 +++- src/client/localplayer.h | 1 + src/network/clientpackethandler.cpp | 1 + src/network/serveropcodes.cpp | 1 + src/remoteplayer.h | 2 ++ src/script/lua_api/l_object.cpp | 4 +++- src/server.cpp | 9 +++------ 10 files changed, 30 insertions(+), 21 deletions(-) diff --git a/doc/lua_api.md b/doc/lua_api.md index b0b548753..7350b140c 100644 --- a/doc/lua_api.md +++ b/doc/lua_api.md @@ -6873,9 +6873,9 @@ Formspec * `playername`: name of player to show formspec * `formname`: name passed to `on_player_receive_fields` callbacks. * It should follow the `"modname:"` naming convention. - * If empty: Reshows the inventory formspec. Servers and - clients >= 5.13.0 will update the inventory formspec - (`ObjectRef:set_inventory_formspec`) for future opens. + * If empty: Shows an inventory formspec. Use + `ObjectRef:set_inventory_formspec` to change it for future opens. + Supported if server AND client are both of version >= 5.13.0. * `formspec`: formspec to display * `core.close_formspec(playername, formname)` * `playername`: name of player to close formspec @@ -8654,7 +8654,7 @@ child will follow movement and rotation of that bone. * Returns `nil` if no attribute found. * `get_meta()`: Returns metadata associated with the player (a PlayerMetaRef). * `set_inventory_formspec(formspec)` - * Redefine player's inventory form + * Redefine player's inventory form. This sends an update to the player. * Should usually be called in `on_joinplayer` * If `formspec` is `""`, the player's inventory is disabled. * `get_inventory_formspec()`: returns a formspec string diff --git a/src/client/game.cpp b/src/client/game.cpp index 96832b4ed..1ad670290 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -1925,7 +1925,7 @@ void Game::processKeyInput() if (g_settings->getBool("continuous_forward")) toggleAutoforward(); } else if (wasKeyDown(KeyType::INVENTORY)) { - m_game_formspec.showPlayerInventory(); + m_game_formspec.showPlayerInventory(nullptr); } else if (input->cancelPressed()) { #ifdef __ANDROID__ m_android_chat_open = false; @@ -2717,11 +2717,7 @@ void Game::handleClientEvent_ShowFormSpec(ClientEvent *event, CameraOrientation auto &fs = event->show_formspec; if (fs.formname->empty() && !fs.formspec->empty()) { - // Overwrite the inventory formspec - LocalPlayer *player = client->getEnv().getLocalPlayer(); - player->inventory_formspec = *fs.formspec; - - m_game_formspec.showPlayerInventory(); + m_game_formspec.showPlayerInventory(fs.formspec); } else { m_game_formspec.showFormSpec(*fs.formspec, *fs.formname); diff --git a/src/client/game_formspec.cpp b/src/client/game_formspec.cpp index 3d8dc6fc8..7440afe3d 100644 --- a/src/client/game_formspec.cpp +++ b/src/client/game_formspec.cpp @@ -178,6 +178,10 @@ public: const std::string &getForm() const { LocalPlayer *player = m_client->getEnv().getLocalPlayer(); + + if (!player->inventory_formspec_override.empty()) + return player->inventory_formspec_override; + return player->inventory_formspec; } @@ -304,7 +308,7 @@ void GameFormSpec::showNodeFormspec(const std::string &formspec, const v3s16 &no m_formspec->setFormSpec(formspec, inventoryloc); } -void GameFormSpec::showPlayerInventory() +void GameFormSpec::showPlayerInventory(const std::string *fs_override) { /* * Don't permit to open inventory is CAO or player doesn't exists. @@ -327,10 +331,13 @@ void GameFormSpec::showPlayerInventory() return; } - if (fs_src->getForm().empty()) { + const std::string &formspec = fs_override ? *fs_override : fs_src->getForm(); + if (formspec.empty()) { delete fs_src; return; } + if (fs_override) + player->inventory_formspec_override = *fs_override; TextDest *txt_dst = new TextDestPlayerInventory(m_client); @@ -338,7 +345,7 @@ void GameFormSpec::showPlayerInventory() &m_input->joystick, fs_src, txt_dst, m_client->getFormspecPrepend(), m_client->getSoundManager()); - m_formspec->setFormSpec(fs_src->getForm(), inventoryloc); + m_formspec->setFormSpec(formspec, inventoryloc); } #define SIZE_TAG "size[11,5.5,true]" // Fixed size (ignored in touchscreen mode) diff --git a/src/client/game_formspec.h b/src/client/game_formspec.h index 980dac47f..022b8a55b 100644 --- a/src/client/game_formspec.h +++ b/src/client/game_formspec.h @@ -34,7 +34,9 @@ struct GameFormSpec // Currently only used for the in-game settings menu. void showPauseMenuFormSpec(const std::string &formspec, const std::string &formname); void showNodeFormspec(const std::string &formspec, const v3s16 &nodepos); - void showPlayerInventory(); + /// If ` fs_override`: Uses `player->inventory_formspec`. + /// If `!fs_override`: Uses a temporary formspec until an update is received. + void showPlayerInventory(const std::string *fs_override); void showDeathFormspecLegacy(); // Shows the hardcoded "main" pause menu. void showPauseMenu(); diff --git a/src/client/localplayer.h b/src/client/localplayer.h index 93b768ceb..047a95372 100644 --- a/src/client/localplayer.h +++ b/src/client/localplayer.h @@ -99,6 +99,7 @@ public: std::string hotbar_image = ""; std::string hotbar_selected_image = ""; + std::string inventory_formspec_override; video::SColor light_color = video::SColor(255, 255, 255, 255); diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp index bb1930d96..6cd7150c6 100644 --- a/src/network/clientpackethandler.cpp +++ b/src/network/clientpackethandler.cpp @@ -902,6 +902,7 @@ void Client::handleCommand_InventoryFormSpec(NetworkPacket* pkt) // Store formspec in LocalPlayer player->inventory_formspec = pkt->readLongString(); + player->inventory_formspec_override.clear(); } void Client::handleCommand_DetachedInventory(NetworkPacket* pkt) diff --git a/src/network/serveropcodes.cpp b/src/network/serveropcodes.cpp index b50e13082..f75e1f5cd 100644 --- a/src/network/serveropcodes.cpp +++ b/src/network/serveropcodes.cpp @@ -178,6 +178,7 @@ const ClientCommandFactory clientCommandFactoryTable[TOCLIENT_NUM_MSG_TYPES] = { "TOCLIENT_STOP_SOUND", 0, true }, // 0x40 { "TOCLIENT_PRIVILEGES", 0, true }, // 0x41 { "TOCLIENT_INVENTORY_FORMSPEC", 0, true }, // 0x42 + // ^ `channel` MUST be the same as TOCLIENT_SHOW_FORMSPEC { "TOCLIENT_DETACHED_INVENTORY", 0, true }, // 0x43 { "TOCLIENT_SHOW_FORMSPEC", 0, true }, // 0x44 { "TOCLIENT_MOVEMENT", 0, true }, // 0x45 diff --git a/src/remoteplayer.h b/src/remoteplayer.h index 1f2f8df9c..1f56bc517 100644 --- a/src/remoteplayer.h +++ b/src/remoteplayer.h @@ -121,6 +121,8 @@ public: u16 protocol_version = 0; u16 formspec_version = 0; + bool inventory_formspec_overridden = false; + /// returns PEER_ID_INEXISTENT when PlayerSAO is not ready session_t getPeerId() const { return m_peer_id; } diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index 19c513dd3..eed2215ac 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -1574,7 +1574,9 @@ int ObjectRef::l_set_inventory_formspec(lua_State *L) auto formspec = readParam(L, 2); - if (formspec != player->inventory_formspec) { + if (player->inventory_formspec_overridden + || formspec != player->inventory_formspec) { + player->inventory_formspec_overridden = false; player->inventory_formspec = formspec; getServer(L)->reportInventoryFormspecModified(player->getName()); } diff --git a/src/server.cpp b/src/server.cpp index 338068d96..d063f8865 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1595,11 +1595,10 @@ void Server::SendShowFormspecMessage(session_t peer_id, const std::string &forms (it->second == formname || formname.empty())) { m_formspec_state_data.erase(peer_id); } - pkt.putLongString(""); } else { m_formspec_state_data[peer_id] = formname; - pkt.putLongString(formspec); } + pkt.putLongString(formspec); pkt << formname; Send(&pkt); @@ -3397,10 +3396,8 @@ bool Server::showFormspec(const char *playername, const std::string &formspec, if (!player) return false; - if (formname.empty() && !formspec.empty()) { - // Overwrite the inventory formspec - player->inventory_formspec = formspec; - } + // To allow re-sending the same inventory formspec. + player->inventory_formspec_overridden = formname.empty() && !formspec.empty(); SendShowFormspecMessage(player->getPeerId(), formspec, formname); return true;