Skip to main content

Overview

LiquidBounce provides a rich set of value types for creating module and feature settings. All values support serialization, change listeners, conditional visibility, and translation keys. Package: net.ccbluex.liquidbounce.config.types

Base Value Class

open class Value<T : Any>(
    val name: String,
    val aliases: List<String> = emptyList(),
    private var defaultValue: T,
    val valueType: ValueType,
    var independentDescription: Boolean = false
)
name
String
required
Value name for display and serialization
aliases
List<String>
default:"emptyList()"
Alternative names for migration support
defaultValue
T
required
Default value
valueType
ValueType
required
Type information for serialization

Common Value Types

Boolean Value

val enabled by boolean("Enabled", true)
Creates a checkbox setting. Signature:
fun boolean(name: String, default: Boolean): BooleanValue

Integer Value

val count by int("Count", 10, 1..100)
Creates an integer slider. Signature:
fun int(name: String, default: Int, range: IntRange): IntValue

Float Value

val speed by float("Speed", 1.0f, 0.1f..5.0f)
Creates a decimal slider. Signature:
fun float(name: String, default: Float, range: ClosedFloatingPointRange<Float>): FloatValue

Ranged Value

val range by floatRange("Range", 3.0f..5.0f, 0.0f..10.0f)
Creates a min-max range slider. Signature:
fun floatRange(
    name: String,
    default: ClosedFloatingPointRange<Float>,
    range: ClosedFloatingPointRange<Float>
): RangedValue<Float>

Text Value

val message by text("Message", "Hello World")
Creates a text input field. Signature:
fun text(name: String, default: String): TextValue

Choice Value

val mode by choices("Mode", arrayOf("Fast", "Slow", "Medium"), "Fast")
Creates a dropdown selection. Signature:
fun choices(name: String, choices: Array<String>, default: String): ChoiceValue

List Value

val blocks by listValue("Blocks", mutableListOf<Block>())
Manages a list of items. Signature:
fun <T> listValue(name: String, default: MutableList<T>): ListValue<T>

Curve Value

val curve by curve("Curve", arrayOf(
    Point(0.0, 0.0),
    Point(1.0, 1.0)
))
Creates a bezier curve editor. Signature:
fun curve(name: String, default: Array<Point>): CurveValue

Block Value

val targetBlock by block("Block", Blocks.STONE)
Block selection dropdown. Signature:
fun block(name: String, default: Block): BlockValue

Color Value

val color by color("Color", Color4b(255, 0, 0, 255))
RGBA color picker. Signature:
fun color(name: String, default: Color4b): ColorValue

Bind Value

val keybind by bind("Key", InputBind(
    type = InputConstants.Type.KEYSYM,
    value = GLFW.GLFW_KEY_R,
    action = InputBind.BindAction.TOGGLE
))
Keybind configuration. Signature:
fun bind(name: String, default: InputBind): BindValue

Mode Values (Choice Groups)

private val modes = choices("Mode",
    ModeA,
    ModeB,
    ModeC
)

object ModeA : ChoiceConfigurable(this, "ModeA") {
    val speed by float("Speed", 1.0f, 0.1f..5.0f)
    val ticks by int("Ticks", 20, 1..100)
}

object ModeB : ChoiceConfigurable(this, "ModeB") {
    val power by float("Power", 2.0f, 0.1f..10.0f)
}
Each mode can have its own settings that only appear when selected. Signature:
fun choices(name: String, vararg choices: ChoiceConfigurable): ModeValue

Value Modifiers

Conditional Visibility

val enabled by boolean("Enabled", true)
val speed by float("Speed", 1.0f, 0.1f..5.0f)
    .listen { enabled } // Only visible when enabled is true

Change Listeners

val mode by choices("Mode", modes, "Fast")
    .onChange { newValue ->
        // React to value change
        println("Mode changed to: $newValue")
        newValue // Must return value
    }

