Linking your plugin to the GDK
The GDK lives in its own plugin (UHCGDK). Your themed game mode lives in a separate Spigot plugin that depends on the GDK at runtime, declares one or more UHCGameModule implementations, and registers them with the GDK registry on enable. The pattern is intentionally minimal: your plugin owns its own lifecycle, commands and listeners, and only reaches into the GDK to publish its module.
Plugin descriptor (plugin.yml)
Section titled “Plugin descriptor (plugin.yml)”Declare the GDK as a hard dependency so the server loads it before your plugin and refuses to enable yours if the GDK is missing.
name: MyUHCmain: fr.example.myuhc.MyMainversion: 1.0.0api-version: 1.8
depend: - UHCGDKDeclaring a module
Section titled “Declaring a module”Subclass UHCGameModule and override the abstract members. The framework only looks at the signatures listed below; everything else is opt-in.
package fr.example.myuhc
import fr.noradrenalin.gdk.module.EliminationDecisionimport fr.noradrenalin.gdk.module.GameContextimport fr.noradrenalin.gdk.module.UHCGameModuleimport fr.noradrenalin.gdk.module.VictoryResultimport fr.noradrenalin.gdk.utils.GDKItemsimport net.md_5.bungee.api.ChatColorimport org.bukkit.Materialimport org.bukkit.entity.Playerimport org.bukkit.inventory.ItemStack
class MyUHCModule : UHCGameModule() { override fun name(): String = "${ChatColor.WHITE}My ${ChatColor.AQUA}UHC"
override fun description(): String = "An example mode where the last player standing wins."
override fun symbolItem(): ItemStack = GDKItems.Builder(Material.DIAMOND_SWORD, 1, name()).build()
override fun onPlayerDeath(player: Player, context: GameContext): EliminationDecision = EliminationDecision.Eliminate
override fun evaluateVictory(context: GameContext): VictoryResult { val active = context.activePlayers() return if (active.size == 1) VictoryResult.SingleWinner(active.first()) else VictoryResult.NoWinnerYet }}The five abstract members are the contract every module must satisfy:
| Method | Purpose |
|---|---|
name() / description() | Display strings for the host’s mode-selection panel and module logs. |
symbolItem() | The ItemStack shown in the mode-selection inventory. |
onPlayerDeath(player, context) | Called when an active player dies. Returns the elimination decision (see the dedicated page). |
evaluateVictory(context) | Called once per second while a game is in progress. Returns a VictoryResult to end the game, or VictoryResult.NoWinnerYet to continue. |
Everything else (onGameStart, onGameFinish, canStart, role/team registration, configuration panels, scoreboard extras) ships with sensible defaults. Override them when you need them.
Registering the module
Section titled “Registering the module”In your plugin’s onEnable(), retrieve the running GDKMain instance and publish your module to its registry. Optionally declare it as the active module so the server boots into it.
package fr.example.myuhc
import fr.noradrenalin.gdk.GDKMainimport org.bukkit.plugin.java.JavaPlugin
class MyMain : JavaPlugin() {
override fun onEnable() { super.onEnable()
val gdk = GDKMain.getInstance().orElseThrow { NoSuchElementException( "UHCGDK plugin is not loaded. Install it before enabling MyUHC.", ) }
val module = MyUHCModule() gdk.gdkGamesRegistry.registerModule(module)
// Optional: declare your module as the one that will run the next game. // If you skip this step, hosts switch to it from the in-game configuration // dashboard like any other registered module. gdk.gdkGamesRegistry.setActiveModule(module) }}GDKRegistry.registerModule throws GDKUHCModuleAlreadyExistsException if a module with the same name() is already registered. Module identity is derived from name() (via equals / hashCode), so two modules with identical display names collide.
setActiveModule refuses to switch the active module while a game is in progress. Hosts may also pick a different module from the in-game dashboard at any time during the waiting phase, which calls the same method internally.
What the GDK does for you
Section titled “What the GDK does for you”Once your module is registered and the host triggers a start, the GDK takes over the heavy lifting:
- Generates the game world (or reuses the existing one), spreads players across it, and applies the configured world border.
- Resets every active player’s inventory, max health, hunger and statistics, then distributes the configured starter inventory.
- Schedules the PvP enable, the invulnerability fade, the cyclic episode broadcasts, and the day / night cycle events.
- Calls your module’s
onGameStart(context), then drivesonPlayerDeathper death andevaluateVictoryonce a second. - Fires UHC-level events (
UHCGameStartedEvent,UHCPlayerDeathEvent,UHCDayStartEvent, etc.) that any listener (your module, your roles, scenario plugins) can subscribe to. - Calls
onGameFinish(context), broadcasts the victory and kill leaderboard, and tears down per-game listeners and timers.
You only write the parts that are specific to your mode. The next pages walk through each extension point in order of growing complexity.