We treat client messages like server messages, dedicating a subclass to each message type. The subclass is expected to provide accessors to set the message fields, and an encodeData function that uses the appendByte/appendInt32 and other functions to assemble the encoded message. The base class prepends the message type and length.