From fae6242d4ef6ca34d131054484acf5efc2fcba70 Mon Sep 17 00:00:00 2001
From: SmallJoker <mk939@ymail.com>
Date: Sun, 25 Aug 2019 10:55:27 +0200
Subject: Send cumulated inventory changes only each step (#8856)

Applies to player and detached inventories
---
 src/inventorymanager.cpp            |  6 +++---
 src/network/serverpackethandler.cpp | 15 ++++++---------
 src/server.cpp                      | 23 ++++++++++-------------
 src/server.h                        |  5 +++--
 src/serverenvironment.cpp           | 13 +++++++++++++
 5 files changed, 35 insertions(+), 27 deletions(-)

diff --git a/src/inventorymanager.cpp b/src/inventorymanager.cpp
index 24d1fa6ff..02cb9e3a4 100644
--- a/src/inventorymanager.cpp
+++ b/src/inventorymanager.cpp
@@ -524,9 +524,9 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame
 		}
 	}
 
-	mgr->setInventoryModified(from_inv, false);
+	mgr->setInventoryModified(from_inv);
 	if (inv_from != inv_to)
-		mgr->setInventoryModified(to_inv, false);
+		mgr->setInventoryModified(to_inv);
 }
 
 void IMoveAction::clientApply(InventoryManager *mgr, IGameDef *gamedef)
@@ -671,7 +671,7 @@ void IDropAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame
 			if (item2.count != actually_dropped_count)
 				errorstream<<"Could not take dropped count of items"<<std::endl;
 
-			mgr->setInventoryModified(from_inv, false);
+			mgr->setInventoryModified(from_inv);
 		}
 	}
 
diff --git a/src/network/serverpackethandler.cpp b/src/network/serverpackethandler.cpp
index 1965d87aa..6cb3b3520 100644
--- a/src/network/serverpackethandler.cpp
+++ b/src/network/serverpackethandler.cpp
@@ -313,7 +313,7 @@ void Server::handleCommand_Init2(NetworkPacket* pkt)
 	sendMediaAnnouncement(pkt->getPeerId(), lang);
 
 	// Send detached inventories
-	sendDetachedInventories(pkt->getPeerId());
+	sendDetachedInventories(pkt->getPeerId(), false);
 
 	// Send time of day
 	u16 time = m_env->getTimeOfDay();
@@ -608,10 +608,9 @@ void Server::handleCommand_InventoryAction(NetworkPacket* pkt)
 		ma->from_inv.applyCurrentPlayer(player->getName());
 		ma->to_inv.applyCurrentPlayer(player->getName());
 
-		setInventoryModified(ma->from_inv, false);
-		if (ma->from_inv != ma->to_inv) {
-			setInventoryModified(ma->to_inv, false);
-		}
+		setInventoryModified(ma->from_inv);
+		if (ma->from_inv != ma->to_inv)
+			setInventoryModified(ma->to_inv);
 
 		bool from_inv_is_current_player =
 			(ma->from_inv.type == InventoryLocation::PLAYER) &&
@@ -676,7 +675,7 @@ void Server::handleCommand_InventoryAction(NetworkPacket* pkt)
 
 		da->from_inv.applyCurrentPlayer(player->getName());
 
