Skip to main content

Overview

The Parameter system provides type-safe command arguments with validation, auto-completion, and flexible configuration. Parameters can be required or optional, support varargs, and include custom verification logic. Package: net.ccbluex.liquidbounce.features.command

Parameter Class

class Parameter<T : Any>(
    val name: String,
    val required: Boolean,
    val default: T?,
    val vararg: Boolean,
    val verifier: Verificator<T>?,
    val autocompletionHandler: AutoCompletionProvider?
)
name
String
required
Parameter name for display and error messages
required
Boolean
required
Whether parameter must be provided
default
T?
required
Default value if parameter is optional and not provided
vararg
Boolean
required
If true, parameter consumes all remaining arguments as array
verifier
Verificator<T>?
required
Validates and parses parameter value
autocompletionHandler
AutoCompletionProvider?
required
Provides completion suggestions

Properties

command
Command?
Parent command (set automatically)
var command: Command?
index
Int
Parameter index in command (set automatically)
var index: Int
description
MutableComponent
Translated parameter description
val description: MutableComponent

Methods

nameAsText

fun nameAsText(): Component
Returns formatted parameter name with hover description:
  • Required: <name>
  • Optional: [<name>]
  • Vararg: <name>...

Verificator Interface

fun interface Verificator<T : Any> {
    fun verifyAndParse(sourceText: String): Result<out T>
    
    sealed interface Result<T : Any> {
        class Ok<T : Any>(val mappedResult: T) : Result<T>
        class Error(val errorMessage: String) : Result<Nothing>
    }
}

Creating Verificators

// Integer with range
val intVerifier = Parameter.Verificator { text ->
    val value = text.toIntOrNull()
    if (value == null) {
        Parameter.Verificator.Result.Error("Must be a number")
    } else if (value !in 1..100) {
        Parameter.Verificator.Result.Error("Must be between 1 and 100")
    } else {
        Parameter.Verificator.Result.Ok(value)
    }
}

// Module verification
val moduleVerifier = Parameter.Verificator { text ->
    val module = ModuleManager[text]
    Parameter.Verificator.Result.ofNullable(module) {
        "Module '$text' not found"
    }
}

// Enum verification
val enumVerifier = Parameter.Verificator<MyEnum> { text ->
    try {
        Parameter.Verificator.Result.Ok(MyEnum.valueOf(text))
    } catch (e: IllegalArgumentException) {
        Parameter.Verificator.Result.Error("Invalid value. Valid values: ${MyEnum.values().joinToString()}")
    }
}

AutoCompletionProvider

fun interface AutoCompletionProvider {
    fun autocomplete(begin: String, args: List<String>): Iterable<String>
}
begin
String
Current partial text of the parameter being completed
args
List<String>
All current arguments of the command

Creating Auto-completion Providers

// Module names
val moduleCompletion = AutoCompletionProvider { begin, _ ->
    ModuleManager
        .filter { it.name.startsWith(begin, ignoreCase = true) }
        .map { it.name }
}

// File names
val fileCompletion = AutoCompletionProvider { begin, _ ->
    File(".")
        .listFiles { file -> file.name.startsWith(begin, ignoreCase = true) }
        ?.map { it.name }
        ?: emptyList()
}

// Contextual completion
val contextualCompletion = AutoCompletionProvider { begin, args ->
    when (args.getOrNull(0)) {
        "add" -> getAvailableItems(begin)
        "remove" -> getCurrentItems(begin)
        else -> emptyList()
    }
}

Parameter Examples

Required String Parameter

val name = parameter<String>(
    name = "name",
    required = true
)

Optional Integer Parameter

val count = parameter(
    name = "count",
    required = false,
    default = 10,
    verifier = Parameter.Verificator { text ->
        val value = text.toIntOrNull()
        Parameter.Verificator.Result.ofNullable(value) {
            "Must be a number"
        }
    }
)

Vararg String Parameter

val message = parameter<String>(
    name = "message",
    required = true,
    vararg = true
)

