A heavily DSL-based minigame library for Paper and Spigot, allowing you to scope chapters of your game (such as countdown, active round, between rounds, end game) into eventScope {} blocks.
The ethos of this library is to reduce heavy reliance on state, ease data movement between game modules, and to reduce cleanup code - events, scheduled tasks and coroutines are all cancelled when you leave or cancel an eventScope.
All chapters of a game (such as a countdown, active game, between rounds, end game etc.) should be scoped using an eventScope {}.
Within the event scope, you can use listen<Event> {} and listenOnly<Event> {} to listen to Bukkit events within the scope.
By calling eventScope {} within an eventScope, you create a child eventScope forming a hierarchical relationship.
Child eventScopes are bound to the parent, therefore if the parent eventScope is cancelled, the child eventScope will be cancelled too.
When an eventScope is cancelled, any child eventScopes running will also be cancelled.
For all cancelled eventScopes, listeners will be deregistered, scheduled Bukkit tasks will be cancelled, and coroutines will be stopped immediately.
To cancel an eventScope, call cancelScope() from within itself.
Within an event scope, you can use launchTask(delay) { task -> ... } and launchRepeating(delay, interval) { task -> ... } which wrap Bukkit scheduler functions for launching a task later, and a repeating task respectively.
The Bukkit task object is passed in as the argument task, which allows you to cancel the task from within itself, especially useful in a repeating task if you hit a certain condition (such as run x times).
Once the
eventScopeis exited or cancelled, all Bukkit tasks created within theeventScopeand childeventScopes are cancelled.
Although wrappers are provided for Bukkit schedulers, you may still decide to launch coroutines to run asynchronous code.
launchInScope {} provides the same functionality as Kotlin's launch {}, but will cancel the created coroutine if the parent eventScope is cancelled.
For a full example game, check out src/main/kotlin/dev/mqlvin/papergames/impl/quake/Quake.kt.
In 150 lines of logic, this demonstrates a polished Quake game involving:
- The main
Gamefunction eventScopes and childeventScopes- Event listeners, and common listeners such as
listenAll(NoBuild, NoPvp) - A pregame countdown
- Win logic for first to 10 kills or 120s elapsed (+ countdown) or players disconnect leaving 1 alive
- Async animations using Bukkit tasks (railgun reload, invincibility)