Skip to main content

Overview

The ModuleManager is a singleton object that manages all registered modules in LiquidBounce. It handles module registration, keybind processing, and lifecycle events.

Object Declaration

object ModuleManager : EventListener, Collection<ClientModule>
ModuleManager implements Collection<ClientModule>, so you can use standard collection operations like forEach, filter, find, etc.

Properties

modulesConfig

val modulesConfig: ConfigRoot
The configuration root for all modules. Used by the config system to save and load module states.

Methods

addModule

fun addModule(module: ClientModule)
Registers a new module with the ModuleManager. Throws an error if a module with the same name already exists.
module
ClientModule
required
The module instance to register
val customModule = object : ClientModule(
    name = "MyModule",
    category = ModuleCategories.MISC
) {
    // Module implementation
}

ModuleManager.addModule(customModule)

removeModule

fun removeModule(module: ClientModule)
Unregisters a module from the ModuleManager. Throws an error if the module is not registered.
module
ClientModule
required
The module instance to remove

clear

fun clear()
Removes all registered modules. Use with caution.

getModuleByName

fun getModuleByName(module: String): ClientModule?
Finds a module by name (case-insensitive).
module
String
required
The name of the module to find
val killAura = ModuleManager.getModuleByName("KillAura")
if (killAura != null) {
    killAura.enabled = true
}

get (operator)

operator fun get(moduleName: String): ClientModule?
Operator overload for array-style access to modules by name.
// Both are equivalent
val fly = ModuleManager["Fly"]
val fly2 = ModuleManager.getModuleByName("Fly")

getCategories

fun getCategories(): Array<String>
Returns an array of all category names. Used by the ClickGUI implementation.

getModules

fun getModules(): Collection<ClientModule>
Returns the collection of all registered modules.

registerInbuilt

fun registerInbuilt()
Registers all built-in LiquidBounce modules. Called during client initialization.

Collection Operations

Since ModuleManager implements Collection<ClientModule>, you can use standard collection operations:
// Find all enabled modules
val enabledModules = ModuleManager.filter { it.enabled }

// Find all combat modules
val combatModules = ModuleManager.filter { it.category == ModuleCategories.COMBAT }

// Count modules by category
val renderCount = ModuleManager.count { it.category == ModuleCategories.RENDER }

// Iterate over all modules
ModuleManager.forEach { module ->
    println("${module.name}: ${if (module.enabled) "ON" else "OFF"}")
}

// Check if a module exists
val hasSpeed = ModuleManager.any { it.name.equals("Speed", ignoreCase = true) }

Event Handling

ModuleManager automatically handles:
  • Keyboard events: Processes keybinds for all modules
  • Mouse events: Handles mouse button binds
  • World changes: Enables delayed-start modules when joining a world
  • Disconnect events: Disables modules marked with disableOnQuit

Bind Actions

Modules support three bind action types:

TOGGLE

Press key to toggle on/off

HOLD

Module active only while key is held

SMART

Quick press toggles, long hold activates temporarily

Examples

Finding and Enabling a Module

// Method 1: Using getModuleByName
val killAura = ModuleManager.getModuleByName("KillAura")
killAura?.enabled = true

// Method 2: Using operator get
ModuleManager["Fly"]?.enabled = true

// Method 3: Using find
val speed = ModuleManager.find { it.name.equals("Speed", ignoreCase = true) }
speed?.enabled = true

Accessing Module Settings

val killAura = ModuleManager["KillAura"]
if (killAura != null) {
    // Access settings through the settings map
    val rangeValue = killAura.settings["Range"]
    println("KillAura range: ${rangeValue?.get()}")
}

Creating and Registering a Custom Module

object ModuleAutoGreet : ClientModule(
    name = "AutoGreet",
    category = ModuleCategories.MISC,
    state = false
) {
    private val greeting by text("Message", "Hello!")
    
    val chatHandler = handler<ChatReceivedEvent> { event ->
        // Auto-respond logic here
        chat(greeting)
    }
}

// Register the module
ModuleManager.addModule(ModuleAutoGreet)

Filtering Modules by Category

// Get all movement modules
val movementModules = ModuleManager.filter { 
    it.category == ModuleCategories.MOVEMENT 
}

// Enable all render modules (not recommended!)
ModuleManager
    .filter { it.category == ModuleCategories.RENDER }
    .forEach { it.enabled = true }

Checking Module States

// Check if any combat module is enabled
val combatActive = ModuleManager.any { 
    it.category == ModuleCategories.COMBAT && it.enabled 
}

// Count enabled modules
val enabledCount = ModuleManager.count { it.enabled }

println("$enabledCount modules are currently enabled")

Configuration

Modules are automatically saved and loaded through the configuration system:
  • Auto-save: Module states are saved when leaving a world
  • Auto-load: Module states are restored on client startup
  • Delayed enable: Modules enabled in config will call onToggled() when first joining a world

See Also

Build docs developers (and LLMs) love