Local development stack
Everything runs in Docker, from dev/: PostgreSQL, Redis, server-service, Velocity 4.3.1 and Paper 26.3 with the GrayCore
plugins mounted from target/. Connect with a Minecraft client to localhost:25565.
Quick start
cd dev
./dev.sh up # Windows: .\dev.ps1 up (builds with Maven, then starts the stack)
./dev.sh logs paper # follow a service
Requirements: Docker, JDK 25 and Maven (the plugins are built on the host).
| Command | What it does |
|---|---|
up | Build, then start Velocity and one Paper server (dev-gens-1). |
multi | Same, plus a second Paper server (dev-gens-2) to test server switching, player locks and crashes. |
reload | Rebuild and restart Velocity and Paper to pick up new plugin jars. |
psql | Open a SQL shell on the dev database. |
console <service> <command> | Type a command in a server console, e.g. ./dev.sh console paper op YourName. |
sample | Rebuild only the RPG sample and restart only the first Paper, which is much faster than reload when only the sample changed (the proxy is not restarted: players have to reconnect to the server). |
world | Put the world of DEV_WORLD in place of the Paper servers' world (the old one is kept as world-backup) and start Paper again. |
logs [service] | Follow the logs. |
reset | Stop everything and wipe dev/data/ (the database is recreated by Liquibase on the next start). |
Layout
docker-compose.yml: the stack. Every value has a working default; copy.env.exampleto.envto override.config/: committed templates, copied into the servers on first start (edits made indata/are never overwritten).${CFG_*}placeholders are filled from the compose environment.data/: git-ignored persistent data (PostgreSQL, Redis, Paper and Velocity folders).
| Service | What it is |
|---|---|
velocity | The proxy, the only one exposed (localhost:25565). |
paper, paper-2 | The game servers dev-gens-1 and dev-gens-2 (the second with multi). |
server-service | The registry of game servers. |
postgres, redis | The shared storage. |
resource-packs | Serves the resource packs published by the RPG sample on localhost:8088. |
Testing on a real map
Set DEV_WORLD to a world folder (one with level.dat), in dev/.env or in the environment. up and multi copy it into
data/<server>/world when a server has no world yet, and ./dev.sh world replaces the existing one. The copy is made once:
changes you make in the dev world do not go back to the source folder.
Browsing the world: BlueMap
BlueMap runs on the first Paper server and draws the world in 3D, with the players moving on
it, at http://localhost:8100. Its settings are in config/paper/plugins/BlueMap/core.conf (it accepts the download of the
Minecraft client files it needs, and renders with 6 threads). Nothing is drawn until you ask:
./dev.sh console paper bluemap update world # the first render of a big map takes minutes; `bluemap` shows the progress
After that, BlueMap keeps the map up to date with the changes made in the world.
Zones for the dev map
The templates in config/paper/plugins/ hold the zones of the RPG sample for the map
used in DEV_WORLD (mmo_rpg_world), in the module's zones.yml, and their markers for BlueMap (BlueMap/maps/world.conf), so a
reset does not lose them. They are built from the world's own data by dev/tools/map-zones:
cd dev/tools/map-zones && npm install
npm run build # scan the world, cut the land between the level tiers, write both templates
WORLD_DIR names another world folder (the world of the first Paper server by default). The tiers, their towns, levels and mobs
are at the top of zones.mjs and regions.mjs. A server copies a template into data/ only when it is newer than the file there. After a build, delete
data/paper/plugins/GrayCorePaper/modules/rpg-sample/zones.yml and data/paper/plugins/BlueMap/maps/world.conf, then restart the
servers. Do not overwrite them from the host instead: the server then fails to start, with Operation not permitted.
Admin and debug mode
The admin group (every plugin permission, including graycore.commands.debug) is created the first time a Paper server
starts. Give it to yourself from the console, then use the commands in game:
./dev.sh console paper grayperms player add-group YourName admin
/debug on then shows how your profile is loaded and saved, and which servers the proxy considered when routing you. See
Administration.
Notes
- The console helper runs
mc-send-to-consoleas user 1000, as the image requires:docker compose exec paper mc-send-to-console ...without-u 1000fails with "Exec needs to be run with user ID 1000". - Velocity runs in online mode: you need a real Minecraft account. Only Velocity is exposed, not the game servers.
- Third-party plugins (FastAsyncWorldEdit, WorldGuard, PlaceholderAPI, TAB, BetterModel, BlueMap) are downloaded from Modrinth when a server starts. FastAsyncWorldEdit and WorldGuard are pinned to versions that work together: a newer pair once stopped WorldGuard, and GrayCorePaper with it. Move both at once, and check a server starts.
- Paper and Velocity register through
server-service: there are no static servers invelocity.toml. ./dev.sh psql, thenselect name, lock, lock_expires_at from players;, shows which server owns which player.