-		setInventoryModified(da->from_inv, false);
+		setInventoryModified(da->from_inv);
 
 		/*
 			Disable dropping items out of craftpreview
@@ -712,7 +711,7 @@ void Server::handleCommand_InventoryAction(NetworkPacket* pkt)
 
 		ca->craft_inv.applyCurrentPlayer(player->getName());
 
-		setInventoryModified(ca->craft_inv, false);
+		setInventoryModified(ca->craft_inv);
 
 		//bool craft_inv_is_current_player =
 		//	(ca->craft_inv.type == InventoryLocation::PLAYER) &&
@@ -731,8 +730,6 @@ void Server::handleCommand_InventoryAction(NetworkPacket* pkt)
 	a->apply(this, playersao, this);
 	// Eat the action
 	delete a;
-
-	SendInventory(playersao, true);
 }
 
 void Server::handleCommand_ChatMessage(NetworkPacket* pkt)
diff --git a/src/server.cpp b/src/server.cpp
index 59bc12581..f6bf491be 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -1234,7 +1234,7 @@ Inventory* Server::getInventory(const InventoryLocation &loc)
 	return NULL;
 }
 
-void Server::setInventoryModified(const InventoryLocation &loc, bool playerSend)
+void Server::setInventoryModified(const InventoryLocation &loc)
 {
 	switch(loc.type){
 	case InventoryLocation::UNDEFINED:
@@ -1248,15 +1248,7 @@ void Server::setInventoryModified(const InventoryLocation &loc, bool playerSend)
 			return;
 
 		player->setModified(true);
-
-		if (!playerSend)
-			return;
-
-		PlayerSAO *playersao = player->getPlayerSAO();
-		if(!playersao)
-			return;
-
-		SendInventory(playersao, true);
+		// Updates are sent in ServerEnvironment::step()
 	}
 		break;
 	case InventoryLocation::NODEMETA:
@@ -1269,7 +1261,7 @@ void Server::setInventoryModified(const InventoryLocation &loc, bool playerSend)
 		break;
 	case InventoryLocation::DETACHED:
 	{
-		sendDetachedInventory(loc.name,PEER_ID_INEXISTENT);
+		// Updates are sent in ServerEnvironment::step()
 	}
 		break;
 	default:
@@ -2617,11 +2609,16 @@ void Server::sendDetachedInventory(const std::string &name, session_t peer_id)
 		Send(&pkt);
 }
 
-void Server::sendDetachedInventories(session_t peer_id)
+void Server::sendDetachedInventories(session_t peer_id, bool incremental)
 {
 	for (const auto &detached_inventory : m_detached_inventories) {
 		const std::string &name = detached_inventory.first;
-		//Inventory *inv = i->second;
+		if (incremental) {
+			Inventory *inv = detached_inventory.second;
+			if (!inv || !inv->checkModified())
+				continue;
+		}
+
 		sendDetachedInventory(name, peer_id);
 	}
 }
diff --git a/src/server.h b/src/server.h
index d1dcafac3..86f82b6d7 100644
--- a/src/server.h
+++ b/src/server.h
@@ -195,7 +195,7 @@ public:
 		Shall be called with the environment and the connection locked.
 	*/
 	Inventory* getInventory(const InventoryLocation &loc);
-	void setInventoryModified(const InventoryLocation &loc, bool playerSend = true);
+	void setInventoryModified(const InventoryLocation &loc);
 
 	// Connection must be locked when called
 	std::wstring getStatusString();
@@ -337,6 +337,8 @@ public:
 	void SendMovePlayer(session_t peer_id);
 	void SendPlayerSpeed(session_t peer_id, const v3f &added_vel);
 
+	void sendDetachedInventories(session_t peer_id, bool incremental);
+
 	virtual bool registerModStorage(ModMetadata *storage);
 	virtual void unregisterModStorage(const std::string &name);
 
@@ -443,7 +445,6 @@ private:
 			const std::vector<std::string> &tosend);
 
 	void sendDetachedInventory(const std::string &name, session_t peer_id);
-	void sendDetachedInventories(session_t peer_id);
 
 	// Adds a ParticleSpawner on peer with peer_id (PEER_ID_INEXISTENT == all)
 	void SendAddParticleSpawner(session_t peer_id, u16 protocol_version,
diff --git a/src/serverenvironment.cpp b/src/serverenvironment.cpp
index 1af3cf6d7..333d32ff5 100644
--- a/src/serverenvironment.cpp
+++ b/src/serverenvironment.cpp
@@ -1454,6 +1454,19 @@ void ServerEnvironment::step(float dtime)
 				++i;
 		}
 	}
+
+	// Send outdated player inventories
+	for (RemotePlayer *player : m_players) {
+		if (player->getPeerId() == PEER_ID_INEXISTENT)
+			continue;
+
+		PlayerSAO *sao = player->getPlayerSAO();
+		if (sao && player->inventory.checkModified())
+			m_server->SendInventory(sao, true);
+	}
+
+	// Send outdated detached inventories
+	m_server->sendDetachedInventories(PEER_ID_INEXISTENT, true);
 }
 
 u32 ServerEnvironment::addParticleSpawner(float exptime)
-- 
cgit v1.2.3