Skip to main content

Overview

ModuleCategories provides a registry of all module categories in LiquidBounce. Categories are used to organize modules in the ClickGUI and for logical grouping.

ModuleCategory Class

class ModuleCategory(override val tag: String) : Tagged
tag
String
required
The category’s display name

Available Categories

ModuleCategories is an object that provides predefined category constants:
object ModuleCategories {
    val COMBAT: ModuleCategory
    val PLAYER: ModuleCategory
    val MOVEMENT: ModuleCategory
    val RENDER: ModuleCategory
    val WORLD: ModuleCategory
    val MISC: ModuleCategory
    val EXPLOIT: ModuleCategory
    val FUN: ModuleCategory
    
    val entries: Collection<ModuleCategory>
    
    fun byName(name: String): ModuleCategory?
}

Category Descriptions

COMBAT

Modules for combat situations: KillAura, Velocity, AutoArmor, Criticals, etc.

MOVEMENT

Modules affecting player movement: Speed, Fly, Sprint, NoSlow, Step, etc.

PLAYER

Player-related utilities: NoFall, AutoRespawn, ChestStealer, InventoryCleaner, etc.

RENDER

Visual modifications: ESP, Fullbright, Nametags, ClickGUI, HUD, etc.

WORLD

World interaction modules: Scaffold, Fucker, FastBreak, CrystalAura, etc.

EXPLOIT

Exploit-based modules: Disabler, Phase, Blink, PingSpoof, etc.

MISC

Miscellaneous utilities: AntiBot, Teams, Spammer, NameProtect, etc.

FUN

Entertainment modules: Derp, SkinDerp, Twerk, Notebot, etc.

Methods

byName

fun byName(name: String): ModuleCategory?
Finds a category by name (case-insensitive). Returns null if not found.
name
String
required
The category name to look up
val combat = ModuleCategories.byName("Combat")
val movement = ModuleCategories.byName("movement") // Case-insensitive

entries

val entries: Collection<ModuleCategory>
Returns a collection of all registered categories.
// Iterate over all categories
ModuleCategories.entries.forEach { category ->
    println("Category: ${category.tag}")
}

Usage Examples

Creating a Module with a Category

object ModuleCustomSpeed : ClientModule(
    name = "CustomSpeed",
    category = ModuleCategories.MOVEMENT,  // Use predefined category
    bind = GLFW.GLFW_KEY_V
) {
    // Module implementation
}

Filtering Modules by Category

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

// Count modules in each category
ModuleCategories.entries.forEach { category ->
    val count = ModuleManager.count { it.category == category }
    println("${category.tag}: $count modules")
}

Category-based Operations

// Disable all movement modules
ModuleManager
    .filter { it.category == ModuleCategories.MOVEMENT }
    .forEach { it.enabled = false }

// Check if any render module is enabled
val renderActive = ModuleManager.any {
    it.category == ModuleCategories.RENDER && it.enabled
}

// Get all categories with at least one enabled module
val activeCategories = ModuleCategories.entries.filter { category ->
    ModuleManager.any { module ->
        module.category == category && module.enabled
    }
}

Registering Custom Categories

While the built-in categories cover most use cases, you can theoretically register custom categories:
// Note: ModuleCategories.register() is private, so custom categories
// are not officially supported. Use existing categories instead.

// If you need a custom grouping, use MISC or create a subcategory
// through naming conventions:
object ModuleMyCustomFeature : ClientModule(
    name = "MyCustomFeature",
    category = ModuleCategories.MISC,
    aliases = listOf("custom-subcategory")
) {
    // Implementation
}

Category Organization

Categories are stored in a case-insensitive TreeMap, ensuring:
  • Case-insensitive lookup: “Combat”, “combat”, and “COMBAT” all work
  • Alphabetical ordering: Categories are ordered alphabetically
  • No duplicates: Each category name must be unique
// All of these work
val cat1 = ModuleCategories.byName("Combat")
val cat2 = ModuleCategories.byName("COMBAT")
val cat3 = ModuleCategories.byName("combat")

// All reference the same category
assert(cat1 == cat2 && cat2 == cat3)

Best Practices

Always use one of the eight predefined categories rather than attempting to create custom ones. They cover all common use cases.
If a module could fit multiple categories, choose the most specific one. For example, AntiVoid is PLAYER rather than MOVEMENT, as it’s specifically a player protection feature.
Use MISC for utility modules that don’t fit other categories, like AntiBot, Teams, or chat-related features.
Remember that categories determine how modules appear in the ClickGUI, so choose categories that make intuitive sense to users.

Category Statistics

// Print statistics for all categories
ModuleCategories.entries.forEach { category ->
    val modules = ModuleManager.filter { it.category == category }
    val enabledCount = modules.count { it.enabled }
    val totalCount = modules.size
    
    println("""
        Category: ${category.tag}
        Total Modules: $totalCount
        Enabled: $enabledCount
        Disabled: ${totalCount - enabledCount}
    """.trimIndent())
}

See Also

Build docs developers (and LLMs) love