private void ProductsRequest(Packet packet)
        {
            if (packet.GetString() != "GetProductList" || !packet.GetBool()) // Is valid
                return;

            var currentPostId = packet.GetInt();
            var post = Erinn.Posts.FirstOrDefault(p => p.Id == currentPostId);

            if (post == null)
                return;

            packet.GetInt(); // Unk
            packet.GetInt(); // Unk

            var itemCount = packet.GetInt();
            for (var i = 0; i < itemCount; i++) // List of item ids (duplicated later in the packet)
                packet.GetInt();

            itemCount = packet.GetInt();
            for (var i = 0; i < itemCount; i++)
            {
                var itemId = packet.GetInt();

                var item = post.Items.FirstOrDefault(a => a.Id == itemId);

                var normalizedCost = packet.GetInt();
                var stock = packet.GetInt();
                packet.GetBool(); // Limited time

                if (item != null)
                {
                    item.Stock = stock;
                    item.Price = (int)Math.Round(normalizedCost * post.MerchantLevel.Discount, MidpointRounding.AwayFromZero);
                }

                var townCount = packet.GetInt();
                for (var j = 0; j < townCount; j++)
                {
                    var destId = packet.GetInt();
                    packet.GetInt(); // Stock at destination
                    var normalizedSellPrice = packet.GetInt();

                    var destPost = Erinn.Posts.FirstOrDefault(p => p.Id == destId);

                    if (destPost == null || item == null)
                        continue;

                    if (!post.Weights.ContainsKey(destPost.Id))
                        continue;

                    var weight = post.Weights[destPost.Id];

                    var profit = item.Profits.FirstOrDefault(p => p.Destination == destPost);

                    if (profit != null)
                    {
                        var sellPrice = (int)Math.Round(normalizedSellPrice * weight * item.MultiFactor + item.AddFactor,
                            MidpointRounding.AwayFromZero);

                        profit.Amount = sellPrice - item.Price;
                    }
                }
            }

            PostSelect.SelectedItem = post;
            //CalculateTrades();
        }
        private void InfoUpdate(Packet packet)
        {
            Erinn.Ducats = packet.GetLong();
            var transportFlags = packet.GetLong(); // Transport type flags (Bitfield)
            packet.GetInt(); // Unknown

            var townCount = packet.GetShort();

            for (var i = 0; i < townCount; i++)
            {
                var townId = packet.GetInt();
                var tradingExp = packet.GetInt();

                var town = Erinn.Posts.FirstOrDefault(t => t.Id == townId);

                if (town != null)
                    town.MerchantLevel = GetMerchantLevel(tradingExp);
            }

            if (Properties.Settings.Default.SniffTransports)
            {
                foreach (var transport in Erinn.Transports)
                {
                    transport.Enabled = (transportFlags & 1 << transport.Id) != 0;
                }
            }
        }