void ExportInventory(IMyTerminalBlock block, bool skipIngots = false, bool skipComponents = false, bool skipOres = false, bool skipTools = false)
        {
            IMyInventory inv;

            if (block.InventoryCount == 2)
            {
                if (block is IMyAssembler && (block as IMyAssembler).Mode == MyAssemblerMode.Disassembly)
                {
                    inv = block.GetInventory(0);
                }
                else
                {
                    inv = block.GetInventory(1);
                }
            }
            else
            {
                inv = block.GetInventory(0);
            }

            //Abort if inventory is missing
            if (inv == null)
            {
                BlocksMissingInventory.Add(block.CustomName);
                return;
            }

            var items = new List <MyInventoryItem>();

            inv.GetItems(items);
            foreach (var item in items)
            {
                var info = item.Type.GetItemInfo();

                if (info.IsIngot)
                {
                    //Is ingot
                    if (skipIngots)
                    {
                        continue;
                    }
                    if (!ExportItem(item, inv, Ingots))
                    {
                        Errors |= RunningError.IngotExportFailed;
                    }
                    else
                    {
                        Echo("Moved ingot " + item.Type.SubtypeId);
                    }
                }
                else if (info.IsOre)
                {
                    //Is ore
                    if (skipOres)
                    {
                        continue;
                    }
                    if (!ExportItem(item, inv, Ores))
                    {
                        Errors |= RunningError.OreExportFailed;
                    }
                    else
                    {
                        Echo("Moved ore " + item.Type.SubtypeId);
                    }
                }
                else
                {
                    //if (info.MaxStackAmount == 1) Bugged in the current version. (1.190.101)
                    if (item.Type.TypeId.EndsWith("Object"))                    //Workaround
                    {
                        //Is Tool/misc
                        if (skipTools)
                        {
                            continue;
                        }
                        if (!ExportItem(item, inv, Tools))
                        {
                            Errors |= RunningError.ToolExportFailed;
                        }
                        else
                        {
                            Echo("Moved tool " + item.Type.SubtypeId);
                        }
                    }
                    else
                    {
                        //Is component
                        if (skipComponents)
                        {
                            continue;
                        }
                        if (!ExportItem(item, inv, Components))
                        {
                            Errors |= RunningError.ComponentExportFailed;
                        }
                        else
                        {
                            Echo("Moved comp " + item.Type.SubtypeId);
                        }
                    }
                }
            }
        }
        private IEnumerator <bool> Run()
        {
            while (true)
            {
                Errors = 0;
                BlocksMissingInventory = new HashSet <string>();

                //Step 0: Export to other grids

                foreach (var item in ExternalExporter)
                {
                    ExternalExport(item.connector, item.exportFrom);
                    yield return(true);
                }

                //Step 1: Export unwanted.

                foreach (var block in Ingots)
                {
                    ExportInventory(block, skipIngots: true);
                    yield return(true);
                }

                foreach (var block in Ores)
                {
                    ExportInventory(block, skipOres: true);
                    yield return(true);
                }

                foreach (var block in Components)
                {
                    ExportInventory(block, skipComponents: true);
                    yield return(true);
                }

                foreach (var block in Tools)
                {
                    ExportInventory(block, skipTools: true);
                    yield return(true);
                }

                foreach (var block in Empty)
                {
                    ExportInventory(block);
                    yield return(true);
                }


                //Step 2. Check what's in the inventory

                TypeFillData fill = new TypeFillData();
                Dictionary <MyDefinitionId, VRage.MyFixedPoint> data = new Dictionary <MyDefinitionId, VRage.MyFixedPoint>();

                foreach (var block in Ingots)
                {
                    fill.Ingots += GetFillLevel(block);
                    yield return(true);
                }

                foreach (var block in Ores)
                {
                    fill.Ores += GetFillLevel(block);
                    yield return(true);
                }

                foreach (var block in Components)
                {
                    if (Assemblers != null)
                    {
                        Assemblers.CalculateAssemblableCount(block, data);
                    }
                    fill.Components += GetFillLevel(block);
                    yield return(true);
                }

                foreach (var block in Tools)
                {
                    fill.Tools += GetFillLevel(block);
                    yield return(true);
                }

                foreach (var block in Empty)
                {
                    fill.Empty += GetFillLevel(block);
                    yield return(true);
                }

                fill.Ingots.Z     = fill.Ingots.X / fill.Ingots.Y * 100;         //Percent = Amount / Total
                fill.Components.Z = fill.Components.X / fill.Components.Y * 100; //Percent = Amount / Total
                fill.Ores.Z       = fill.Ores.X / fill.Ores.Y * 100;             //Percent = Amount / Total
                fill.Tools.Z      = fill.Tools.X / fill.Tools.Y * 100;           //Percent = Amount / Total


                //Step 3. Tell assemblers to assemble or dissasemmble as needed.

                if (Assemblers != null)
                {
                    Assemblers.Update(data);
                }


                ErrorsShow = Errors;
                BlocksMissingInventoryShow = BlocksMissingInventory.ToList();
                FillLevel = fill;
                yield return(true);
            }
        }