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).