public static void AddItemToContainer(ContainerAddItemMessage message, Client cli)
        {
            var noAppearanceUpdate = false;

            /* Container ID's:
             * 0065 Weaponpage
             * 0066 Armorpage
             * 0067 Implantpage
             * 0068 Inventory (places 64-93)
             * 0069 Bank
             * 006B Backpack
             * 006C KnuBot Trade Window
             * 006E Overflow window
             * 006F Trade Window
             * 0073 Socialpage
             * 0767 Shop Inventory
             * 0790 Playershop Inventory
             * DEAD Trade Window (incoming)
             */
            var fromContainerID = (int)message.SourceContainer.Type;
            var fromPlacement = message.SourceContainer.Instance;
            var toIdentity = message.Target;
            var toPlacement = message.TargetPlacement;

            // Where and what does need to be moved/added?
            IInventoryPage sendingPage = cli.Character.BaseInventory.Pages[fromContainerID];
            IItem itemFrom = sendingPage[fromPlacement];

            // Receiver of the item (IInstancedEntity, can be mostly all from NPC, Character or Bag, later even playfields)
            IItemContainer itemReceiver = cli.Playfield.FindByIdentity(toIdentity) as IItemContainer;
            if (itemReceiver == null)
            {
                throw new ArgumentOutOfRangeException("No Entity found: " + message.Target.Type.ToString() + ":" + message.Target.Instance);
            }

            // On which inventorypage should the item be added?
            IInventoryPage receivingPage = itemReceiver.BaseInventory.PageFromSlot(toPlacement);

            // Get standard page if toplacement cant be found (0x6F for next free slot)
            // TODO: If Entities are not the same (other player, bag etc) then always add to the standard page
            if (receivingPage == null)
            {
                receivingPage = itemReceiver.BaseInventory.Pages[itemReceiver.BaseInventory.StandardPage];
            }

            if (receivingPage == null)
            {
                throw new ArgumentOutOfRangeException("No inventorypage found.");
            }

            if (toPlacement == 0x6f)
            {
                toPlacement = receivingPage.FindFreeSlot();
            }

            // Is there already a item?
            IItem itemTo;
            try
            {
                itemTo = receivingPage[toPlacement];
            }
            catch (Exception)
            {
                itemTo = null;
            }

            // Calculating delay for equip/unequip/switch gear
            var delay = 0;

            if (itemFrom != null)
            {
                delay += itemFrom.GetAttribute(211);
            }

            if (itemTo != null)
            {
                delay += itemTo.GetAttribute(211);
            }

            if (delay == 0)
            {
                delay = 200;
            }

            int counter;

            cli.Character.DoNotDoTimers = true;
            IItemSlotHandler equipTo = receivingPage as IItemSlotHandler;
            IItemSlotHandler unequipFrom = sendingPage as IItemSlotHandler;

            if (equipTo != null)
            {
                if (itemTo != null)
                {
                    equipTo.HotSwap(sendingPage, fromPlacement, toPlacement);
                }
                else
                {
                    equipTo.Equip(sendingPage, fromPlacement, toPlacement);
                }
            }
            else
            {
                if (unequipFrom != null)
                {
                    unequipFrom.Unequip(fromPlacement, receivingPage, toPlacement);

                }
            }
            /*
            switch (fromContainerID)
            {
                case 0x68:

                    // from Inventory
                    if (toPlacement <= 30)
                    {
                        // to Weaponspage or Armorpage
                        // TODO: Send some animation
                        if (itemTo != null)
                        {
                            cli.Character.UnequipItem(itemTo, cli.Character, false, fromPlacement);

                            // send interpolated item
                            Unequip.Send(cli, itemTo, InventoryPage(toPlacement), toPlacement);

                            // client takes care of hotswap
                            cli.Character.EquipItem(itemFrom, cli.Character, false, toPlacement);
                            Equip.Send(cli, itemFrom, InventoryPage(toPlacement), toPlacement);
                        }
                        else
                        {
                            cli.Character.EquipItem(itemFrom, cli.Character, false, toPlacement);
                            Equip.Send(cli, itemFrom, InventoryPage(toPlacement), toPlacement);
                        }
                    }
                    else
                    {
                        if (toPlacement < 46)
                        {
                            if (itemTo == null)
                            {
                                cli.Character.EquipItem(itemFrom, cli.Character, false, toPlacement);
                                Equip.Send(cli, itemFrom, InventoryPage(toPlacement), toPlacement);
                            }
                        }

                        // Equiping to social page
                        if ((toPlacement >= 49) && (toPlacement <= 63))
                        {
                            if (itemTo != null)
                            {
                                cli.Character.UnequipItem(itemTo, cli.Character, true, fromPlacement);

                                // send interpolated item
                                cli.Character.EquipItem(itemFrom, cli.Character, true, toPlacement);
                            }
                            else
                            {
                                cli.Character.EquipItem(itemFrom, cli.Character, true, toPlacement);
                            }

                            // cli.Character.switchItems(cli, fromplacement, toplacement);
                        }
                    }

                    cli.Character.SwitchItems(fromPlacement, toPlacement);
                    cli.Character.CalculateSkills();
                    noAppearanceUpdate = false;
                    break;
                case 0x66:

                    // from Armorpage
                    cli.Character.UnequipItem(itemFrom, cli.Character, false, fromPlacement);

                    // send interpolated item
                    Unequip.Send(cli, itemFrom, InventoryPage(fromPlacement), fromPlacement);
                    cli.Character.SwitchItems(fromPlacement, toPlacement);
                    cli.Character.CalculateSkills();
                    noAppearanceUpdate = false;
                    break;
                case 0x65:

                    // from Weaponspage
                    cli.Character.UnequipItem(itemFrom, cli.Character, false, fromPlacement);

                    // send interpolated item
                    Unequip.Send(cli, itemFrom, InventoryPage(fromPlacement), fromPlacement);
                    cli.Character.SwitchItems(fromPlacement, toPlacement);
                    cli.Character.CalculateSkills();
                    noAppearanceUpdate = false;
                    break;
                case 0x67:

                    // from Implantpage
                    cli.Character.UnequipItem(itemFrom, cli.Character, false, fromPlacement);

                    // send interpolated item
                    Unequip.Send(cli, itemFrom, InventoryPage(fromPlacement), fromPlacement);
                    cli.Character.SwitchItems(fromPlacement, toPlacement);
                    cli.Character.CalculateSkills();
                    noAppearanceUpdate = true;
                    break;
                case 0x73:
                    cli.Character.UnequipItem(itemFrom, cli.Character, true, fromPlacement);

                    cli.Character.SwitchItems(fromPlacement, toPlacement);
                    cli.Character.CalculateSkills();
                    break;
                case 0x69:
                    cli.Character.TransferItemfromBank(fromPlacement, toPlacement);
                    toPlacement = 0x6f; // setting back to 0x6f for packet reply
                    noAppearanceUpdate = true;
                    break;
                case 0x6c:

                    // KnuBot Trade Window
                    cli.Character.TransferItemfromKnuBotTrade(fromPlacement, toPlacement);
                    break;
                default:
                    break;
            }
            }*/

            cli.Character.DoNotDoTimers = false;
            if ((equipTo!=null) || (unequipFrom!=null))
            {
                // Equipmentpages need delays
                // Delay when equipping/unequipping
                // has to be redone, jumping breaks the equiping/unequiping
                // and other messages have to be done too
                // like heartbeat timer, damage from environment and such
                Thread.Sleep(delay);
            }
            else
            {
                Thread.Sleep(200); // social has to wait for 0.2 secs too (for helmet update)
            }
            /*
            SwitchItem.Send(
                cli,
                fromContainerID,
                fromPlacement,
                new Identity { Type = toIdentity.Type, Instance = toIdentity.Instance },
                toPlacement);
             */
            cli.Character.Stats.ClearChangedFlags();
            if (!noAppearanceUpdate)
            {
                throw new NotImplementedException("TODO");
                //cli.Character.AppearanceUpdate();
            }

            itemFrom = null;
            itemTo = null;
        }
        /// <summary>
        /// </summary>
        /// <param name="message">
        /// </param>
        /// <param name="cli">
        /// </param>
        /// <exception cref="ArgumentOutOfRangeException">
        /// </exception>
        /// <exception cref="NotImplementedException">
        /// </exception>
        public static void AddItemToContainer(ContainerAddItemMessage message, ZoneClient cli)
        {
            bool noAppearanceUpdate = false;

            /* Container ID's:
             * 0065 Weaponpage
             * 0066 Armorpage
             * 0067 Implantpage
             * 0068 Inventory (places 64-93)
             * 0069 Bank
             * 006B Backpack
             * 006C KnuBot Trade Window
             * 006E Overflow window
             * 006F Trade Window
             * 0073 Socialpage
             * 0767 Shop Inventory
             * 0790 Playershop Inventory
             * DEAD Trade Window (incoming) It's bank now (when you put something into the bank)
             */
            var fromContainerID = (int)message.SourceContainer.Type;
            int fromPlacement = message.SourceContainer.Instance;
            Identity toIdentity = message.Target;
            int toPlacement = message.TargetPlacement;

            // Where and what does need to be moved/added?
            IInventoryPage sendingPage = cli.Character.BaseInventory.Pages[fromContainerID];
            IItem itemFrom = sendingPage[fromPlacement];

            // Receiver of the item (IInstancedEntity, can be mostly all from NPC, Character or Bag, later even playfields)
            // Turn 0xDEAD into C350 if instance is the same
            if (toIdentity.Type == IdentityType.IncomingTradeWindow)
            {
                toIdentity.Type = IdentityType.CanbeAffected;
            }

            IItemContainer itemReceiver = cli.Playfield.FindByIdentity(toIdentity) as IItemContainer;
            if (itemReceiver == null)
            {
                throw new ArgumentOutOfRangeException(
                    "No Entity found: " + message.Target.Type.ToString() + ":" + message.Target.Instance);
            }

            // On which inventorypage should the item be added?
            IInventoryPage receivingPage;
            if ((toPlacement == 0x6f) && (message.Target.Type == IdentityType.IncomingTradeWindow))
            {
                receivingPage = itemReceiver.BaseInventory.Pages[(int)IdentityType.Bank];
            }
            else
            {
                receivingPage = itemReceiver.BaseInventory.PageFromSlot(toPlacement);
            }

            // Get standard page if toplacement cant be found (0x6F for next free slot)
            // TODO: If Entities are not the same (other player, bag etc) then always add to the standard page
            if ((receivingPage == null) || (itemReceiver.GetType() != cli.Character.GetType()))
            {
                receivingPage = itemReceiver.BaseInventory.Pages[itemReceiver.BaseInventory.StandardPage];
            }

            if (receivingPage == null)
            {
                throw new ArgumentOutOfRangeException("No inventorypage found.");
            }

            if (toPlacement == 0x6f)
            {
                toPlacement = receivingPage.FindFreeSlot();
            }

            // Is there already a item?
            IItem itemTo;
            try
            {
                itemTo = receivingPage[toPlacement];
            }
            catch (Exception)
            {
                itemTo = null;
            }

            // Calculating delay for equip/unequip/switch gear
            int delay = 20;

            cli.Character.DoNotDoTimers = true;
            IItemSlotHandler equipTo = receivingPage as IItemSlotHandler;
            IItemSlotHandler unequipFrom = sendingPage as IItemSlotHandler;

            noAppearanceUpdate =
                !((equipTo is WeaponInventoryPage) || (equipTo is ArmorInventoryPage)
                  || (equipTo is SocialArmorInventoryPage));
            noAppearanceUpdate &=
                !((unequipFrom is WeaponInventoryPage) || (unequipFrom is ArmorInventoryPage)
                  || (unequipFrom is SocialArmorInventoryPage));

            if (equipTo != null)
            {
                if (itemTo != null)
                {
                    if (receivingPage.NeedsItemCheck)
                    {
                        Actions action = GetAction(sendingPage, itemFrom);

                        if (action.CheckRequirements(cli.Character))
                        {
                            UnEquip.Send(cli, receivingPage, toPlacement);
                            if (!noAppearanceUpdate)
                            {
                                // Equipmentpages need delays
                                // Delay when equipping/unequipping
                                // has to be redone, jumping breaks the equiping/unequiping
                                // and other messages have to be done too
                                // like heartbeat timer, damage from environment and such

                                delay = (itemFrom.GetAttribute(211) == 1234567890 ? 20 : itemFrom.GetAttribute(211))
                                        + (itemTo.GetAttribute(211) == 1234567890 ? 20 : itemTo.GetAttribute(211));
                            }

                            Thread.Sleep(delay * 10); // social has to wait for 0.2 secs too (for helmet update)

                            cli.Character.Send(message);
                            equipTo.HotSwap(sendingPage, fromPlacement, toPlacement);
                            Equip.Send(cli, receivingPage, toPlacement);
                        }
                    }
                }
                else
                {
                    if (receivingPage.NeedsItemCheck)
                    {
                        if (itemFrom == null)
                        {
                            throw new NullReferenceException("itemFrom can not be null, possible inventory error");
                        }

                        Actions action = GetAction(receivingPage, itemFrom);

                        if (action.CheckRequirements(cli.Character))
                        {
                            if (!noAppearanceUpdate)
                            {
                                // Equipmentpages need delays
                                // Delay when equipping/unequipping
                                // has to be redone, jumping breaks the equiping/unequiping
                                // and other messages have to be done too
                                // like heartbeat timer, damage from environment and such

                                delay = itemFrom.GetAttribute(211);
                                if ((equipTo is SocialArmorInventoryPage) || (delay == 1234567890))
                                {
                                    delay = 20;
                                }

                                Thread.Sleep(delay * 10);
                            }

                            if (sendingPage == receivingPage)
                            {
                                // Switch rings for example
                                UnEquip.Send(cli, sendingPage, fromPlacement);
                            }

                            cli.Character.Send(message);
                            equipTo.Equip(sendingPage, fromPlacement, toPlacement);
                            Equip.Send(cli, receivingPage, toPlacement);
                        }
                    }
                }
            }
            else
            {
                if (unequipFrom != null)
                {
                    // Send to client first
                    if (!noAppearanceUpdate)
                    {
                        // Equipmentpages need delays
                        // Delay when equipping/unequipping
                        // has to be redone, jumping breaks the equiping/unequiping
                        // and other messages have to be done too
                        // like heartbeat timer, damage from environment and such

                        delay = itemFrom.GetAttribute(211);
                        if ((unequipFrom is SocialArmorInventoryPage) || (delay == 1234567890))
                        {
                            delay = 20;
                        }

                        Thread.Sleep(delay * 10);
                    }

                    UnEquip.Send(cli, sendingPage, fromPlacement);
                    unequipFrom.Unequip(fromPlacement, receivingPage, toPlacement);
                    cli.Character.Send(message);
                }
                else
                {
                    // No equipment page involved, just send ContainerAddItemMessage back
                    message.TargetPlacement = receivingPage.FindFreeSlot();
                    IItem item = sendingPage.Remove(fromPlacement);
                    receivingPage.Add(message.TargetPlacement, item);
                    cli.Character.Send(message);
                }
            }

            cli.Character.DoNotDoTimers = false;

            cli.Character.Stats.ClearChangedFlags();

            // Apply item functions before sending the appearanceupdate message
            cli.Character.CalculateSkills();

            if (!noAppearanceUpdate)
            {
                AppearanceUpdate.AnnounceAppearanceUpdate(cli.Character);
            }
        }