From 134e49cc8e442e582608411832363e15f68ea6eb Mon Sep 17 00:00:00 2001
From: JacobF <queatz@gmail.com>
Date: Thu, 25 Aug 2011 19:27:50 -0400
Subject: [PATCH] Merged 2 branches because they relied on each other. This one
 contains these changes from main c55: * Adds a function to check if there is
 room for a specific item * Using that, you can now pick up rats if you have a
 full inventory and a not full rat stack * Furnace would cook only 1 item if
 that item used the last available result slot, now it will continue * Furnace
 will say it's overloaded * Furnace won't wait until the next step to start on
 the next item  - This caused small fuels to cook slower than meant to  - Also
 caused furnaces to say they were out of fuel after finishing the last fuel
 item

---
 src/content_nodemeta.cpp | 34 ++++++++++++++++++++++++++--------
 src/inventory.cpp        | 24 +++++++++++++++++++++---
 src/inventory.h          |  8 +++++++-
 src/server.cpp           |  2 +-
 4 files changed, 55 insertions(+), 13 deletions(-)

diff --git a/src/content_nodemeta.cpp b/src/content_nodemeta.cpp
index 433e6d04b..7c0e817f8 100644
--- a/src/content_nodemeta.cpp
+++ b/src/content_nodemeta.cpp
@@ -182,16 +182,24 @@ std::string FurnaceNodeMetadata::infoText()
 		assert(src_list);
 		const InventoryItem *src_item = src_list->getItem(0);
 
-		if(src_item)
+		if(src_item) {
+			InventoryList *dst_list = m_inventory->getList("dst");
+			if(!dst_list->roomForCookedItem(src_item))
+				return "Furnace is overloaded";
 			return "Furnace is out of fuel";
+		}
 		else
 			return "Furnace is inactive";
 	}
 	else
 	{
-		std::string s = "Furnace is active (";
-		s += itos(m_fuel_time/m_fuel_totaltime*100);
-		s += "%)";
+		std::string s = "Furnace is active";
+		// Do this so it doesn't always show (0%) for weak fuel
+		if(m_fuel_totaltime > 3) {
+			s += " (";
+			s += itos(m_fuel_time/m_fuel_totaltime*100);
+			s += "%)";
+		}
 		return s;
 	}
 }
@@ -221,9 +229,14 @@ bool FurnaceNodeMetadata::step(float dtime)
 		assert(src_list);
 		const InventoryItem *src_item = src_list->getItem(0);
 		
+		bool room_available = false;
+		
+		if(src_item && src_item->isCookable())
+			room_available = dst_list->roomForCookedItem(src_item);
+		
 		// Start only if there are free slots in dst, so that it can
 		// accomodate any result item
-		if(dst_list->getFreeSlots() > 0 && src_item && src_item->isCookable())
+		if(room_available)
 		{
 			m_src_totaltime = 3;
 		}
@@ -252,13 +265,18 @@ bool FurnaceNodeMetadata::step(float dtime)
 				m_src_totaltime = 0;
 			}
 			changed = true;
-			continue;
+			
+			// Fall through if the fuel item was used up this step
+			if(m_fuel_time < m_fuel_totaltime)
+				continue;
 		}
 		
 		/*
-			If there is no source item or source item is not cookable, stop loop.
+			If there is no source item or source item is not cookable,
+			or furnace became overloaded, stop loop.
 		*/
-		if(src_item == NULL || m_src_totaltime < 0.001)
+		if((m_fuel_time < m_fuel_totaltime || dst_list->roomForCookedItem(src_item) == false)
+			&& (src_item == NULL || m_src_totaltime < 0.001))
 		{
 			m_step_accumulator = 0;
 			break;
diff --git a/src/inventory.cpp b/src/inventory.cpp
index 1ee63819d..62aedb536 100644
--- a/src/inventory.cpp
+++ b/src/inventory.cpp
@@ -549,7 +549,7 @@ InventoryItem * InventoryList::addItem(u32 i, InventoryItem *newitem)
 	}
 }
 
-bool InventoryList::itemFits(u32 i, InventoryItem *newitem)
+bool InventoryList::itemFits(const u32 i, const InventoryItem *newitem)
 {
 	// If it is an empty position, it's an easy job.
 	const InventoryItem *to_item = getItem(i);
@@ -558,11 +558,11 @@ bool InventoryList::itemFits(u32 i, InventoryItem *newitem)
 		return true;
 	}
 	
-	// If not addable, return the item
+	// If not addable, fail
 	if(newitem->addableTo(to_item) == false)
 		return false;
 	
-	// If the item fits fully in the slot, add counter and delete it
+	// If the item fits fully in the slot, pass
 	if(newitem->getCount() <= to_item->freeSpace())
 	{
 		return true;
@@ -571,6 +571,24 @@ bool InventoryList::itemFits(u32 i, InventoryItem *newitem)
 	return false;
 }
 
+bool InventoryList::roomForItem(const InventoryItem *item)
+{
+	for(u32 i=0; i<m_items.size(); i++)
+		if(itemFits(i, item))
+			return true;
+	return false;
+}
+
+bool InventoryList::roomForCookedItem(const InventoryItem *item)
+{
+	const InventoryItem *cook = item->createCookResult();
+	if(!cook)
+		return false;
+	bool room = roomForItem(cook);
+	delete cook;
+	return room;
+}
+
 InventoryItem * InventoryList::takeItem(u32 i, u32 count)
 {
 	if(count == 0)
diff --git a/src/inventory.h b/src/inventory.h
index 9c2027a53..b19a365c8 100644
--- a/src/inventory.h
+++ b/src/inventory.h
@@ -490,7 +490,13 @@ class InventoryList
 	InventoryItem * addItem(u32 i, InventoryItem *newitem);
 
 	// Checks whether the item could be added to the given slot
-	bool itemFits(u32 i, InventoryItem *newitem);
+	bool itemFits(const u32 i, const InventoryItem *newitem);
+
+	// Checks whether there is room for a given item
+	bool roomForItem(const InventoryItem *item);
+
+	// Checks whether there is room for a given item aftr it has been cooked
+	bool roomForCookedItem(const InventoryItem *item);
 
 	// Takes some items from a slot.
 	// If there are not enough, takes as many as it can.
diff --git a/src/server.cpp b/src/server.cpp
index a8eb68c55..daa1e5d86 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -2446,7 +2446,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
 					if(g_settings.getBool("creative_mode") == false)
 					{
 						// Skip if inventory has no free space
-						if(ilist->getUsedSlots() == ilist->getSize())
+						if(ilist->roomForItem(item) == false)
 						{
 							dout_server<<"Player inventory has no free space"<<std::endl;
 							return;
-- 
GitLab