Allow restricting detached inventories to one player
authorsfan5 <sfan5@live.de>
Sat, 26 Nov 2016 16:35:25 +0000 (17:35 +0100)
committersfan5 <sfan5@live.de>
Mon, 28 Nov 2016 12:41:19 +0000 (13:41 +0100)
This combats the problem of sending the hundreds of
"creative" / "armor" or whatever detached invs that
exist on popular servers to each and every player
on join or on change of said invs.

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

index b5d106b042ccfb13e963f0ba13aef45024bb9eab..420e89ff28dd513244d9b9f3a8dcdec3de72c7c4 100644 (file)
@@ -2,7 +2,7 @@
 
 core.detached_inventories = {}
 
-function core.create_detached_inventory(name, callbacks)
+function core.create_detached_inventory(name, callbacks, player_name)
        local stuff = {}
        stuff.name = name
        if callbacks then
@@ -15,6 +15,6 @@ function core.create_detached_inventory(name, callbacks)
        end
        stuff.mod_origin = core.get_current_modname() or "??"
        core.detached_inventories[name] = stuff
-       return core.create_detached_inventory_raw(name)
+       return core.create_detached_inventory_raw(name, player_name)
 end
 
index 9da0fb4f98549e5cd6f5684d60590a3f30fe026a..eb47270f48c41776ce864c22125530886d4d3e68 100644 (file)
@@ -2310,8 +2310,11 @@ and `minetest.auth_reload` call the authetification handler.
     * `{type="player", name="celeron55"}`
     * `{type="node", pos={x=, y=, z=}}`
     * `{type="detached", name="creative"}`
-* `minetest.create_detached_inventory(name, callbacks)`: returns an `InvRef`
+* `minetest.create_detached_inventory(name, callbacks, [player_name])`: returns an `InvRef`
     * callbacks: See "Detached inventory callbacks"
+    * player_name: Make detached inventory available to one player exclusively,
+      by default they will be sent to every player (even if not used).
+      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.do_item_eat(hp_change, replace_with_item, itemstack, user, pointed_thing)`:
    returns left over ItemStack
index 110e68d23c1b7abeb675b17eb9e79717668c377a..38eade6094b9dffb03f139213ad1e8fb7e23a268 100644 (file)
@@ -520,16 +520,17 @@ int ModApiInventory::l_get_inventory(lua_State *L)
        }
 }
 
-// create_detached_inventory_raw(name)
+// create_detached_inventory_raw(name, [player_name])
 int ModApiInventory::l_create_detached_inventory_raw(lua_State *L)
 {
        NO_MAP_LOCK_REQUIRED;
        const char *name = luaL_checkstring(L, 1);
-       if(getServer(L)->createDetachedInventory(name) != NULL){
+       const char *player = lua_isstring(L, 2) ? lua_tostring(L, 2) : "";
+       if (getServer(L)->createDetachedInventory(name, player) != NULL) {
                InventoryLocation loc;
                loc.setDetached(name);
                InvRef::create(L, loc);
-       }else{
+       } else {
                lua_pushnil(L);
        }
        return 1;
index fae375425888ea87e45644f1ce877f52f96a4cdb..fe67ac96e87f49c7d3b391eaaecac0f025cea9eb 100644 (file)
@@ -2487,11 +2487,16 @@ void Server::sendDetachedInventory(const std::string &name, u16 peer_id)
        NetworkPacket pkt(TOCLIENT_DETACHED_INVENTORY, 0, peer_id);
        pkt.putRawString(s.c_str(), s.size());
 
-       if (peer_id != PEER_ID_INEXISTENT) {
-               Send(&pkt);
-       }
-       else {
-               m_clients.sendToAll(0, &pkt, true);
+       const std::string &check = m_detached_inventories_player[name];
+       if (peer_id == PEER_ID_INEXISTENT) {
+               if (check == "")
+                       return m_clients.sendToAll(0, &pkt, true);
+               RemotePlayer *p = m_env->getPlayer(check.c_str());
+               if (p)
+                       m_clients.send(p->peer_id, 0, &pkt, true);
+       } else {
+               if (check == "" || getPlayerName(peer_id) == check)
+                       Send(&pkt);
        }
 }
 
@@ -3224,7 +3229,7 @@ void Server::deleteParticleSpawner(const std::string &playername, u32 id)
        SendDeleteParticleSpawner(peer_id, id);
 }
 
-Inventory* Server::createDetachedInventory(const std::string &name)
+Inventory* Server::createDetachedInventory(const std::string &name, const std::string &player)
 {
        if(m_detached_inventories.count(name) > 0){
                infostream<<"Server clearing detached inventory \""<<name<<"\""<<std::endl;
@@ -3235,6 +3240,7 @@ Inventory* Server::createDetachedInventory(const std::string &name)
        Inventory *inv = new Inventory(m_itemdef);
        sanity_check(inv);
        m_detached_inventories[name] = inv;
+       m_detached_inventories_player[name] = player;
        //TODO find a better way to do this
        sendDetachedInventory(name,PEER_ID_INEXISTENT);
        return inv;
index 9e844e36c3531ccf641dbefef209c3bfc0d76c7c..cc2bcef25f916c708369eba63b09e75a52c746ef 100644 (file)
@@ -270,7 +270,7 @@ public:
        void deleteParticleSpawner(const std::string &playername, u32 id);
 
        // Creates or resets inventory
-       Inventory* createDetachedInventory(const std::string &name);
+       Inventory* createDetachedInventory(const std::string &name, const std::string &player="");
 
        // Envlock and conlock should be locked when using scriptapi
        GameScripting *getScriptIface(){ return m_script; }
@@ -647,6 +647,8 @@ private:
        */
        // key = name
        std::map<std::string, Inventory*> m_detached_inventories;
+       // value = "" (visible to all players) or player name
+       std::map<std::string, std::string> m_detached_inventories_player;
 
        DISABLE_CLASS_COPY(Server);
 };