Refactor client packet decoding, take 2

Re-opening #82 against `dev`.