diff --git a/builtin/game/detached_inventory.lua b/builtin/game/detached_inventory.lua
index b5d106b042ccfb13e963f0ba13aef45024bb9eab..420e89ff28dd513244d9b9f3a8dcdec3de72c7c4 100644
--- a/builtin/game/detached_inventory.lua
+++ b/builtin/game/detached_inventory.lua
@@ -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
 
diff --git a/doc/lua_api.txt b/doc/lua_api.txt
index 9da0fb4f98549e5cd6f5684d60590a3f30fe026a..eb47270f48c41776ce864c22125530886d4d3e68 100644
--- a/doc/lua_api.txt
+++ b/doc/lua_api.txt
@@ -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
diff --git a/src/script/lua_api/l_inventory.cpp b/src/script/lua_api/l_inventory.cpp
index 110e68d23c1b7abeb675b17eb9e79717668c377a..38eade6094b9dffb03f139213ad1e8fb7e23a268 100644
--- a/src/script/lua_api/l_inventory.cpp
+++ b/src/script/lua_api/l_inventory.cpp
@@ -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;
diff --git a/src/server.cpp b/src/server.cpp
index fae375425888ea87e45644f1ce877f52f96a4cdb..fe67ac96e87f49c7d3b391eaaecac0f025cea9eb 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -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;
diff --git a/src/server.h b/src/server.h
index 9e844e36c3531ccf641dbefef209c3bfc0d76c7c..cc2bcef25f916c708369eba63b09e75a52c746ef 100644
--- a/src/server.h
+++ b/src/server.h
@@ -270,7 +270,7 @@ class Server : public con::PeerHandler, public MapEventReceiver,
 	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 @@ class Server : public con::PeerHandler, public MapEventReceiver,
 	*/
 	// 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);
 };