Changed Listeners

val range by float("Range", 3.0f, 1.0f..6.0f)
    .onChanged { newValue ->
        // Called after value changed
        updateRangeDisplay(newValue)
    }

Not An Option

val internal by boolean("Internal", true)
    .notAnOption() // Hidden from REST API

Do Not Include

val temporary by text("Temp", "")
    .doNotIncludeAlways() // Never saved to config

Immutable

val constant by int("Version", 1)
    .immutable() // Cannot be changed

Advanced Value Types

Vec3 Value

val position by vec3("Position", Vec3(0.0, 64.0, 0.0))
Three-dimensional vector (X, Y, Z).

File Value

val configFile by file("Config", File("config.json"))
File path selector.

Multi-Choice List

val blocks by multiChoice("Blocks", mutableListOf("Stone", "Dirt"))
Multiple selection from list.

Value Groups

Tree Structure

object MyModule : ClientModule(...) {
    val tree by tree("Advanced") {
        val option1 by boolean("Option1", true)
        val option2 by float("Option2", 1.0f, 0.1f..5.0f)
    }
}
Collapsible setting groups.

Toggleable Group

val autoBlock by toggleable("AutoBlock", false) {
    val blockDelay by int("Delay", 50, 0..500)
    val onlyWhileSprinting by boolean("OnlyWhileSprinting", false)
}
Group with enable/disable toggle.

Usage Examples

Complete Module Settings

object ModuleKillAura : ClientModule(
    name = "KillAura",
    category = ModuleCategories.COMBAT
) {
    // Range settings
    val range by floatRange("Range", 3.0f..4.2f, 1.0f..6.0f)
    
    // Target selection
    val priority by choices("Priority", 
        arrayOf("Distance", "Health", "Direction", "Armor"),
        "Distance"
    )
    
    // Attack settings
    val maxCPS by int("MaxCPS", 12, 1..20)
    val minCPS by int("MinCPS", 8, 1..20)
        .listen { it <= maxCPS }
    
    // Rotation settings  
    val rotations by toggleable("Rotations", true) {
        val speed by float("Speed", 2.0f, 0.1f..180.0f)
        val smoothing by boolean("Smoothing", true)
    }
    
    // Mode selection with sub-settings
    private val modes = choices("Mode", Single, Multi)
    
    object Single : ChoiceConfigurable(this, "Single") {
        val switchDelay by int("SwitchDelay", 15, 1..40)
    }
    
    object Multi : ChoiceConfigurable(this, "Multi") {
        val maxTargets by int("MaxTargets", 3, 1..10)
    }
}

Dynamic Value Visibility

val useCustomSpeed by boolean("UseCustomSpeed", false)
val customSpeed by float("CustomSpeed", 1.0f, 0.1f..5.0f)
    .listen { useCustomSpeed } // Only show when enabled

val mode by choices("Mode", arrayOf("Fast", "Slow"), "Fast")
val fastModeBoost by float("Boost", 2.0f, 1.0f..5.0f)
    .listen { mode == "Fast" } // Only for Fast mode

Value Change Reactions

val autoRespawn by boolean("AutoRespawn", true)
    .onChanged { enabled ->
        if (enabled && player.health <= 0) {
            player.respawn()
        }
    }

val theme by choices("Theme", arrayOf("Dark", "Light"), "Dark")
    .onChange { newTheme ->
        applyTheme(newTheme)
        newTheme
    }

Best Practices

  1. Use descriptive names - Value names appear in UI
  2. Set reasonable ranges - Prevent invalid values
  3. Add change listeners - React to setting changes
  4. Group related settings - Use trees and toggleables
  5. Use modes for variants - Different strategies/algorithms
  6. Validate dependencies - Use listen for conditional visibility
  7. Provide defaults - Sensible default values
  8. Add aliases for migration - Support config updates

See Also

Build docs developers (and LLMs) love