diff --git a/src/content_nodemeta.cpp b/src/content_nodemeta.cpp
index 433e6d04b23e372138eaee5f33d945fd295d00b9..7c0e817f8576a10606d883f28672d7a103bb7198 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 1ee63819dc344137240f0e2fa0816dcbe780e45f..62aedb536aee407b4309706c8b4b8c1b2c36c3aa 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 9c2027a5303e874d23a92d88f69c6cb2301b5012..b19a365c8ee1b71266835eaca6d0dab3bc7a5d1d 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 a8eb68c55a95cc5d1fb9d1dd4f1424404d9cc32c..daa1e5d865eec0e269a79f9ecf6e653d1ea76dc9 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;