From e9c9b66ae92f4b95061d2b93e5db182d0c80b526 Mon Sep 17 00:00:00 2001
From: ShadowNinja <shadowninja@minetest.net>
Date: Tue, 2 Sep 2014 12:53:20 -0400
Subject: [PATCH] Make players check inventory modification properly

---
 src/environment.cpp |  1 +
 src/inventory.cpp   |  7 +++++++
 src/inventory.h     | 14 +++++++++++++-
 src/player.cpp      |  8 ++++----
 src/player.h        | 11 +++++++++--
 src/server.cpp      |  7 +++++--
 6 files changed, 39 insertions(+), 9 deletions(-)

diff --git a/src/environment.cpp b/src/environment.cpp
index 4106ecdf5..8977ee673 100644
--- a/src/environment.cpp
+++ b/src/environment.cpp
@@ -478,6 +478,7 @@ Player *ServerEnvironment::loadPlayer(const std::string &playername)
 	if (newplayer) {
 		addPlayer(player);
 	}
+	player->setModified(false);
 	return player;
 }
 
diff --git a/src/inventory.cpp b/src/inventory.cpp
index 4766524dd..cecef01a0 100644
--- a/src/inventory.cpp
+++ b/src/inventory.cpp
@@ -831,6 +831,7 @@ Inventory::~Inventory()
 
 void Inventory::clear()
 {
+	m_dirty = true;
 	for(u32 i=0; i<m_lists.size(); i++)
 	{
 		delete m_lists[i];
@@ -840,6 +841,7 @@ void Inventory::clear()
 
 void Inventory::clearContents()
 {
+	m_dirty = true;
 	for(u32 i=0; i<m_lists.size(); i++)
 	{
 		InventoryList *list = m_lists[i];
@@ -852,12 +854,14 @@ void Inventory::clearContents()
 
 Inventory::Inventory(IItemDefManager *itemdef)
 {
+	m_dirty = false;
 	m_itemdef = itemdef;
 }
 
 Inventory::Inventory(const Inventory &other)
 {
 	*this = other;
+	m_dirty = false;
 }
 
 Inventory & Inventory::operator = (const Inventory &other)
@@ -865,6 +869,7 @@ Inventory & Inventory::operator = (const Inventory &other)
 	// Gracefully handle self assignment
 	if(this != &other)
 	{
+		m_dirty = true;
 		clear();
 		m_itemdef = other.m_itemdef;
 		for(u32 i=0; i<other.m_lists.size(); i++)
@@ -945,6 +950,7 @@ void Inventory::deSerialize(std::istream &is)
 
 InventoryList * Inventory::addList(const std::string &name, u32 size)
 {
+	m_dirty = true;
 	s32 i = getListIndex(name);
 	if(i != -1)
 	{
@@ -990,6 +996,7 @@ bool Inventory::deleteList(const std::string &name)
 	s32 i = getListIndex(name);
 	if(i == -1)
 		return false;
+	m_dirty = true;
 	delete m_lists[i];
 	m_lists.erase(m_lists.begin() + i);
 	return true;
diff --git a/src/inventory.h b/src/inventory.h
index 52b776db3..d21a5deda 100644
--- a/src/inventory.h
+++ b/src/inventory.h
@@ -279,18 +279,30 @@ class Inventory
 	// A shorthand for adding items. Returns leftover item (possibly empty).
 	ItemStack addItem(const std::string &listname, const ItemStack &newitem)
 	{
+		m_dirty = true;
 		InventoryList *list = getList(listname);
 		if(list == NULL)
 			return newitem;
 		return list->addItem(newitem);
 	}
-	
+
+	bool checkModified() const
+	{
+		return m_dirty;
+	}
+
+	void setModified(const bool x)
+	{
+		m_dirty = x;
+	}
+
 private:
 	// -1 if not found
 	const s32 getListIndex(const std::string &name) const;
 
 	std::vector<InventoryList*> m_lists;
 	IItemDefManager *m_itemdef;
+	bool m_dirty;
 };
 
 #endif
diff --git a/src/player.cpp b/src/player.cpp
index a8f95bb99..13866e5f5 100644
--- a/src/player.cpp
+++ b/src/player.cpp
@@ -64,6 +64,7 @@ Player::Player(IGameDef *gamedef, const char *name):
 	craft->setWidth(3);
 	inventory.addList("craftpreview", 1);
 	inventory.addList("craftresult", 1);
+	inventory.setModified(false);
 
 	// Can be redefined via Lua
 	inventory_formspec = "size[8,7.5]"
@@ -203,6 +204,7 @@ void Player::deSerialize(std::istream &is, std::string playername)
 				playername + " not found!");
 	}
 
+	m_dirty = true;
 	//args.getS32("version"); // Version field value not used
 	std::string name = args.get("name");
 	strlcpy(m_name, name.c_str(), PLAYERNAME_SIZE);
@@ -235,8 +237,6 @@ void Player::deSerialize(std::istream &is, std::string playername)
 			inventory.getList("craftresult")->changeItem(0, ItemStack());
 		}
 	}
-
-	m_dirty = false;
 }
 
 u32 Player::addHud(HudElement *toadd)
@@ -299,7 +299,7 @@ void RemotePlayer::save(std::string savedir)
 			if (!fs::safeWriteToFile(path, ss.str())) {
 				infostream << "Failed to write " << path << std::endl;
 			}
-			m_dirty = false;
+			setModified(false);
 			return;
 		}
 		// Open file and deserialize
@@ -317,7 +317,7 @@ void RemotePlayer::save(std::string savedir)
 			if (!fs::safeWriteToFile(path, ss.str())) {
 				infostream << "Failed to write " << path << std::endl;
 			}
-			m_dirty = false;
+			setModified(false);
 			return;
 		}
 		path = savedir + m_name + itos(i);
diff --git a/src/player.h b/src/player.h
index aa38996a5..a5cc7123f 100644
--- a/src/player.h
+++ b/src/player.h
@@ -226,9 +226,16 @@ class Player
 	void serialize(std::ostream &os);
 	void deSerialize(std::istream &is, std::string playername);
 
-	bool checkModified()
+	bool checkModified() const
 	{
-		return m_dirty;
+		return m_dirty || inventory.checkModified();
+	}
+
+	void setModified(const bool x)
+	{
+		m_dirty = x;
+		if (x == false)
+			inventory.setModified(x);
 	}
 
 	bool touching_ground;
diff --git a/src/server.cpp b/src/server.cpp
index 4f4763ea4..6afe600ed 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -5039,13 +5039,16 @@ PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id)
 	if (!player) {
 		newplayer = true;
 		player = new RemotePlayer(this, name);
-		/* Set player position */
+		// Set player position
 		infostream<<"Server: Finding spawn place for player \""
 				<<name<<"\""<<std::endl;
 		v3f pos = findSpawnPos(m_env->getServerMap());
 		player->setPosition(pos);
 
-		/* Add player to environment */
+		// Make sure the player is saved
+		player->setModified(true);
+
+		// Add player to environment
 		m_env->addPlayer(player);
 	}
 
-- 
GitLab