# Hurry Curry! protocol

The protocol schema is defined in [`protocol.ts`](./test-client/protocol.ts)

1. Connect to the server via WebSocket and send/receive json in WebSocket "Text"
   messages. The binary protocol uses "Binary" messages and is optional for
   servers and clients.
2. Wait for `version` packet and check version compatibiliy (see below).
3. Send the join packet with your username.
4. The server will send the current game state:
   - `data` once for setting important look-up tables
   - `update_map` for every tile
   - `set_tile_item` for every item on a tile
   - `add_player` for every player in the game
   - `set_player_item` for every item held by a player
5. Run the game loop
   - Send your position every 20ms - 40ms.
   - Send `interact` when the player interacts with a tile.
   - Receive packets
6. The Game ends. The server will remove all players and tiles. Then continue at
   step 4.

Collisions are handled by the clients. Whenever to players collide the player
with the greater PlayerID is responsible for updating their own momentum and
sending a packet to update that of the other player.

## Ports

- 443: All uses with TLS
- 27032: Game Server Websocket
- 27033: Registry API HTTP / Local dicovery service
- 27034: Lobby Server Websocket
- 27035: Map Editor Server Websocket

## Binary Protocol

Servers might also support the binary protocol. It uses
[Bincode](https://github.com/bincode-org/bincode) to encode packets. If a server
advertises bincode support with the `init` packet, you are free to use the
binary protocol. By default the server will send JSON. For every packet you
send, you can choose between bincode and JSON. After a client sent the first
Bincode packet, the server might start to reply using Bincode aswell. Bincoded
packets are sent with WebSocket "Binary" messages.

## Protocol Versioning

The `init` packet sends minor and major version numbers of the protocol is use
by the server. These are to be interpreted according to
[SemVer](https://semver.org/) for the JSON protocol. The binary protocol can not
be used if either minor or major version differs.

## Movement

Movement is handled server-side but should be predicted by client for better
latency. For this reason it implemented three times:

- In GDscript (for the Godot client):
  [controllable_player.gd](./client/player/controllable_player.gd)
- In Rust (for server, pixelcurry and customers):
  [movement.rs](./server/protocol/src/movement.rs)
- In TypeScript (for test-client): [movement.ts](./test-client/movement.ts)

## Limits

The server currently enforces the following network limits:

- Server inbound json packets are at most 8196 bytes in size
- Server inbound binary packets are at most 4096 bytes in size
- Player names are no longer than 32 characters
- Player names are no longer than 64 bytes
