Repository navigation
Architecture
Pavel Erokhin edited this page Oct 19, 2026
·
1 revision
WorldAPI is a Kotlin plugin for Paper. A Ktor server answers HTTP and the WebSocket next to the game, and everything that touches Bukkit runs on the server thread.
| Path | What it does |
|---|---|
WorldApiPlugin.kt, core/
|
Startup and shutdown; MainThread.kt runs Bukkit calls on the server thread, with a timeout |
config/ |
config.yml through kaml in strict mode; an unknown key is an error, not a silent default |
api/ |
The Ktor server, the endpoint DSL, auth, permissions and groups (Scope.kt), rate limits, trusted proxies, the HTTPS warning (Exposure.kt), and the OpenAPI generator |
routes/ |
One file per area; each endpoint declares its permission, so the router and docs/openapi.json come from the same list |
files/ |
/files: which paths may be read or written (ServerFiles), paged and grep reads, writes with backups, and key edits in YAML, .properties, and JSON |
events/ |
Every topic and its privacy (Topic.kt), listeners, the sampler for state topics, snapshots, and Visibility, which strips what visitors mustn't see |
ws/ |
The WebSocket hub: per-client outboxes; state topics coalesce, event topics drop the oldest |
stats/ |
Statistics from live players and the stats files, leaderboards, aggregates |
store/ |
Event history, sessions, audit log, experience: Exposed over HikariCP on SQLite, PostgreSQL, or MySQL/MariaDB. Writes queue on one thread; reads wait for the writes queued before them |
extensions/ |
The bridge other plugins call (see Extensions) |
plan/ |
The section on Plan's pages; its classes load only when Plan is enabled |
tokens/, command/
|
Issued tokens (stored as SHA-256), the in-game menus, /worldapi
|
script/ |
Java scripts: compiled by the bundled ECJ, loaded by a filtered class loader, checked against blocked calls |
admin/ |
The admin panel: a React app built with Bun into the jar, served at /admin, with its sign-in and accounts in admin/*.kt
|
- Bukkit calls happen on the server thread through
MainThread; IO, the database, and the network never do. A request that waits too long for the thread gets503before it touches the world. - Visitors never get coordinates, inventories, addresses, or chat. A new topic or field declares its privacy, and
Visibilitystrips it. - Vanished players look offline to every client without
players:moderate. - One endpoint list feeds both the router and the OpenAPI document, and a test fails when the committed
docs/openapi.jsonfalls behind. - The extension bridge is a contract other plugins compile against without WorldAPI's classes: plain Java types in, maps out, and a version on every request.
-
paper-plugin.yml, because WorldAPI is Paper-only and gets an isolated class loader and Brigadier commands. - Dependencies are shaded and relocated under
com.mairwunnx.worldapi.libs, so the jar works offline and can't clash with FAWE, BlueMap, Plan, or TAB. - ECJ stays unrelocated, because it finds its message bundles by package name.
- The SQLite driver comes from Paper; the PostgreSQL and MariaDB drivers are named through class references, so the relocation holds.
Next: Development.