diff --git a/guides/docker.md b/guides/docker.md new file mode 100644 index 0000000..ba45b4e --- /dev/null +++ b/guides/docker.md @@ -0,0 +1,178 @@ +--- +title: Docker and game panels +group: Guides +sidebar: + order: 6 +--- + +Every release publishes the Linux dedicated server as a public container image: + +```text +ghcr.io/hogwarts-mp/hogwartsmp-server: +``` + +The image holds the same native server the release ZIP ships, repackaged on Ubuntu 24.04 for `linux/amd64`. It is not a source build, and like the ZIP it carries **no game-mode resources**. Pulling it needs no login. + +Tags are exact release versions with no leading `v`, such as `1.8.0`. There is no `latest`, `stable` or `testing` tag, because the server must match the release your players run: a mismatched client is rejected before it loads in. Changing the tag is how you update. + +This page covers the container. Configuration, Foundations, ports and the masterlist work exactly as in [Hosting a server](/guides/hosting/). + +## Docker Compose + +Create a directory for the server with this `compose.yaml`: + +```yaml +services: + server: + image: ghcr.io/hogwarts-mp/hogwartsmp-server:${HOGWARTSMP_VERSION:?Set HOGWARTSMP_VERSION to a released version} + platform: linux/amd64 + restart: unless-stopped + init: true + ports: + - "27015:27015/udp" # game traffic: must be reachable by players + - "127.0.0.1:27016:27016/tcp" # information API: this host only + volumes: + - server-data:/home/container + stop_grace_period: 30s + +volumes: + server-data: +``` + +Next to it, create a `.env` that pins the release: + +```dotenv +HOGWARTSMP_VERSION=1.8.0 +``` + +Start it and follow the log: + +```sh +docker compose pull +docker compose up -d +docker compose logs -f server +``` + +The server is up when the log shows `HogwartsMP Server successfully started`. Open UDP 27015 on the host or cloud firewall as well. Publishing a port in Compose does not open it in a firewall in front of the machine. + +Without Compose, the same container is: + +```sh +docker run -d --name hogwartsmp --init --restart unless-stopped \ + -p 27015:27015/udp -p 127.0.0.1:27016:27016/tcp \ + -v hogwartsmp-data:/home/container \ + ghcr.io/hogwarts-mp/hogwartsmp-server:1.8.0 +``` + +## Data and resources + +`/home/container` is the server's working directory and its volume. Everything that must survive an upgrade lives there: + +```text +/home/container/ +├── server.json # written with defaults on first start +├── resources/ # your game mode, e.g. the hmp-* Foundations resources +├── data/ # Foundations' hmp-*.json configuration +├── logs/ +└── .packages/ # resource package key and cache; keep it +``` + +The server runs as UID and GID `10001`, not root. A named volume handles ownership for you. To manage resources from the host instead, bind-mount a directory over `resources/` and make it writable by that UID: + +```yaml + volumes: + - server-data:/home/container + - ./resources:/home/container/resources +``` + +```sh +sudo chown -R 10001:10001 ./resources +``` + +Install Foundations by copying its `hmp-*` directories into `resources/` and its example configs into `data/`, as in [Install HMP Foundations](/guides/hosting/#4-install-hmp-foundations). Restart the container after changing resources or `server.json`. + +### Database and secrets + +Inside the container, `127.0.0.1` is the container itself, not the host. Point `data/hmp-mysql.json` (or `HMP_MYSQL_HOST`) at a database the container can reach. With a MySQL service in the same Compose file, that is the service's name. Foundations' [database guide](https://github.com/hogwarts-mp/foundations/blob/main/DATABASE.md#option-2-docker-on-the-game-server-machine) has a ready-made MySQL container. Never publish the database's port to the internet. + +Foundations reads its secrets from the process environment. Keep them in a file next to `compose.yaml`, readable only by you, and hand it to the service: + +```yaml +services: + server: + # ... + env_file: foundations.env +``` + +## Ports and flags + +Arguments after the image name go straight to the server, as the [command-line flags](/guides/server-config/#command-line-flags). Change the published ports to match: + +```sh +docker run -d --name hogwartsmp --init --restart unless-stopped \ + -p 28015:28015/udp -p 127.0.0.1:28016:28016/tcp \ + -v hogwartsmp-data:/home/container \ + ghcr.io/hogwarts-mp/hogwartsmp-server:1.8.0 --port 28015 --apiport 28016 +``` + +In Compose, edit `command` and `ports` together: + +```yaml + command: ["--port", "28015", "--apiport", "28016"] + ports: + - "28015:28015/udp" + - "127.0.0.1:28016:28016/tcp" +``` + +Keep the container port equal to the published port, as above. Mapping `28015:27015` would have the server advertise 27015 to the masterlist while players need 28015. + +## Update + +Stop the server, back up the volume and the Foundations database, then move the tag: + +```sh +docker compose down +# edit .env: HOGWARTSMP_VERSION= +docker compose pull +docker compose up -d +``` + +The runtime lives in the image, so there is nothing to copy. Your volume keeps `server.json`, `data/` and `resources/`; replace the Foundations pack there with the release that matches. The [update checklist](/guides/hosting/#update-to-a-new-release) still applies. + +The server handles `SIGTERM` and `SIGINT` by shutting down cleanly: every resource's stop handlers run and state is saved. `docker stop` and `docker compose down` send `SIGTERM`, and the 30-second grace period gives the shutdown time to finish. + +## Pterodactyl and Pelican + +Each release has a ready-made egg that points at that release's exact image, so importing it pins the version. The egg ships inside the image, so you can extract it from any machine with Docker: + +```sh +docker run --rm --user 0 --entrypoint cat ghcr.io/hogwarts-mp/hogwartsmp-server:1.8.0 \ + /usr/share/hogwartsmp/egg-hogwartsmp.json > egg-hogwartsmp.json +``` + +`--user 0` is needed because the image's default user cannot open the directory that holds the egg. + +Then, in the panel: + +1. **Admin → Nests → Import Egg**, and upload `egg-hogwartsmp.json`. +2. Create a server from the egg. Its **primary allocation** is the UDP game port players connect to. +3. Assign a **second allocation** for the information API and set the **HTTP port** variable to it. The variable selects a port; it does not allocate one. +4. Set **Masterlist token** to your [server key](/guides/hosting/#8-list-it-publicly), or leave it blank for an unlisted server. The panel's value overrides any `server-token` in `server.json`. +5. Start the server. The panel marks it running once the log shows `HogwartsMP Server successfully started`. + +The install step only creates `resources/`, `logs/` and `.packages/`. Upload Foundations or your own resources into `resources/` through the panel's **File Manager** or SFTP, and edit `server.json` there for the keys the panel does not control, such as `maxplayers` and `password`. The panel stops the server with `^C`, which is the same clean shutdown as `SIGINT`. + +To update, switch the server's Docker image to the next release's tag in its startup settings, or update the egg from that release's file, then restart. There is nothing to reinstall. + +## Troubleshooting + +| Symptom | Check | +| --- | --- | +| Players are rejected immediately | The image tag and the players' client are from different releases. | +| The server runs but has no game mode | Expected on a fresh volume. The image ships no resources; install Foundations into `resources/`. | +| `Permission denied` writing `resources/`, `logs/` or `server.json` | A bind mount is not writable by UID `10001`. `chown -R 10001:10001` the host directory. | +| The panel is stuck on **Starting** | The panel waits for `HogwartsMP Server successfully started`. Read the console for the error that came first. | +| `libnode.so.141: cannot open shared object file` | The panel's startup command no longer runs `/opt/hogwartsmp/HogwartsMPServer`, or `LD_LIBRARY_PATH` was overridden. The image sets it; leave it alone. | +| Foundations reports `ECONNREFUSED` | `127.0.0.1` inside the container is the container. Use the database service's name or the host's address. | +| Exits on a VPS with `CPU doesn't support invariant TSC` | Add `TRACY_NO_INVARIANT_CHECK=1` to the container's environment. | +| Players cannot connect | Confirm the UDP port is published, opened in the host and cloud firewalls, and equal on both sides of the mapping. | diff --git a/guides/events.md b/guides/events.md index 226f5f9..41afb5c 100644 --- a/guides/events.md +++ b/guides/events.md @@ -1,6 +1,8 @@ --- title: Events group: Guides +sidebar: + order: 3 --- `Events` is the asynchronous, named event bus available to both server and client resources. Resources use it to react to runtime activity, communicate with other resources in the same environment, and exchange messages across the client/server boundary. diff --git a/guides/getting-started.md b/guides/getting-started.md index d0e5dd1..f72d34b 100644 --- a/guides/getting-started.md +++ b/guides/getting-started.md @@ -1,6 +1,8 @@ --- title: Your first resource group: Guides +sidebar: + order: 2 --- Everything a game mode does in HogwartsMP lives in a **resource**: a directory containing a `package.json` manifest and one or more JavaScript files. The server discovers every resource directory under `resources/` at startup, runs its server scripts in Node.js, and packages its client scripts and assets for each connecting player, where they run in a sandboxed V8 context. diff --git a/guides/hosting.md b/guides/hosting.md new file mode 100644 index 0000000..b5a7463 --- /dev/null +++ b/guides/hosting.md @@ -0,0 +1,301 @@ +--- +title: Hosting a server +group: Guides +sidebar: + order: 4 +--- + +A HogwartsMP server is one executable plus a `server.json` configuration file and a `resources/` directory. The release ships the runtime only, with no game mode. Public servers run **HMP Foundations**, a complete resource pack that adds characters, inventory, banking, jobs, shops, administration and other common systems on top of a MySQL or MariaDB database. + +This guide takes a fresh machine to a server players can join, then covers keeping it running and updating it. It is for server owners. Players only need the [player guide](https://github.com/hogwarts-mp/hosting/blob/main/PLAYER_GUIDE.md). + +## What you need + +| | Why | +| --- | --- | +| A Windows x64 or Linux x86-64 host | The dedicated server is native on both. Linux needs **glibc 2.38 or newer**: Ubuntu 24.04+ or Debian 13+. | +| The release ZIP from the official `#builds` channel in the [HogwartsMP Discord](https://discord.gg/RzqENjGe99) | It must be the **same release your players run**. A mismatched client is rejected before it loads in. | +| MySQL 8.x or MariaDB 10.6+ | Foundations stores its data there. A bare server with no resources needs no database. | +| An [HMP Foundations release](https://github.com/hogwarts-mp/foundations/releases) | The supported starting point for a public server. Its [compatibility matrix](https://github.com/hogwarts-mp/foundations/blob/main/COMPATIBILITY.md) names the HogwartsMP release it pairs with. | +| Control of the host firewall, and of the router on a home connection | Players reach the server on **UDP 27015**. | + +> Running in Docker or under Pterodactyl or Pelican? The server's [public image](/guides/docker/) packages this same runtime. Read on for configuration, Foundations and the masterlist, then follow that page for the container itself. + +## 1. Get the release + +Download the complete ZIP from `#builds` and extract it. It is arranged like this: + +```text +HogwartsMP--/ +├── client/ # your own client copy +├── server/ # Windows dedicated server +└── server-linux/ # Linux dedicated server +``` + +Do not send the archive or its `client/` directory to players, and do not mirror or modify it. Every player downloads their own copy from `#builds`, and the launcher keeps it updated after that. Do not combine a server directory from one archive with a client from another. + +## 2. Install the server + +### Windows + +1. Create a permanent directory such as `C:\HogwartsMPServer`. +2. Copy everything inside the release's `server` directory into it. +3. Create empty `resources`, `logs` and `data` directories next to `HogwartsMPServer.exe`. + +An ordinary user account can run the server, provided it can write to that directory. Do not run it elevated; nothing in the server requires administrator rights. + +### Linux + +Install the runtime libraries the server links against. These are the packages the official container image installs on Ubuntu 24.04, plus `unzip` for extracting Foundations: + +```sh +sudo apt-get update +sudo apt-get install -y ca-certificates libcurl4t64 libssh2-1 libssl3t64 libstdc++6 zlib1g unzip +``` + +Create an unprivileged system account to own and run the server. This is a local account on the host, not a cloud provider's IAM service account: + +```sh +sudo useradd --system --home-dir /opt/hogwartsmp --shell /usr/sbin/nologin hogwartsmp +``` + +Then install the runtime from the directory where you extracted the archive: + +```sh +sudo install -d -o hogwartsmp -g hogwartsmp /opt/hogwartsmp +sudo cp -a HogwartsMP-*/server-linux/. /opt/hogwartsmp/ +sudo install -d /opt/hogwartsmp/resources /opt/hogwartsmp/logs /opt/hogwartsmp/data +sudo chown -R hogwartsmp:hogwartsmp /opt/hogwartsmp +sudo chmod +x /opt/hogwartsmp/HogwartsMPServer /opt/hogwartsmp/crashpad_handler +``` + +The `chmod` matters: an extracted archive does not always keep the executable bit. Keep `HogwartsMPServer`, `crashpad_handler` and `libnode.so.141` together. The last one is the bundled Node.js runtime that executes server resources, and a `libnode` from another release will not work. + +Never run the server as root. + +## 3. Create `server.json` + +The server reads `server.json` from its **working directory**. Create it next to the executable: + +```json +{ + "host": "0.0.0.0", + "port": 27015, + "maxplayers": 32, + "server-token": "", + "mod": { + "curseforge": { + "mods": [] + } + } +} +``` + +That is enough for a first start. The server also writes a complete default file on its first start if none exists, listing every key the build understands. Leave `server-token` empty until you [list the server](#8-list-it-publicly). + +Every key, the join password, the command-line overrides and the required-mod list are covered in [Server configuration](/guides/server-config/). + +## 4. Install HMP Foundations + +Foundations is installed separately from the server and versioned as one unit: install every `hmp-*` resource from a single release, and never mix resource versions. Its own [installation guide](https://github.com/hogwarts-mp/foundations/blob/main/INSTALL.md) is authoritative. In short: + +1. Create an empty `hogwartsmp` database and a non-root account scoped to it, following the [database guide](https://github.com/hogwarts-mp/foundations/blob/main/DATABASE.md). Do not import a schema; Foundations creates and migrates its own tables. +2. Copy every `hmp-*` directory from the release's `resources` directory into your server's `resources/`. They must sit directly under it, with no extra `hmp-foundations/` level in between. +3. Copy the release's example `data/hmp-*.json` files into your server's `data/` and replace every `CHANGE_ME` value. `data/hmp-mysql.json` holds the database connection. +4. Remove any older resources the installation guide lists as overlapping. Two stacks loaded side by side give duplicate commands and UI. + +Secrets such as the admin bootstrap secret are read from the server process's **environment**. Foundations does not load `.env` files on its own: + +```text +HMP_ADMIN_BOOTSTRAP_SECRET=REPLACE_WITH_A_LONG_RANDOM_SECRET +HMP_ADMIN_REQUIRE_VERIFIED=true +HMP_ADMIN_UNSAFE_ASSERTED_BANS=false +``` + +The database, `data/` and these secrets are server data. They are never sent to clients. + +## 5. Open the ports + +| Port | Protocol | Expose it? | Purpose | +| --- | --- | --- | --- | +| `27015` | UDP | **Yes**, to the internet | Game traffic. Forward it through the router when hosting at home. | +| `27016` | TCP | No | Server information HTTP API. It binds every interface by default, so firewall it. Players do not need it. | +| `3306` | TCP | **Never** | MySQL or MariaDB. Restrict it to the server host or a private network. | + +On Linux with ufw: + +```sh +sudo ufw allow 27015/udp +``` + +On Windows, allow the program when Windows Defender Firewall asks on first start, or add the rule from an elevated PowerShell. The rule needs administrator rights; the server does not: + +```powershell +New-NetFirewallRule -DisplayName "HogwartsMP" -Direction Inbound -Protocol UDP -LocalPort 27015 -Action Allow +``` + +On a cloud host, open the same UDP port in the provider's firewall or security group as well. Test from a machine **outside** your network: connecting from the host itself proves nothing about the public path, and TCP port checkers cannot test a UDP port. + +## 6. Start it + +Start MySQL or MariaDB first, then the server, with the server directory as the working directory. + +On Windows: + +```powershell +Set-Location C:\HogwartsMPServer +.\HogwartsMPServer.exe +``` + +On Linux: + +```sh +cd /opt/hogwartsmp +sudo -u hogwartsmp ./HogwartsMPServer +``` + +The server finds `server.json`, `resources`, `data` and `logs` relative to the directory it runs in, so always start it from its own directory. A shortcut, scheduled task or service that only points at the executable starts in the wrong directory and finds no configuration or resources. Set its **Start in** or working directory too. + +A healthy first boot logs lines like these: + +```text +HogwartsMP Server successfully started +[hmp-mysql] connected to 127.0.0.1:3306/hogwartsmp +[hmp-core] Accounts, characters, groups and metadata are ready +``` + +followed by ready messages from the rest of the `hmp-*` resources. `Server will not be announced to masterlist` is expected while `server-token` is empty. **Do not admit players if any resource logs `Startup failed`.** The full log is written to `logs/hogwarts-mp.log`. + +The console accepts `status` (address and player count), `help`, and `stop` or `quit` to shut down cleanly. In a release build, restart the server after changing resources or `server.json`. + +## 7. Join it + +Start HogwartsMP through the launcher, open **Play**, and enter the server's address, or pick it from the list once it is [listed](#8-list-it-publicly). The client assumes port 27015, so add `:port` only if you changed it. Fill **Password** only if the server [sets one](/guides/server-config/#passwords). + +You can also hand players a link. The launcher registers the `hogwartsmp://` scheme each time it runs, so once a player has started it once, opening a link connects straight to your server: + +```text +hogwartsmp://play.example.com +hogwartsmp://203.0.113.10:28015 +``` + +Link a player to a passworded server with `?password=…` appended. Anyone holding that link can join, so do not post it publicly. + +Run your first join with a disposable test account and walk through Foundations' [first-player checks](https://github.com/hogwarts-mp/foundations/blob/main/INSTALL.md#5-first-player-checks): create and select a character, reconnect, open the inventory, and confirm `/admin` is denied to a normal player. + +## 8. List it publicly + +An unlisted server is still reachable by address. To appear in the server list, register it with the MafiaHub masterlist: + +1. Sign in at [mafiahub.dev](https://mafiahub.dev/) and open [your servers](https://mafiahub.dev/dashboard/servers). +2. Click **Add a server**. This registers the listing and gives you its **server key**. +3. Put the key in `server.json` as `server-token`, and restart. + +No heartbeat script is needed: while running, the server announces its name, address, port and player count, and it appears within a minute or so. The key also pairs the listing with the exact build players need. + +The key is a secret. Anyone with it can announce a server as yours, so keep it out of screenshots, support logs, source control and Discord. + +## Keep it running + +A server started from a terminal stops when the terminal closes, does not come back after a crash, and does not return after a reboot. + +### Linux: systemd + +Skip this if a game panel manages the process; its daemon already supervises the server. Otherwise create `/etc/systemd/system/hogwartsmp.service`: + +```ini +[Unit] +Description=HogwartsMP dedicated server +After=network-online.target mysql.service +Wants=network-online.target +Requires=mysql.service + +[Service] +Type=simple +User=hogwartsmp +Group=hogwartsmp +WorkingDirectory=/opt/hogwartsmp +EnvironmentFile=/etc/hogwartsmp.env +ExecStart=/opt/hogwartsmp/HogwartsMPServer +Restart=on-failure +RestartSec=5 +StandardInput=null +StandardOutput=journal +StandardError=journal + +[Install] +WantedBy=multi-user.target +``` + +Five lines carry the weight: + +- `WorkingDirectory` resolves `resources`, `data`, `logs` and `server.json`. +- `Requires=` and `After=mysql.service` hold the server back until the database is up. Without them a reboot races Foundations against MySQL and every resource that depends on `hmp-core` fails. On MariaDB the unit is usually `mariadb.service`. Drop both when the database runs on another machine, or when there is none. +- `EnvironmentFile` supplies Foundations' secrets. The unit file is world-readable, so secrets do not belong in it. +- `Restart=on-failure` brings the server back after a crash. +- `WantedBy=multi-user.target` starts it on boot once the unit is enabled. + +Create the private environment file, fill it with `KEY=value` lines, and enable the unit: + +```sh +sudo install -m 600 /dev/null /etc/hogwartsmp.env +sudoedit /etc/hogwartsmp.env +sudo systemctl daemon-reload +sudo systemctl enable --now hogwartsmp +``` + +Day to day: + +```sh +systemctl status hogwartsmp # running? since when? last exit? +sudo systemctl restart hogwartsmp # after editing server.json or resources +journalctl -u hogwartsmp -f # live log; add -b for this boot only +``` + +`StandardInput=null` disables the server console; `systemctl stop` and `systemctl status` replace it. Reboot the host once and confirm the server comes back by itself before opening it to players. That is the only real test that the unit is enabled and ordered after the database. + +### Windows: a service wrapper + +Use a Windows service wrapper or process manager that restarts the server on exit and starts it at boot. Whichever you choose, set its **working directory** to the server directory and give it the Foundations environment variables. + +## Update to a new release + +The launcher updates players' clients automatically. It never updates a dedicated server, so every release means: + +1. Announce maintenance and stop admitting players. +2. Stop the server cleanly. +3. Back up `server.json`, `data/`, any custom resources, the runtime you are about to replace, and the Foundations database. Foundations documents the dump command under [backups and upgrades](https://github.com/hogwarts-mp/foundations/blob/main/DATABASE.md#backups-and-upgrades). +4. Replace the runtime from the new release, and replace the whole Foundations pack as one unit with the release its compatibility matrix names. On Linux the runtime is `HogwartsMPServer`, `crashpad_handler` and `libnode.so.141`; run `chmod +x` on the first two again afterwards. +5. Read the release notes and example configs for new keys. +6. Start the database, then the server, and wait for every resource's ready message. +7. Join once with a client from the same release and test character selection, inventory and your main gameplay loop. + +Keep the previous runtime and the matching database backup until the new build has passed a real connection test. Foundations migrations can be forward-only, so rolling back the server may also mean restoring that backup. + +## Troubleshooting + +| Symptom | Check | +| --- | --- | +| Exits immediately | Read the first error in the log. Confirm the working directory, a writable `logs/`, complete runtime files, and valid JSON. | +| `JSON config could not be applied: … type must be …` | A `server.json` key has the wrong JSON type, such as `"port": "27015"` or `null`. The message names the type, not the key. See [Server configuration](/guides/server-config/#validation). | +| Linux: `version 'GLIBC_2.38' not found` | The distribution is too old. Use Ubuntu 24.04+ or Debian 13+, directly or as a container base. | +| Linux: `libnode.so.141: cannot open shared object file` | Keep the complete Linux bundle together, or start it with `LD_LIBRARY_PATH=/opt/hogwartsmp`. Do not substitute a `libnode` from another release. | +| Linux: exits on a VPS with `Tracy Profiler initialization failure: CPU doesn't support invariant TSC` | The virtual CPU hides a feature the built-in profiler checks for. Start the server with `TRACY_NO_INVARIANT_CHECK=1` in its environment (`Environment=TRACY_NO_INVARIANT_CHECK=1` in the unit). | +| Stops when the terminal closes, or is gone after a reboot | It was started from a shell. Run it under [systemd](#linux-systemd) or a Windows service manager. | +| Every Foundations resource fails after a reboot, but a manual start works | The server raced the database. Add `Requires=` and `After=mysql.service` to the unit. | +| Players cannot connect | Confirm UDP reachability from outside, router forwarding, the address and the port. A TCP port test does not validate UDP. | +| Players connect and are rejected immediately | Client and server come from different releases. Update the server, or have players relaunch so the launcher updates them. | +| Foundations says MySQL is not configured | Install `data/hmp-mysql.json`, or set the `HMP_MYSQL_*` variables in the server's environment. | +| Foundations reports `ECONNREFUSED` | Start MySQL and check its host and port. Inside a container, `127.0.0.1` is the container itself. | +| Foreign-key or migration error | Stop the server and read the earliest Foundations schema error. Do not edit migration history to silence it. | +| A resource depends on a missing resource | The resource set is incomplete or mixes releases. Restore one matching set. | +| Duplicate commands or UI | Overlapping legacy and Foundations resources are both loaded. Keep one owner per system. | +| Not in the server list | Confirm `server-token`, outbound HTTPS, the registration, and the masterlist line in the log. Direct connect keeps working either way. | + +When asking for help, include the release, the operating system, a sanitized `server.json`, the resource list, and the first relevant error from `logs/hogwarts-mp.log`. Remove tokens, passwords, database URLs, player addresses and identity information first. + +## Related + +- [Server configuration](/guides/server-config/): every `server.json` key, command-line overrides, passwords and required mods. +- [Docker and game panels](/guides/docker/): the public server image, Compose, and the Pterodactyl and Pelican egg. +- [Your first resource](/guides/getting-started/): writing your own resources on top of the server. diff --git a/guides/overview.md b/guides/overview.md index 8b5f570..8e52181 100644 --- a/guides/overview.md +++ b/guides/overview.md @@ -1,6 +1,8 @@ --- title: Overview group: Guides +sidebar: + order: 1 --- HogwartsMP resources run JavaScript in one of two environments: @@ -20,6 +22,12 @@ Use the navigation to browse the globals available to the selected environment. - [Events](/guides/events/) — listeners, the client/server bridge, the runtime event catalog, and the trust boundary. +**Running a server:** + +- [Hosting a server](/guides/hosting/) — installing on Windows or Linux, Foundations, ports, the masterlist, and updates. +- [Server configuration](/guides/server-config/) — every `server.json` key, command-line flags, passwords, and required mods. +- [Docker and game panels](/guides/docker/) — the public server image, Compose, and the Pterodactyl and Pelican egg. + ## Server example ```js diff --git a/guides/server-config.md b/guides/server-config.md new file mode 100644 index 0000000..967805a --- /dev/null +++ b/guides/server-config.md @@ -0,0 +1,138 @@ +--- +title: Server configuration +group: Guides +sidebar: + order: 5 +--- + +The server takes its settings from `server.json` in its working directory, and command-line flags can override some of them. This page lists every key and flag. To install a server first, see [Hosting a server](/guides/hosting/). + +## server.json + +On first start, if `server.json` is missing and the directory is writable, the server writes one with every key the build understands, set to its default. That generated file is the authoritative list for your release, so edit it rather than writing one from scratch. + +A complete file, with a password and a custom HTTP port: + +```json +{ + "host": "0.0.0.0", + "port": 27015, + "apihost": "127.0.0.1", + "apiport": 27016, + "map": "", + "maxplayers": 32, + "server-token": "", + "password": "castle-gate", + "mod": { + "curseforge": { + "mods": [] + }, + "autoRespawn": true + } +} +``` + +Every key is optional: one you leave out takes its default. Restart the server after editing the file. + +### Framework keys + +| Key | Default | Meaning | +| --- | --- | --- | +| `host` | `0.0.0.0` | Interface the game socket binds to. `0.0.0.0` accepts players on every interface. | +| `port` | `27015` | Game port (**UDP**). Players connect here. | +| `apihost` | `0.0.0.0` | Interface the [information API](#information-api) binds to. Set `127.0.0.1` to keep it off the network. | +| `apiport` | `27016` | Information API port (**TCP**). | +| `map` | `""` | Reserved. HogwartsMP ignores it; leave it empty. | +| `maxplayers` | `32` | Connection cap. This build allows at most **128**; a higher value logs a warning and runs with 128. | +| `server-token` | `""` | Masterlist key from the [MafiaHub dashboard](https://mafiahub.dev/dashboard/servers). Empty keeps the server unlisted. See [List it publicly](/guides/hosting/#8-list-it-publicly). | +| `password` | `""` | Password players must enter to join. Empty lets anyone in. See [Passwords](#passwords). | + +### Mod keys + +HogwartsMP's own settings live under the `mod` object, so they can never collide with framework keys added later. + +| Key | Default | Meaning | +| --- | --- | --- | +| `curseforge.mods` | `[]` | CurseForge project IDs every connecting player must activate. See [Required CurseForge mods](#required-curseforge-mods). | +| `autoRespawn` | `true` | Whether a dead player respawns on their own after a few seconds. See [Respawning](#respawning). | + +### Validation + +The file is checked at boot, so a mistake stops the server with a reason instead of surfacing at the first connect: + +- **Invalid JSON** stops it with `JSON config load has failed:` and the parser's error. +- **A framework key with the wrong type**, such as `"port": "27015"` or `null`, stops it with `JSON config could not be applied: … type must be number, but is string`. That message names the type, **not the key**, so compare each value against the table above. +- **A `mod` key with the wrong type** stops it with a message that names the key, such as `'mod.autoRespawn' must be a …`. +- **An unknown `mod` key** is kept, with a warning that the build does not understand it. A config written for a newer release still loads on an older one. +- **Unknown top-level keys** are ignored, so documentation keys such as `"_comment"` are harmless. + +The server also rejects a `port` or `apiport` outside 1–65535, a `maxplayers` of zero or less, and a `password` over 255 bytes. + +## Command-line flags + +Flags override the matching `server.json` keys for that run. A flag you do not pass never overrides the file. + +| Flag | Overrides | Purpose | +| --- | --- | --- | +| `-h`, `--host` | `host` | Game bind address | +| `-p`, `--port` | `port` | Game port (UDP) | +| `-H`, `--apihost` | `apihost` | Information API bind address | +| `-P`, `--apiport` | `apiport` | Information API port (TCP) | +| `-t`, `--server-token` | `server-token` | Masterlist key | +| `--password` | `password` | Join password | +| `-c`, `--config` | | Read a different configuration file instead of `server.json` | +| `--help` | | Print the flags and exit | + +For example, to run a second server from another directory on the next pair of ports: + +```sh +./HogwartsMPServer --port 28015 --apiport 28016 +``` + +`maxplayers`, `map` and the `mod` keys have no flags; set them in the file. Game panels use flags to inject the port and token they manage. That is why the [Pterodactyl egg](/guides/docker/#pterodactyl-and-pelican) overrides whatever `server.json` says for those keys. + +> On a shared machine, other users can read a process's command line. Prefer `server.json` for `server-token` and `password` there, and keep that file readable only by the server's account. + +## Passwords + +Set `password` (or pass `--password`) to make players enter it before they are admitted. Players type it into the **Password** field on the **Play** screen, next to the address. You can also send it in a `hogwartsmp://` [join link](/guides/hosting/#7-join-it) as `?password=…`. + +**Keep it to 64 plain ASCII characters or fewer, with no spaces at either end.** The server accepts up to 255 bytes, but the Play screen trims spaces from both ends and sends at most 64 bytes. A password that breaks either rule can never be typed correctly. + +The server reports that a password is required to the masterlist and in its information API. It never reports the password itself. + +## Required CurseForge mods + +`mod.curseforge.mods` lists CurseForge projects every client must activate before entering your server. The list is sent during the connection handshake, and supported clients set up that server's mod set before the world loads. + +The list starts empty, and it should stay empty until you have chosen and tested a mod. An accidental entry affects every player who connects. To require one, add its **numeric project ID** as a string: + +```json +"mod": { + "curseforge": { + "mods": ["YOUR_CURSEFORGE_PROJECT_ID"] + } +} +``` + +That is a fragment of `server.json`, not a complete file, and the placeholder has to be replaced. Several projects are separate strings in the same array. Do not use a URL, project name, slug or file ID, or an ID copied from another server without knowing what it installs. Set the array back to `[]` to require nothing. + +## Respawning + +With `mod.autoRespawn` at its default of `true`, a dead player stands back up on their own a few seconds after dying. Set it to `false` and a dead player stays where they fell, still watching the world, until a script respawns them with `player.respawn()`. Game modes with revives, spectating or round-based play use this. + +Scripts can override it for one player with `player.setAutoRespawn(on)`. Passing `null` restores the `server.json` value. See the Server API reference. + +## Information API + +The server answers `GET /` on `apiport` with a JSON summary: `mod_name`, `mod_slug`, `mod_version`, `framework_version`, `host`, `port`, `password_required`, `max_players` and `mod_config`. It is handy for a quick health check from the host itself: + +```sh +curl http://127.0.0.1:27016/ +``` + +Players do not need it to join, and the masterlist does not read it: the server announces itself. It binds every interface by default, so either block its port at the firewall or set `apihost` to `127.0.0.1`. + +## Changing ports + +Moving the game port means changing three things together: `port` (or `--port`), the firewall or router rule, and any container port mapping. Then tell players the new port, because the client assumes 27015 unless the address carries `:port`. When you run several servers on one machine, give each its own directory and its own pair of `port` and `apiport`.