aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--builtin/game/detached_inventory.lua4
-rw-r--r--doc/lua_api.txt2
-rw-r--r--src/network/clientpackethandler.cpp29
-rw-r--r--src/network/networkprotocol.h8
-rw-r--r--src/script/lua_api/l_inventory.cpp10
-rw-r--r--src/script/lua_api/l_inventory.h2
-rw-r--r--src/server.cpp75
-rw-r--r--src/server.h4
8 files changed, 100 insertions, 34 deletions
diff --git a/builtin/game/detached_inventory.lua b/builtin/game/detached_inventory.lua
index 420e89ff2..2e27168a1 100644
--- a/builtin/game/detached_inventory.lua
+++ b/builtin/game/detached_inventory.lua
@@ -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
diff --git a/doc/lua_api.txt b/doc/lua_api.txt
index e144a2c8f..19d6482ae 100644
--- a/doc/lua_api.txt
+++ b/doc/lua_api.txt
@@ -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`
diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp
index cbd0d6a57..5a62fec3d 100644
--- a/src/network/clientpackethandler.cpp
+++ b/src/network/clientpackethandler.cpp
@@ -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);
}
diff --git a/src/network/networkprotocol.h b/src/network/networkprotocol.h
index 4e896602b..855afc638 100644
--- a/src/network/networkprotocol.h
+++ b/src/network/networkprotocol.h
@@ -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
diff --git a/src/script/lua_api/l_inventory.cpp b/src/script/lua_api/l_inventory.cpp
index 04fa3a196..6e7afa4a4 100644
--- a/src/script/lua_api/l_inventory.cpp
+++ b/src/script/lua_api/l_inventory.cpp
@@ -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);
}
diff --git a/src/script/lua_api/l_inventory.h b/src/script/lua_api/l_inventory.h
index 2b7910ac3..94f670c9d 100644
--- a/src/script/lua_api/l_inventory.h
+++ b/src/script/lua_api/l_inventory.h
@@ -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:
diff --git a/src/server.cpp b/src/server.cpp
index 41248c869..678ee387b 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -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,
diff --git a/src/server.h b/src/server.h
index c2adbbc07..9643fe456 100644
--- a/src/server.h
+++ b/src/server.h
@@ -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; }