# Reaper's Sky - Dedicated Server

Everything needed to run the Reaper's Sky NeoForge **1.21.1** server (NeoForge
**21.1.248**) on Debian 13 (trixie).

## Quick start (on the server box)

```sh
sudo ./deploy.sh     # installs Java 21 + curl/unzip, NeoForge, the 92 mods, config
./run.sh             # start the server (run inside tmux/screen so it survives logout)
```

The first `./run.sh` generates the world. Wait for `Done (...)` in the console,
then connect with IP **`reaperofveriod.nl`** (port 25565).

`deploy.sh` is idempotent — safe to re-run; it skips anything already in place
and verifies every mod by sha1 before installing.

## What deploy.sh does

| Step | Result |
|------|--------|
| System packages | `openjdk-21-jre-headless`, `curl`, `unzip` (needs root/`sudo`) |
| NeoForge server | Official installer from Maven → server files + `libraries/` |
| Mods | Downloads the 92 server-safe mods pinned in `mods.json`, sha1-verified; prunes jars no longer in the pack |
| Config | `eula.txt` (EULA accepted), `server.properties` (IP, motd, 8 G) |
| Run script | `run.sh` with 8 GB + G1GC (`nogui`) |

Install location defaults to `~/reaper-sky-server`. Override with `DIR=/path`,
memory with `MEMORY=6G`, etc.:

```sh
sudo DIR=/srv/minecraft MEMORY=10G ./deploy.sh
```

## Keeping it running

```sh
tmux new -s mc                    # new session
cd ~/reaper-sky-server && ./run.sh
# detach with Ctrl-b d, reattach later with: tmux attach -t mc
```

Stop the server cleanly with the console command `stop` (Ctrl-c also works).

## Configuration notes

- `server.properties` sets `online-mode=true` (Mojang authentication). Set it to
  `false` in `~/reaper-sky-server/server.properties` to allow unauthenticated
  clients, then restart.
- `server-ip` is left **empty** on purpose: the server binds all interfaces
  (`0.0.0.0`) and is reached through the edge router's port-forward. Do **not**
  put the public hostname/IP here — it isn't assigned to a local interface and
  the server will crash with `Cannot assign requested address`.
- `difficulty=hard`, `spawn-protection=0`, `view-distance=10` are set for the
  airship-focused, land-claim-friendly experience.
- The 17 client-only mods (Iris/shaders, Sodium, Minimap, MouseTweaks, etc.)
  are intentionally excluded here — everything gameplay-relevant runs on the
  server too (including JEI and Jade).

## Updating the server's mods

### The easy way — one command from your PC

If your PC has SSH key access to the server (`ssh root@ReapersSky` works
without a password), you can push mod changes to the live server with a single
command run **from the repo root on your PC**:

```sh
python3 server/build_mods.py --push
```

This does everything:

1. Scans the Prism instance `Reaper's Sky - dev` and regenerates
   `server/mods.json` (skipping client-only mods).
2. Uploads that manifest to the server.
3. On the server: **stops** it cleanly, **syncs** `mods/` against the manifest
   (deletes jars that are no longer in the pack, downloads + sha1-verifies new
   or changed ones), then **starts** it again.
4. Waits for boot and prints `Server is UP` once the log shows `Done (...)`.

No git commit/push is needed first — it works straight from your working tree,
so you can test changes on the server before committing them.

Useful variations:

```sh
python3 server/build_mods.py --push          # full cycle: stop -> sync -> start
RS_SERVER_HOST=user@otherhost python3 server/build_mods.py --push   # different box
```

### Manual / on-server way

If you already have a `mods.json` on the server (e.g. uploaded by hand), run
this **on the server box**:

```sh
bash ~/update.sh /path/to/mods.json        # stop -> sync -> start
bash ~/update.sh /path/to/mods.json --no-start   # sync only, leave stopped
```

`update.sh` is safe to re-run at any time: if the server isn't running it just
syncs; every jar is verified by sha1 before it counts as installed.

### Full reinstall

For a brand-new box (or to rebuild everything from scratch), use the one-shot
installer described at the top — it also prunes stale jars since it shares the
same sync logic.
