public void Run(ZACommons commons, EventDriver eventDriver)
    {
        if (CurrentState == STATE_INACTIVE)
        {
            return;
        }

        var ship = LIMIT_PRODUCTION_MANAGER_SAME_GRID ? commons.Blocks : commons.AllBlocks;

        var allowedSubtypes  = new HashSet <string>();
        var assemblerTargets = new Dictionary <string, AssemblerTarget>();

        var assemblers = ZACommons.GetBlocksOfType <IMyAssembler>(ship);

        for (var e = assemblers.GetEnumerator(); e.MoveNext();)
        {
            var       assembler = (IMyAssembler)e.Current;
            ItemStock target;
            if (ItemStock.TryParse(assembler.CustomName, out target))
            {
                var subtype = target.SubtypeName;

                // When we take inventory, filter to just these types
                allowedSubtypes.Add(subtype);

                AssemblerTarget assemblerTarget;
                if (!assemblerTargets.TryGetValue(subtype, out assemblerTarget))
                {
                    assemblerTarget = new AssemblerTarget(target.Amount);
                    assemblerTargets.Add(subtype, assemblerTarget);
                }

                // Remember this assembler for this subtype
                assemblerTarget.Assemblers.Add(assembler);

                // Adjust target amount, if necessary
                assemblerTarget.Amount = Math.Max(assemblerTarget.Amount, target.Amount);
            }
        }

        if (CurrentState == STATE_ACTIVE)
        {
            // Get current stocks
            var stocks = EnumerateItems(ship, allowedSubtypes);

            // Now we just enable/disable based on who's low
            for (var e = assemblerTargets.GetEnumerator(); e.MoveNext();)
            {
                var subtype = e.Current.Key;
                var target  = e.Current.Value;
                VRage.MyFixedPoint currentStock;
                if (!stocks.TryGetValue(subtype, out currentStock))
                {
                    currentStock = (VRage.MyFixedPoint) 0.0f;
                }

                // Enable or disable based on current stock
                target.EnableAssemblers((float)currentStock < target.Amount);
            }
        }
        else if (CurrentState == STATE_INACTIVATING)
        {
            // Shut down all known assemblers
            for (var e = assemblerTargets.Values.GetEnumerator(); e.MoveNext();)
            {
                e.Current.EnableAssemblers(false);
            }
            SetState(commons, STATE_INACTIVE);
        }

        eventDriver.Schedule(RunDelay, Run);
    }
    public void Run(ZACommons commons, EventDriver eventDriver)
    {
        if (CurrentState == STATE_INACTIVE) return;

        var ship = LIMIT_PRODUCTION_MANAGER_SAME_GRID ? commons.Blocks : commons.AllBlocks;

        var allowedSubtypes = new HashSet<string>();
        var assemblerTargets = new Dictionary<string, AssemblerTarget>();

        var assemblers = ZACommons.GetBlocksOfType<IMyAssembler>(ship);
        for (var e = assemblers.GetEnumerator(); e.MoveNext();)
        {
            var assembler = (IMyAssembler)e.Current;
            ItemStock target;
            if (ItemStock.TryParse(assembler.CustomName, out target))
            {
                var subtype = target.SubtypeName;

                // When we take inventory, filter to just these types
                allowedSubtypes.Add(subtype);

                AssemblerTarget assemblerTarget;
                if (!assemblerTargets.TryGetValue(subtype, out assemblerTarget))
                {
                    assemblerTarget = new AssemblerTarget(target.Amount);
                    assemblerTargets.Add(subtype, assemblerTarget);
                }

                // Remember this assembler for this subtype
                assemblerTarget.Assemblers.Add(assembler);

                // Adjust target amount, if necessary
                assemblerTarget.Amount = Math.Max(assemblerTarget.Amount, target.Amount);
            }
        }

        if (CurrentState == STATE_ACTIVE)
        {
            // Get current stocks
            var stocks = EnumerateItems(ship, allowedSubtypes);

            // Now we just enable/disable based on who's low
            for (var e = assemblerTargets.GetEnumerator(); e.MoveNext();)
            {
                var subtype = e.Current.Key;
                var target = e.Current.Value;
                VRage.MyFixedPoint currentStock;
                if (!stocks.TryGetValue(subtype, out currentStock)) currentStock = (VRage.MyFixedPoint)0.0f;

                // Enable or disable based on current stock
                target.EnableAssemblers((float)currentStock < target.Amount);
            }
        }
        else if (CurrentState == STATE_INACTIVATING)
        {
            // Shut down all known assemblers
            for (var e = assemblerTargets.Values.GetEnumerator(); e.MoveNext();)
            {
                e.Current.EnableAssemblers(false);
            }
            SetState(commons, STATE_INACTIVE);
        }

        eventDriver.Schedule(RunDelay, Run);
    }