protected InventoryManagerComponent()
        {
            Listen(OnStart, () =>
            {
                _inventoryComponent = GameObject.GetComponent <InventoryComponent>();

                _lock = new object();

                foreach (var value in Enum.GetValues(typeof(InventoryType)))
                {
                    var id = (InventoryType)value;

                    Logger.Information($"[{id}]");

                    _inventories.Add(id, new Inventory(id, this));
                }
            });

            Listen(OnDestroyed, () =>
            {
                OnLotAdded.Clear();

                OnLotRemoved.Clear();

                foreach (var item in _inventories.Values.SelectMany(inventory => inventory.Items))
                {
                    Destroy(item);
                }
            });
        }
        public async Task AddItemAsync(int lot, uint count, InventoryType inventoryType, LegoDataDictionary extraInfo = default)
        {
            var itemCount = count;

            Detach(() =>
            {
                OnLotAdded.Invoke(lot, itemCount);
            });

            var inventory = _inventories[inventoryType];

            // The math here cannot be executed in parallel

            await using var cdClient = new CdClientContext();

            var componentId = cdClient.ComponentsRegistryTable.FirstOrDefault(
                r => r.Id == lot && r.Componenttype == (int)ComponentId.ItemComponent
                );

            if (componentId == default)
            {
                Logger.Error($"{lot} does not have a Item component");
                return;
            }

            var component = cdClient.ItemComponentTable.FirstOrDefault(
                i => i.Id == componentId.Componentid
                );

            if (component == default)
            {
                Logger.Error(
                    $"{lot} has a corrupted component registry. There is no Item component of Id: {componentId.Componentid}"
                    );
                return;
            }

            As <Player>().SendChatMessage($"Calculating for {lot} x {count} [{inventoryType}]", PlayerChatChannel.Normal);

            var stackSize = component.StackSize ?? 1;

            // Bricks and alike does not have a stack limit.
            if (stackSize == default)
            {
                stackSize = int.MaxValue;
            }

            //
            // Update quest tasks
            //

            var questInventory = GameObject.GetComponent <MissionInventoryComponent>();

            for (var i = 0; i < count; i++)
            {
                await questInventory.ObtainItemAsync(lot);
            }

            //
            // Fill stacks
            //

            lock (_lock)
            {
                foreach (var item in inventory.Items.Where(i => i.Lot == lot))
                {
                    if (item.Count == stackSize)
                    {
                        continue;
                    }

                    var toAdd = (uint)Min(stackSize, (int)count, (int)(stackSize - item.Count));

                    item.Count += toAdd;

                    count -= toAdd;

                    if (count <= 0)
                    {
                        return;
                    }
                }

                //
                // Create new stacks
                //

                var toCreate = count;

                while (toCreate != default)
                {
                    var toAdd = (uint)Min(stackSize, (int)toCreate);

                    var item = Item.Instantiate(lot, inventory, toAdd, extraInfo);

                    Start(item);

                    toCreate -= toAdd;
                }
            }
        }