// Usage: .say Hello world this is a message
// message = ["Hello", "world", "this", "is", "a", "message"]

Module Parameter with Validation

val module = parameter(
    name = "module",
    required = true,
    verifier = Parameter.Verificator { text ->
        val module = ModuleManager[text]
        Parameter.Verificator.Result.ofNullable(module) {
            "Module '$text' not found"
        }
    },
    autocompletionHandler = AutoCompletionProvider { begin, _ ->
        ModuleManager
            .filter { it.name.startsWith(begin, ignoreCase = true) }
            .map { it.name }
    }
)

Float Parameter with Range

val speed = parameter(
    name = "speed",
    required = false,
    default = 1.0f,
    verifier = Parameter.Verificator { text ->
        val value = text.toFloatOrNull()
        when {
            value == null -> Parameter.Verificator.Result.Error("Must be a number")
            value < 0.1f -> Parameter.Verificator.Result.Error("Must be at least 0.1")
            value > 10.0f -> Parameter.Verificator.Result.Error("Must be at most 10.0")
            else -> Parameter.Verificator.Result.Ok(value)
        }
    }
)

Boolean Parameter

val enabled = parameter(
    name = "enabled",
    required = false,
    default = true,
    verifier = Parameter.Verificator { text ->
        when (text.lowercase()) {
            "true", "yes", "on", "1" -> Parameter.Verificator.Result.Ok(true)
            "false", "no", "off", "0" -> Parameter.Verificator.Result.Ok(false)
            else -> Parameter.Verificator.Result.Error("Must be true/false")
        }
    },
    autocompletionHandler = AutoCompletionProvider { begin, _ ->
        listOf("true", "false").filter { it.startsWith(begin, ignoreCase = true) }
    }
)

Enum Parameter

enum class GameMode { SURVIVAL, CREATIVE, ADVENTURE, SPECTATOR }

val gameMode = parameter(
    name = "mode",
    required = true,
    verifier = Parameter.Verificator { text ->
        try {
            Parameter.Verificator.Result.Ok(GameMode.valueOf(text.uppercase()))
        } catch (e: IllegalArgumentException) {
            Parameter.Verificator.Result.Error(
                "Invalid mode. Valid modes: ${GameMode.values().joinToString()}"
            )
        }
    },
    autocompletionHandler = AutoCompletionProvider { begin, _ ->
        GameMode.values()
            .map { it.name.lowercase() }
            .filter { it.startsWith(begin, ignoreCase = true) }
    }
)

Best Practices

  1. Always provide verification - Validate input before use
  2. Add auto-completion - Improves user experience significantly
  3. Use meaningful names - Parameter names appear in error messages
  4. Provide helpful error messages - Guide users to correct input
  5. Use nullable defaults for optional parameters - Clear intent
  6. Varargs must be last - Only one vararg per command, at the end
  7. Parse early - Convert strings in verificator, not in handler
  8. Consider context - Auto-completion can be context-aware

Common Parameter Types

Player Parameter

val player = parameter(
    name = "player",
    required = true,
    verifier = Parameter.Verificator { text ->
        val player = mc.level?.players()?.firstOrNull { 
            it.gameProfile.name.equals(text, ignoreCase = true) 
        }
        Parameter.Verificator.Result.ofNullable(player) {
            "Player '$text' not found"
        }
    },
    autocompletionHandler = AutoCompletionProvider { begin, _ ->
        mc.level?.players()
            ?.map { it.gameProfile.name }
            ?.filter { it.startsWith(begin, ignoreCase = true) }
            ?: emptyList()
    }
)

Block Parameter

val block = parameter(
    name = "block",
    required = true,
    verifier = Parameter.Verificator { text ->
        val block = BuiltInRegistries.BLOCK
            .get(ResourceLocation(text))
        Parameter.Verificator.Result.ofNullable(block) {
            "Block '$text' not found"
        }
    }
)

See Also

Build docs developers (and LLMs) love