scroll.server/README.md
WiseDev c0713b50d7 supervised mode: run the services as child processes
SCROLL_MODE=supervised spawns auth-service, game-service and gateway, waits for
each rpc port before starting the next, and restarts whatever dies with backoff
from 500ms to 30s. the counter resets once a service has been up a minute.

single process mode is still the default and unchanged.

kill_on_drop means ctrl-c takes the children with it, no orphans.
2026-08-23 09:46:59 +03:00

91 lines
2.3 KiB
Markdown

# scroll-server
A server for the `scroll` client (Clash Royale `2.0.1306`, iOS). Takes a real
client from TCP connect to the lobby: login, own home data, chests, card
upgrades, the shop.
## Requirements
* Rust 1.75+
* PostgreSQL 16
## Running
```bash
createdb scroll
```
```bash
cargo run --release -p scroll-server
```
Listens on `0.0.0.0:9339`, the port the client hardcodes. The schema is created
on first boot. `DATABASE_URL` defaults to `postgres:///scroll`.
On macOS a Homebrew cluster may need `LC_ALL=C` to start at all.
That runs everything in one process. For real isolation, `SCROLL_MODE=supervised`
makes it spawn the three services as child processes and restart any that dies,
with backoff:
```bash
SCROLL_MODE=supervised ./target/release/scroll-server
```
They can also be started by hand, in any order:
```bash
cargo run --release -p auth-service
cargo run --release -p game-service
cargo run --release -p gateway
```
## Checking it without a phone
`scroll-probe` speaks the same protocol and prints the decoded lobby:
```bash
cargo run --release -p gateway --bin scroll-probe -- 127.0.0.1:9339
```
Flags: `--claim-free-chest`, `--buy-chest <name>`, `--desync`. Pass an account
and pass token to reconnect as an existing player:
`scroll-probe 127.0.0.1:9339 0 1 <passtoken>`.
## Pointing a client at it
The client hardcodes `game.clashroyaleapp.com`. Patch that string in the binary
inside the ipa to your machine's address, keeping the 23 byte slot NUL padded so
nothing around it moves.
## Configuration
| variable | default |
| --- | --- |
| `DATABASE_URL` | `postgres:///scroll` |
| `SCROLL_MODE` | `single`, or `supervised` |
| `SCROLL_BIN_DIR` | next to the running binary |
| `SCROLL_AUTH_LISTEN` | `127.0.0.1:9401` |
| `SCROLL_GAME_LISTEN` | `127.0.0.1:9402` |
| `SCROLL_GATEWAY_LISTEN` | `0.0.0.0:9339` |
| `SCROLL_CSV_ROOT` | `assets` |
| `SCROLL_SHOP` | `config/shop.json` |
| `SCROLL_STARTER_PROFILE` | built in |
| `RUST_LOG` | `info` |
## Shop
`config/shop.json` lists what the server sells, as `Name#count`:
```json
{
"offers": [
{ "id": 1, "give": "Gold#1000" },
{ "id": 5, "give": "chest:Gold#1" },
{ "id": 7, "give": "Diamonds#500", "cost": "Gold#20000" }
]
}
```
Names resolve against the csv tables. `cost` is optional; without it the server
charges the same price the client computes from the game data.