private static void ParseMagicEffect(InputMessage input)
 {
     input.getLocation();
     input.getByte();
 }
 private static void ParseDisconnectClient(InputMessage input)
 {
     input.getString();
 }
 private static void ParseTextMessage(InputMessage input)
 {
     input.getByte();
     input.getString();
 }
 private static void ParseCreatureLight(InputMessage input)
 {
     input.getU32();
     input.getByte();
     input.getByte();
 }
 private static void ParseCloseContainer(InputMessage input)
 {
     input.getByte();
 }
        private static void ParseMoveCreature(InputMessage input)
        {
            Location oldLocation = input.getLocation();
            var      oldStack    = input.getByte();
            Location newLocation = input.getLocation();

            if (oldLocation.IsCreature)
            {
                var      creatureId = oldLocation.GetCretureId(oldStack);
                Creature creature   = new Creature(creatureId);

                if (creature == null)
                {
                    return;
                }

                var tile = Instance.Map.GetTile(newLocation);
                if (tile == null)
                {
                    return;
                }

                tile.AddThing(creature);
                Instance.Map.SetTile(tile);
            }
            else
            {
                Tile tile = Instance.Map.GetTile(oldLocation);
                if (tile == null)
                {
                    return;
                }

                Thing    thing    = tile.GetThing(oldStack);
                Creature creature = thing as Creature;
                if (creature == null)
                {
                    return; //The client will send update tile.
                }
                tile.RemoveThing(oldStack);
                Instance.Map.SetTile(tile);

                tile = Instance.Map.GetTile(newLocation);
                if (tile == null)
                {
                    return;
                }

                tile.AddThing(creature);
                Instance.Map.SetTile(tile);

                //update creature direction
                if (oldLocation.X > newLocation.X)
                {
                    creature.LookDirection = Direction.DIRECTION_WEST;
                    creature.TurnDirection = Direction.DIRECTION_WEST;
                }
                else if (oldLocation.X < newLocation.X)
                {
                    creature.LookDirection = Direction.DIRECTION_EAST;
                    creature.TurnDirection = Direction.DIRECTION_EAST;
                }
                else if (oldLocation.Y > newLocation.Y)
                {
                    creature.LookDirection = Direction.DIRECTION_NORTH;
                    creature.TurnDirection = Direction.DIRECTION_NORTH;
                }
                else if (oldLocation.Y < newLocation.Y)
                {
                    creature.LookDirection = Direction.DIRECTION_SOUTH;
                    creature.TurnDirection = Direction.DIRECTION_SOUTH;
                }
            }
        }
 private static void ParseHouseWindow(InputMessage input)
 {
     input.getByte();
     input.getU32();
     input.getString();
 }
 private static void ParseAddContainerItem(InputMessage input)
 {
     input.getByte();
     GetThing(input);
 }
 private static void ParsesRuleViolationCancel(InputMessage input)
 {
     input.getString();
 }
 private static void ParseLockRuleViolation(InputMessage input)
 {
 }
 private static void ParseRemoveReport(InputMessage input)
 {
     input.getString();
 }
 private static void ParseRuleViolationsChannel(InputMessage input)
 {
     ushort size = input.getU16();
 }
 private static void ParseWaitList(InputMessage input)
 {
     input.getString();
     input.getByte();
 }
 private static void ParseVIPLogin(InputMessage input)
 {
     input.getU32();
 }
 private static void ParseClosePrivate(InputMessage input)
 {
     input.getU16();
 }
 private static void ParseDistanceShoot(InputMessage input)
 {
     input.getLocation();
     input.getLocation();
     input.getByte();
 }
 private static void ParseChannel(InputMessage input)
 {
     input.getU16();
     input.getString();
 }
 private static void ParseRemoveContainerItem(InputMessage input)
 {
     input.getByte();
     input.getByte();
 }
 private static void ParseOutfitWindow(InputMessage input)
 {
     input.getOutfit();
     input.getByte();
     input.getByte();
 }
 private static void ParseAnimatedText(InputMessage input)
 {
     input.getLocation();
     input.getByte();
     input.getString();
 }
 private static void ParseOpenPrivateChannel(InputMessage input)
 {
     input.getString();
 }
 private static void ParsePlayerIcons(InputMessage input)
 {
     input.getByte();
 }
 private static void ParseCancelWalk(InputMessage input)
 {
     input.getByte();
 }
 private static void ParseVIP(InputMessage input)
 {
     input.getU32();
     input.getString();
     input.getByte();
 }
 private static void ParseCreatureOutfit(InputMessage input)
 {
     input.getU32();
     input.getOutfit();
 }
 private static void ParseWorldLight(InputMessage input)
 {
     input.getByte();
     input.getByte();
 }
 private static void ParseChangeSpeed(InputMessage input)
 {
     input.getU32();
     input.getU16();
 }
        private static Thing GetThing(InputMessage message)
        {
            //get thing type
            var thingId = message.getU16();

            if (thingId == 0x0061 || thingId == 0x0062)
            {
                //Console.WriteLine("Creature baby.");
                //creatures
                Creature creature = null;
                if (thingId == 0x0062)
                {
                    uint creatureId = message.getU32();
                    creature = new Creature(creatureId);
                    if (creature == null)
                    {
                        throw new Exception("[GetThing] (0x0062) Can't find the creature.");
                    }

                    byte creatureHealth = message.getByte();
                    //Console.WriteLine("Creature with id: " + creatureId + " Life: " + creatureHealth);
                }
                else if (thingId == 0x0061)     //creature is not known
                {
                    uint creatureId = message.getU32();
                    //Console.WriteLine("Removing creature: " + creatureId);
                    uint creatureIdNew = message.getU32();
                    creature        = new Creature(creatureIdNew);
                    creature.Name   = message.getString();
                    creature.Health = message.getByte();
                }

                var direction = (Direction)message.getByte();
                creature.LookDirection = direction;
                creature.TurnDirection = direction;

                creature.Outfit     = message.getOutfit();
                creature.LightLevel = message.getByte();
                creature.LightColor = message.getByte();
                creature.Speed      = message.getU16();
                creature.Skull      = message.getByte();
                creature.Shield     = message.getByte();

                return(creature);
            }
            else if (thingId == 0x0063)
            {
                uint     creatureId = message.getU32();
                Creature creature   = new Creature(creatureId);
                if (creature == null)
                {
                    throw new Exception("[GetThing] (0x0063)  Can't find the creature in the battle list.");
                }

                creature.TurnDirection = (Direction)message.getByte();

                return(creature);
            }
            else
            {
                return(GetItem(message, thingId));
            }
        }
        public static void ParsePacket(Recording recording, Packet packet)
        {
            byte[]       packetData     = packet.GetPacketData();
            InputMessage inputMessage   = new InputMessage(packetData);
            byte         lastPacketHead = 0;

            try {
                while (inputMessage.getPosition() < inputMessage.getLength())
                {
                    byte packetHead = inputMessage.getByte();
                    switch (packetHead)
                    {
                    case 0xA:
                        ParseLogin(inputMessage);
                        break;

                    case 0x14:
                        ParseDisconnectClient(inputMessage);
                        break;

                    case 0x16:
                        ParseWaitList(inputMessage);
                        break;

                    case 0x1E:
                        break;

                    case 0x64:
                        ParseMapDescription(recording, inputMessage);
                        break;

                    case 0x65:
                        ParseNorthMove(inputMessage);
                        break;

                    case 0x66:
                        ParseEastMove(inputMessage);
                        break;

                    case 0x67:
                        ParseSouthMove(inputMessage);
                        break;

                    case 0x68:
                        ParseWestMove(inputMessage);
                        break;

                    case 0x69:
                        ParseUpdateTile(inputMessage);
                        break;

                    case 0x6A:
                        ParseAddTileItem(inputMessage);
                        break;

                    case 0x6B:
                        ParseUpdateTileItem(inputMessage);
                        break;

                    case 0x6C:
                        ParseRemoveTileItem(inputMessage);
                        break;

                    case 0x6D:
                        ParseMoveCreature(inputMessage);
                        break;

                    case 0x6E:
                        ParseContainer(inputMessage);
                        break;

                    case 0x6F:
                        ParseCloseContainer(inputMessage);
                        break;

                    case 0x70:
                        ParseAddContainerItem(inputMessage);
                        break;

                    case 0x71:
                        ParseUpdateContainerItem(inputMessage);
                        break;

                    case 0x72:
                        ParseRemoveContainerItem(inputMessage);
                        break;

                    case 0x78:
                    case 0x79:
                        ParseInventoryItem(inputMessage, packetHead);
                        break;

                    case 0x7D:
                    case 0x7E:
                        ParseTradeItemRequest(inputMessage);
                        break;

                    case 0x7F:
                        break;

                    case 0x82:
                        ParseWorldLight(inputMessage);
                        break;

                    case 0x83:
                        ParseMagicEffect(inputMessage);
                        break;

                    case 0x84:
                        ParseAnimatedText(inputMessage);
                        break;

                    case 0x85:
                        ParseDistanceShoot(inputMessage);
                        break;

                    case 0x86:
                        ParseCreatureSquare(inputMessage);
                        break;

                    case 0x8C:
                        ParseCreatureHealth(inputMessage);
                        break;

                    case 0x8D:
                        ParseCreatureLight(inputMessage);
                        break;

                    case 0x8E:
                        ParseCreatureOutfit(inputMessage);
                        break;

                    case 0x8F:
                        ParseChangeSpeed(inputMessage);
                        break;

                    case 0x90:
                        ParseCreatureSkull(inputMessage);
                        break;

                    case 0x91:
                        ParseCreatureShield(inputMessage);
                        break;

                    case 0x96:
                        ParseTextWindow(inputMessage);
                        break;

                    case 0x97:
                        ParseHouseWindow(inputMessage);
                        break;

                    case 0xA0:
                        ParsePlayerStats(inputMessage);
                        break;

                    case 0xA1:
                        ParsePlayerSkills(inputMessage);
                        break;

                    case 0xA2:
                        ParsePlayerIcons(inputMessage);
                        break;

                    case 0xA3:     // cancel target
                        break;

                    case 0xAA:
                        ParseCreatureSpeak(inputMessage);
                        break;

                    case 0xAB:
                        ParseChannelsDialog(inputMessage);
                        break;

                    case 0xAC:
                        ParseChannel(inputMessage);
                        break;

                    case 0xAD:
                        ParseOpenPrivateChannel(inputMessage);
                        break;

                    case 0xAE:
                        ParseRuleViolationsChannel(inputMessage);
                        break;

                    case 0xAF:
                        ParseRemoveReport(inputMessage);
                        break;

                    case 0xB0:
                        ParsesRuleViolationCancel(inputMessage);
                        break;

                    case 0xB1:
                        ParseLockRuleViolation(inputMessage);
                        break;

                    case 0xB4:
                        ParseTextMessage(inputMessage);
                        break;

                    case 0xB2:
                        ParseCreatePrivateChannel(inputMessage);
                        break;

                    case 0xB3:
                        ParseClosePrivate(inputMessage);
                        break;

                    case 0xB5:
                        ParseCancelWalk(inputMessage);
                        break;

                    case 0xBE:
                        ParseFloorChangeUp(inputMessage);
                        break;

                    case 0xBF:
                        ParseFloorChangeDown(inputMessage);
                        break;

                    case 0xC8:
                        ParseOutfitWindow(inputMessage);
                        break;

                    case 0xD2:
                        ParseVIP(inputMessage);
                        break;

                    case 0xD3:
                        ParseVIPLogin(inputMessage);
                        break;

                    case 0xD4:
                        ParseVIPLogout(inputMessage);
                        break;

                    default:
                        throw new Exception("Invalid packet head (maybe different version?)");
                    }

                    lastPacketHead = packetHead;
                }
            } catch (Exception ex) {
                //Console.WriteLine("Corrupted packet.");
                recording.HasProblem = true;
            }
        }