Quorix Server

This is the QuorixServer BlueJ project — built and shipped as QuorixServer.jar (Main-Class: ServerMain). Headless: no GUI, no client code at all. Runs unattended on a real machine (a cloud VM with no display included, or just a spare PC left on) rather than opening a login window.

This folder is a partial synced copy, not where edits happen. QuorixClient/ is the edit source of truth for anything genuinely shared (networking, game rule engines, account/economy/social data) — change it there first, then copy the changed file here too, and diff the two to confirm they still match. If you're changing UI-only code (a page, a dialog, a theme, a game's Window class), it only exists in QuorixClient/ — there's nothing to copy here. See QuorixClient/README.md's "Keeping the two projects in sync" section for the full rule and why it matters (it's already caused one real bug).

For what Quorix actually is and how the whole platform fits together, start at the root README.md or, for a no-coding-required explanation, HOW_QUORIX_WORKS.md. This file is specifically about this folder.

Why this folder only has ~140 files

ServerMain doesn't open any client UI — it just starts net.GameServer and blocks the main thread forever (the accept loop itself runs on a daemon thread). Its real dependency set — networking, game rule engines and match managers, and the account/economy/social data layer; no ui, theme, or pages package, no game Window/Dialog classes, no practice-mode AI — was found mechanically: compile just ServerMain.java with -sourcepath pointing at the full QuorixClient/ tree and keep whatever the compiler actually pulls in, rather than guessing.

How to run it

Without BlueJ:

java -jar QuorixServer.jar

Prints Quorix server listening on port 7777 to the console — no window opens. Connect to it from a QuorixClient.jar (or another QuorixServer.jar's "Connect to a Server" option) to actually log in and play.

With BlueJ: open this folder as a project, compile all classes, right-click ServerMain → void main(String[] args) → leave the argument blank.

First run: create the administrator. If no admin exists yet, the server asks for an admin username and password at its console before it accepts anyone (type them there — never share them in a chat). For an unattended start, set QUORIX_ADMIN_USER and QUORIX_ADMIN_PASSWORD instead. With neither, the server still starts but has no admin and says so loudly; restart it from a terminal to set one up. Signing up in the game never makes anyone an admin.

Running it on a VM (unattended)

Everything below lives in the folder the jar runs from (say /home/opc/quorix).

Keep it running, and restart it for updates. A systemd service with Restart=always is what makes self-update work: the server exits after installing a new version and systemd starts the new one.

# /etc/systemd/system/quorix.service
[Unit]
Description=Quorix game server
After=network-online.target

[Service]
User=opc
WorkingDirectory=/home/opc/quorix
ExecStart=/usr/bin/java -Xmx400m -jar QuorixServer.jar
Restart=always
RestartSec=5
# first run only (creates the admin); afterwards these lines can be removed
# Environment=QUORIX_ADMIN_USER=...  Environment=QUORIX_ADMIN_PASSWORD=...

[Install]
WantedBy=multi-user.target

Then sudo systemctl enable --now quorix.

Self-update (on by default). Every 2 days the server asks the repository's latest GitHub Release for QuorixServer.jar and Quorix.jar, downloads whichever differ (checked against the release's SHA256SUMS) into incoming/, and installs them only after the server has been idle for 20 minutes (nobody has sent anything). It tells anyone still connected ("Server is updating"), swaps the files (the old server jar is kept as QuorixServer.jar.prev), exits, and shows "Server is back" for 10 minutes after the restart. Publish a release from the repository's Actions tab: Windows app -> Run workflow -> release_tag (for example v1.0.1). To roll back: stop the service, copy QuorixServer.jar.prev over QuorixServer.jar, start it, and set QUORIX_AUTO_UPDATE=off until you have published a fixed release. Settings (environment variables): QUORIX_AUTO_UPDATE=off, QUORIX_UPDATE_HOURS (48), QUORIX_IDLE_MINUTES (20), QUORIX_UPDATE_REPO (King12Minecraft/Quorix). This installs whatever the release's owner publishes; the hash check catches a damaged download, not a stolen GitHub login, so protect that account (two-step sign-in).

Daily backup (on by default). Once a day the server zips every data file (gamehub_* and notice.txt) into backups/, keeping the newest 3 (QUORIX_BACKUP_HOURS, QUORIX_BACKUP_KEEP, QUORIX_BACKUP=off). To restore: stop the service, unzip the chosen backup over the folder, start it. A normal stop (systemctl restart quorix) first tells everyone connected "The server is restarting"; the app reconnects by itself.

Chat filter (always on). Blocked words in anything players write for each other (private, group and match chat, forum posts, caption answers, Telephone captions, group names) are masked with asterisks on the server, quietly. Staff chat, reports and feedback keep the exact words. Sign-up and rename refuse a name with a blocked word. To add your own words, put one per line in blocked-words.txt next to the jar and restart.

A notice for everybody ("taken down for a reason"). Write it in notice.txt next to the jar:

echo "Down for exam week - back on Monday" > notice.txt      # shows in the app and on the website within ~10 seconds
echo "INFO: Tournament on Friday at 4" > notice.txt          # a calmer, blue banner
rm notice.txt                                                  # banner goes away

It stays up for as long as the file has text, including while the server is stopped (see the next paragraph).

Status file for the website and the app. The server writes public/status.json every 15 seconds (and when it stops) with its state (online, updating or down), players online, build id and the current notice. Serve that folder as plain files so it still answers when the game server is off, for example with Caddy on port 80/443:

:80 {
    root * /home/opc/quorix/public
    header Access-Control-Allow-Origin *
    file_server
}

(open ports 80 and 443 in the Oracle security list and in firewalld, as for 7777.) The app, when it cannot reach the game server, reads http://<server>/status.json to say why; the website reads it when status_url in website/site_config.json is set to its public address. QUORIX_STATUS_DIR changes the folder.

Security

Passwords are salted + hashed (never stored in plain text), there are no hardcoded credentials, repeated failed logins lock an account out, and every privileged action re-checks the requester's role server-side rather than trusting what the client claims. Deserialization off the raw socket is allow-list filtered (net.QuorixSerializationFilter) rather than accepting any class a peer sends. Known, open gaps (tracked in BLOCKED_QUESTIONS.md, not silently ignored): no TLS yet (LAN-only for now, by design), and the client auto-update mechanism has no code signing.

THE Economy Config — economy/EconomyConfig.java

The one file to edit to change Quorix's entire economy: win rewards, practice-mode score-to-coin formulas, the daily login streak curve, challenge/quest definitions, shop items. Every number that affects how many coins something pays lives here, not scattered across individual game files.

Development history

DEVELOPMENT_LOG.md is this folder's old README — a chronological, append-only log of what was built each round going back to the start of the project. Useful for the reasoning behind old decisions; not current documentation (this file, and the ones linked above, are).

Source: QuorixServer/README.md on GitHub