Skip to content

Settings

class LaserTagGame : SettingsGameTemplate() {
override fun supportsTeamSelection(): Boolean = true
override fun supportsTeamBasedVoting(): Boolean = supportsTeamSelection()
override fun onSettingsFinalized() {
gameRuntime.platform.logger().info("Settings finalized: $config")
}
}

Use GameTemplate for fixed-rule games. Use SettingsGameTemplate when the game should participate in the settings flow before setup.

Define settings in a property named dialogSettings so the binder can discover it:

@Suppress("unused")
private val dialogSettings by lazy {
dialogSettings {
config {
factory { LaserTagConfig.from(it) }
option("game_mode", "Deathmatch", "Team Deathmatch", "Gun Game") {
label = "<gold>Game Mode"
default = "Deathmatch"
}
toggle("double_jump", default = true) {
label = "<yellow>Double Jump"
runtime = true
}
intSlider("respawn_seconds", default = 5, min = 2, max = 12, step = 1) {
label = "<aqua>Respawn Time"
format = "%s: %s seconds"
runtime = true
}
text("arena_seed", default = "", maxLength = 32) {
label = "<gray>Arena Seed"
placeholder = "<dark_gray>Optional"
}
}
}
}

Available shapes:

DSLStored typeGood for
toggle"Enabled" / "Disabled"Boolean feature flags.
optionString optionModes, maps, item pools, finite choices.
floatSliderFloat stringTunable rates and multipliers.
intSliderInt-like stringCounts, timers, lives, limits.
doubleSliderDouble stringPrecision tuning.
sliderFloat descriptorAd-hoc slider fully configured in block.
textStringSeeds, labels, short prompts.

Convenience builders include intChoices, durationMinutes, intervalChoices, durationOrNever, enabledDisabled, yesNo, and secondsSlider.

The factory turns the current string map into your own typed data class:

data class LaserTagConfig(
val doubleJumpEnabled: Boolean,
val respawnSeconds: Int,
) {
companion object {
fun from(game: SettingsGameTemplate) =
LaserTagConfig(
doubleJumpEnabled = game.settingBool("double_jump", default = true),
respawnSeconds = game.settingInt("respawn_seconds", default = 5),
)
}
}
private val config: LaserTagConfig
get() = gameConfig()

gameConfig() caches the result and invalidates when runtime settings change.

Settings descriptors parse and serialize values consistently. Presets can use raw keys or descriptors:

private val dialogSettings by lazy {
dialogSettings {
config {
val lives = intSlider("lives", default = 3, min = 1, max = 10) {
label = "<red>Lives"
}
factory { BattleConfig.from(it) }
}
presets {
preset("quick", "<green>Quick") {
"lives"(1)
}
}
}
}

Mark a setting runtime = true if the leader may change it during the match:

override fun onRuntimeSettingChanged(
name: String,
oldValue: String,
newValue: String,
by: GamePlayer?,
) {
if (name == "double_jump") {
reconfigureDoubleJump()
}
}

updateRuntimeSetting(player, name, newValue) checks that the setting exists, the value is valid, the player is allowed, and the value changed. By default only the leader may update runtime settings.

Team helpers are built into SettingsGameTemplate:

supportsTeamSelection()
getTeams()
playersInTeams()
isTeamBasedVoting()
getPlayerTeam(player)
getPlayerTeamIndex(player)

Use them for friendly-fire checks, team scoring, spawn assignment, and team-based voting behavior.