Add map/level negotiation to server

This adds the logic to the server to inform and provide the map to newly connected clients. It's a relatively straight forward procedure.

Upon a new client connecting (and entering the `Connected` state) it is sent a 'map offer', which is the MD5 hash of the map file's contents. E.g.

```json
{"type": "map.offer", "entity": "a9531495903a650967c81781c1694d05"}
```

When the client receives the *offer* it is their responsibility to check if it has this map available and if it is available, that it truly matches the MD5 checksum. If the client doesn't have the map available or the map file is corrupted in some may it must request it from the server:

```json
{"type": "map.request", "entity": null}
```

Note that the `map.request` entity is ignored. Therefore setting it to null seems reasonable even though the server won't enforce its existence.

When the server receives the `map.request` it'll send back the base64-encoded contents of the map file.

```json
{"type": "map.contents", "entity": "BQUCAgABAAAAAAABAAAAAAABAAAAAAABAAAAAAA="}
```

This highlights a couple of problems:

 * We should have probably looked to use an exchange format that supports raw binary data, e.g. BSON.
 * `map.contents` is potentially large so sending it means being blocked on IO for a long time. However the blocking nature of our IO is something that will have to be fixed at a later date regardless.

When the client receives the `map.contents` it should decode it, cache it, sanity check it (using the checksum sent in the `map.offer`) and load it. I do not believe there needs to be an explicit confirmation from the client indicating it loaded the map okay. This should also apply to the initial `map.offer`. If the client *does* have the correct map cached already then it need not send anything at all to server about the map.

:8ball: