Add core.remove_detached_inventory (#7684)
authorSmallJoker <SmallJoker@users.noreply.github.com>
Wed, 10 Oct 2018 18:48:58 +0000 (20:48 +0200)
committerGitHub <noreply@github.com>
Wed, 10 Oct 2018 18:48:58 +0000 (20:48 +0200)
Breaks backwards compatibility for good
Bump protocol version

builtin/game/detached_inventory.lua
doc/lua_api.txt
src/network/clientpackethandler.cpp
src/network/networkprotocol.h
src/script/lua_api/l_inventory.cpp
src/script/lua_api/l_inventory.h
src/server.cpp
src/server.h

index 420e89ff28dd513244d9b9f3a8dcdec3de72c7c4..2e27168a1daffff1b53cc621f578488119adb94e 100644 (file)
@@ -18,3 +18,7 @@ function core.create_detached_inventory(name, callbacks, player_name)
        return core.create_detached_inventory_raw(name, player_name)
 end
 
+function core.remove_detached_inventory(name)
+       core.detached_inventories[name] = nil
+       return core.remove_detached_inventory_raw(name)
+end
index e144a2c8fa00c6a123969c76829008d4b804429d..19d6482ae2401d28e2ed52777d6b18cce8396dd2 100644 (file)
@@ -4141,6 +4141,8 @@ Inventory
       Note that this parameter is mostly just a workaround and will be removed
       in future releases.
     * Creates a detached inventory. If it already exists, it is cleared.
+* `minetest.remove_detached_inventory(name)`
+    * Returns a `boolean` indicating whether the removal succeeded.
 * `minetest.do_item_eat(hp_change, replace_with_item, itemstack, user, pointed_thing)`:
   returns left over ItemStack.
     * See `minetest.item_eat` and `minetest.register_on_item_eat`
index cbd0d6a5736333ff423231225ccae6b00b4ba8b6..5a62fec3d46484cae73e3c469c48228c62374628 100644 (file)
@@ -843,21 +843,32 @@ void Client::handleCommand_InventoryFormSpec(NetworkPacket* pkt)
 
 void Client::handleCommand_DetachedInventory(NetworkPacket* pkt)
 {
-       std::string datastring(pkt->getString(0), pkt->getSize());
-       std::istringstream is(datastring, std::ios_base::binary);
-
-       std::string name = deSerializeString(is);
+       std::string name;
+       bool keep_inv = true;
+       *pkt >> name >> keep_inv;
 
        infostream << "Client: Detached inventory update: \"" << name
-                       << "\"" << std::endl;
+               << "\", mode=" << (keep_inv ? "update" : "remove") << std::endl;
 
-       Inventory *inv = NULL;
-       if (m_detached_inventories.count(name) > 0)
-               inv = m_detached_inventories[name];
-       else {
+       const auto &inv_it = m_detached_inventories.find(name);
+       if (!keep_inv) {
+               if (inv_it != m_detached_inventories.end()) {
+                       delete inv_it->second;
+                       m_detached_inventories.erase(inv_it);
+               }
+               return;
+       }
+       Inventory *inv = nullptr;
+       if (inv_it == m_detached_inventories.end()) {
                inv = new Inventory(m_itemdef);
                m_detached_inventories[name] = inv;
+       } else {
+               inv = inv_it->second;
        }
+
+       std::string contents;
+       *pkt >> contents;
+       std::istringstream is(contents, std::ios::binary);
        inv->deSerialize(is);
 }
 
index 4e896602bf69e7c45d9b912db4bad90553cef9fb..855afc638fbb0d2b81dd1e2b1e980f93e760df00 100644 (file)
@@ -188,19 +188,21 @@ with this program; if not, write to the Free Software Foundation, Inc.,
                Nodebox version 5
                Add disconnected nodeboxes
                Add TOCLIENT_FORMSPEC_PREPEND
+       PROTOCOL VERSION 37:
+               Redo detached inventory sending
 */
 
-#define LATEST_PROTOCOL_VERSION 36
+#define LATEST_PROTOCOL_VERSION 37
 #define LATEST_PROTOCOL_VERSION_STRING TOSTRING(LATEST_PROTOCOL_VERSION)
 
 // Server's supported network protocol range
-#define SERVER_PROTOCOL_VERSION_MIN 36
+#define SERVER_PROTOCOL_VERSION_MIN 37
 #define SERVER_PROTOCOL_VERSION_MAX LATEST_PROTOCOL_VERSION
 
 // Client's supported network protocol range
 // The minimal version depends on whether
 // send_pre_v25_init is enabled or not
-#define CLIENT_PROTOCOL_VERSION_MIN 36
+#define CLIENT_PROTOCOL_VERSION_MIN 37
 #define CLIENT_PROTOCOL_VERSION_MAX LATEST_PROTOCOL_VERSION
 
 // Constant that differentiates the protocol from random data and other protocols
index 04fa3a196bc391fc1d9e8d9ae06c2462a570dbf4..6e7afa4a4e67bf67575341f79af1ee72b1397d6e 100644 (file)
@@ -536,8 +536,18 @@ int ModApiInventory::l_create_detached_inventory_raw(lua_State *L)
        return 1;
 }
 
+// remove_detached_inventory_raw(name)
+int ModApiInventory::l_remove_detached_inventory_raw(lua_State *L)
+{
+       NO_MAP_LOCK_REQUIRED;
+       const std::string &name = luaL_checkstring(L, 1);
+       lua_pushboolean(L, getServer(L)->removeDetachedInventory(name));
+       return 1;
+}
+
 void ModApiInventory::Initialize(lua_State *L, int top)
 {
        API_FCT(create_detached_inventory_raw);
+       API_FCT(remove_detached_inventory_raw);
        API_FCT(get_inventory);
 }
index 2b7910ac35fa734b0906d31e0b21e338566f4b62..94f670c9d51d0dce1ce7d157b0e50a7952b62634 100644 (file)
@@ -120,6 +120,8 @@ class ModApiInventory : public ModApiBase {
 private:
        static int l_create_detached_inventory_raw(lua_State *L);
 
+       static int l_remove_detached_inventory_raw(lua_State *L);
+
        static int l_get_inventory(lua_State *L);
 
 public:
index 41248c869914a1fea5db51701d364e5a23817da9..678ee387bee36bb33147e1ec65847b196da75d91 100644 (file)
@@ -2478,33 +2478,41 @@ void Server::sendRequestedMedia(session_t peer_id,
 
 void Server::sendDetachedInventory(const std::string &name, session_t peer_id)
 {
-       if(m_detached_inventories.count(name) == 0) {
-               errorstream<<FUNCTION_NAME<<": \""<<name<<"\" not found"<<std::endl;
-               return;
-       }
-       Inventory *inv = m_detached_inventories[name];
-       std::ostringstream os(std::ios_base::binary);
+       const auto &inv_it = m_detached_inventories.find(name);
+       const auto &player_it = m_detached_inventories_player.find(name);
 
-       os << serializeString(name);
-       inv->serialize(os);
+       if (player_it == m_detached_inventories_player.end() ||
+                       player_it->second.empty()) {
+               // OK. Send to everyone
+       } else {
+               RemotePlayer *p = m_env->getPlayer(player_it->second.c_str());
+               if (!p)
+                       return; // Player is offline
 
-       // Make data buffer
-       std::string s = os.str();
+               if (peer_id != PEER_ID_INEXISTENT && peer_id != p->getPeerId())
+                       return; // Caller requested send to a different player, so don't send.
+
+               peer_id = p->getPeerId();
+       }
 
        NetworkPacket pkt(TOCLIENT_DETACHED_INVENTORY, 0, peer_id);
-       pkt.putRawString(s.c_str(), s.size());
+       pkt << name;
 
-       const std::string &check = m_detached_inventories_player[name];
-       if (peer_id == PEER_ID_INEXISTENT) {
-               if (check.empty())
-                       return m_clients.sendToAll(&pkt);
-               RemotePlayer *p = m_env->getPlayer(check.c_str());
-               if (p)
-                       m_clients.send(p->getPeerId(), 0, &pkt, true);
+       if (inv_it == m_detached_inventories.end()) {
+               pkt << false; // Remove inventory
        } else {
-               if (check.empty() || getPlayerName(peer_id) == check)
-                       Send(&pkt);
+               pkt << true; // Update inventory
+
+               // Serialization & NetworkPacket isn't a love story
+               std::ostringstream os(std::ios_base::binary);
+               inv_it->second->serialize(os);
+               pkt << os.str();
        }
+
+       if (peer_id == PEER_ID_INEXISTENT)
+               m_clients.sendToAll(&pkt);
+       else
+               Send(&pkt);
 }
 
 void Server::sendDetachedInventories(session_t peer_id)
@@ -2665,9 +2673,10 @@ void Server::DeleteClient(session_t peer_id, ClientDeletionReason reason)
                        playersao->clearParentAttachment();
 
                        // inform connected clients
+                       const std::string &player_name = player->getName();
                        NetworkPacket notice(TOCLIENT_UPDATE_PLAYER_LIST, 0, PEER_ID_INEXISTENT);
                        // (u16) 1 + std::string represents a vector serialization representation
-                       notice << (u8) PLAYER_LIST_REMOVE  << (u16) 1 << std::string(playersao->getPlayer()->getName());
+                       notice << (u8) PLAYER_LIST_REMOVE  << (u16) 1 << player_name;
                        m_clients.sendToAll(&notice);
                        // run scripts
                        m_script->on_leaveplayer(playersao, reason == CDR_TIMEOUT);
@@ -3265,6 +3274,30 @@ Inventory* Server::createDetachedInventory(const std::string &name, const std::s
        return inv;
 }
 
+bool Server::removeDetachedInventory(const std::string &name)
+{
+       const auto &inv_it = m_detached_inventories.find(name);
+       if (inv_it == m_detached_inventories.end())
+               return false;
+
+       delete inv_it->second;
+       m_detached_inventories.erase(inv_it);
+
+       const auto &player_it = m_detached_inventories_player.find(name);
+       if (player_it != m_detached_inventories_player.end()) {
+               RemotePlayer *player = m_env->getPlayer(player_it->second.c_str());
+
+               if (player && player->getPeerId() != PEER_ID_INEXISTENT)
+                       sendDetachedInventory(name, player->getPeerId());
+
+               m_detached_inventories_player.erase(player_it);
+       } else {
+               // Notify all players about the change
+               sendDetachedInventory(name, PEER_ID_INEXISTENT);
+       }
+       return true;
+}
+
 // actions: time-reversed list
 // Return value: success/failure
 bool Server::rollbackRevertActions(const std::list<RollbackAction> &actions,
index c2adbbc07fd265983877ee6069abc6e8e1c7b5a8..9643fe45630baee6d2d9505ff189c2d09cbaa7f7 100644 (file)
@@ -248,7 +248,9 @@ public:
        void deleteParticleSpawner(const std::string &playername, u32 id);
 
        // Creates or resets inventory
-       Inventory* createDetachedInventory(const std::string &name, const std::string &player="");
+       Inventory *createDetachedInventory(const std::string &name,
+                       const std::string &player = "");
+       bool removeDetachedInventory(const std::string &name);
 
        // Envlock and conlock should be locked when using scriptapi
        ServerScripting *getScriptIface(){ return m_script; }