Covers quick start, the two web UIs, non-Docker build instructions, repo layout, and the two Windows-porting gotchas (clock() semantics, DB string widths) most likely to bite future changes.
ROSS
A ROSE Online (KTRose, pre-evo era) private server emulator, ported from its original Windows/MSVC codebase to build and run natively on Linux, packaged as a Docker Compose stack.
Three C++ servers (login, character, world) talk to a MariaDB database and to each other over plain sockets, exactly like
the original 2007-era server did — just with the Windows-only bits (MSVC CRT calls, clock() semantics, path handling)
shimmed out so it builds and runs correctly under Linux/glibc/POSIX threads.
Quick start
cp .env.example .env # edit PUBLIC_HOST at minimum if clients connect from another machine
docker compose up -d --build
That brings up:
| Service | Container | Port | What it is |
|---|---|---|---|
db |
ross-db-1 |
— (internal) | MariaDB, schema auto-loaded from database sql files/ on first start |
loginserver |
ross-loginserver-1 |
29000 |
Account login |
charserver |
ross-charserver-1 |
29100 |
Character select/create/delete |
worldserver |
ross-worldserver-1 |
29200 |
The actual game world |
webtools |
ross-webtools-1 |
80 |
Static GM toolbox (see below) + reverse-proxies /admin/ |
webadmin |
ross-webadmin-1 |
— (behind webtools) | Account/character/server admin panel |
Point a KTRose pre-evo client at PUBLIC_HOST:29000 and log in — LOGIN_CREATE_ACCOUNT=1 (the default) auto-creates an
account on first login with that username/password.
Web tools — http://<host>/
A static, no-build-step GM toolbox, generated from the same STB/DB data the server itself reads:
- GM Commands — every
/commandgmcmds.cppunderstands, with syntax, access-level, and a copy button. - Item Configurator — browse all ~9,950 items, configure refine/count/etc., copy the exact
/itemor/give2command. - Maps — every map with spawn/NPC activity, named from
LIST_ZONE.STB(row index = map id, same as the server's ownCWorldServer::LoadZoneData). - NPCs — every placed NPC (
list_npcs) with coordinates; click to copy a/tele <map> <x> <y>. - Monsters — all 1,193 named monster types from
LIST_NPC.STB; click to copy a/mon <montype> <count> <ai>.
Web admin — http://<host>/admin/
Logs in with an existing game account — only accounts with accesslevel >= ADMIN_MIN_ACCESSLEVEL (default 900) get
in. From there:
- Browse/edit/delete accounts and characters, reset stats, grant GM/DEV, reset a stuck "online" flag.
- Server tab: start/stop/restart each of the three game servers, live-tail their logs (SSE), broadcast a message to everyone online, or kick a character — all straight from the browser.
The server-control features talk to the Docker API (/var/run/docker.sock, mounted read-only into webadmin), so this
panel effectively has host-level privileges. It's fine behind GM-only login on a machine you control; don't put it
directly on the public internet without a reverse proxy that adds another auth layer.
Building without Docker
apt-get install cmake g++ make libmariadb-dev pkg-config
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j"$(nproc)"
Produces build/loginserver, build/charserver, build/worldserver. Each expects a .conf file as its only argument
(see docker/conf/*.conf.tmpl for the format, or Binary/*.conf for a filled-in example) and reads game data relative
to its working directory — run it from a directory containing 3DData/ (see below) and clanmark/.
Repo layout
Src/— the three servers' C++ source, plusSrc/Common/(shared networking/DB/crypto code all three link against).database sql files/— MariaDB schema, loaded automatically into a freshdbcontainer.Binary/3DData/— the subset of the original game's data files the server actually reads at runtime: item/skill/ quest/zone definitions (STB/), quest scripts (QUESTDATA/), monster AI scripts (AI/). This is not the client's 3D models/textures/sound — the server never touches those, so they aren't in this repo.webtools/,webadmin/— the two web UIs described above.docker/— Dockerfile support files: config templates, entrypoint script, the webtools nginx config.tools/rose_login_test.cpp— a standalone protocol-level login smoke test, linking against the server's ownrosecrypt.cppso it exercises the real crypto/handshake instead of a reimplementation.
Notes for anyone touching the server code
This codebase was written entirely against Windows/MSVC assumptions that don't hold on Linux. The two that will bite you if you're not aware of them:
clock(): POSIXclock()returns CPU time summed across every thread in the process, not wall-clock time, and ticks atCLOCKS_PER_SEC == 1,000,000instead of Windows'1,000.Src/Common/sockets.h#definesclock()to aCLOCK_MONOTONIC-backed wall-clock millisecond counter for the whole codebase — don't remove that shim, and don't callclock()expecting Windows semantics anywhere it might not apply.- DB string widths: this server was built against MySQL 5.0, which silently truncated over-length strings instead of rejecting them. MariaDB's default strict mode does not — if you add a new DB-backed field that stores a server-generated string (timestamps, etc.), size the column generously.