Skip to main content
LiquidBounce features advanced integration systems for browser rendering, client-server communication, and third-party mod compatibility.

Overview

The integration system provides:
  • Embedded Chromium browser (MCEF/JCEF)
  • REST API and WebSocket server for UI communication
  • ViaFabricPlus protocol switching support
  • Theme and component management
  • External system browser fallback

Browser Backend System

BrowserBackendManager

Manages browser initialization and lifecycle (BrowserBackendManager.kt:39).
fun makeDependenciesAvailable(taskManager: TaskManager) {
    if (isSkipping) {
        logger.warn("Environment variable 'LB_BROWSER_SKIP' is set to 'true'.")
        return
    }
    
    val browserBackend = when (backendName) {
        "none" -> {
            logger.warn("Environment variable 'LB_BROWSER_BACKEND' is set to 'none'.")
            isSkipping = true
            return
        }
        "cef" -> CefBrowserBackend()
        "external" -> ExternalSystemBrowserBackend()
        else -> error("Unknown browser backend: $backendName")
    }
    this.backend = browserBackend
    browserBackend.makeDependenciesAvailable(taskManager, ::start)
}

Environment Variables

LB_BROWSER_SKIP
boolean
default:"false"
Skip browser initialization entirely
LB_BROWSER_BACKEND
string
default:"cef"
Browser backend to use (cef, external, none)
LB_BROWSER_DISABLE_ACCELERATION
boolean
default:"false"
Disable hardware acceleration

CEF Browser Backend

Chromium Embedded Framework integration via MCEF (CefBrowserBackend.kt:64).

Features

Full Chromium

Complete Chromium browser engine in Minecraft

Hardware Acceleration

GPU-accelerated rendering support

Auto Downloads

Automatic JCEF library downloading

Cache Management

Intelligent cache cleanup and management

MCEF Configuration

MCEF.INSTANCE.settings.apply {
    userAgent = HttpClient.DEFAULT_AGENT
    cacheDirectory = cacheFolder.resolve(System.currentTimeMillis().toString(16)).apply {
        deleteOnExit()
    }
    librariesDirectory = librariesFolder
    
    // CEF Switches
    appendCefSwitches("--no-proxy-server")
}

Directory Structure

mcef/
directory
MCEF root directory

Cache Cleanup

Automatic cleanup of old cache directories (CefBrowserBackend.kt:129):
fun cleanup() {
    if (cacheFolder.exists()) {
        cacheFolder.listFiles()
            ?.filter { file ->
                file.isDirectory && 
                System.currentTimeMillis() - file.lastModified() > CACHE_CLEANUP_THRESHOLD
            }
            ?.sumOf { file ->
                val fileSize = file.walkTopDown().sumOf { it.length() }
                file.deleteRecursively()
                fileSize
            }
    }
}
Cache directories older than 7 days are automatically cleaned up on startup.

Compatibility Checking

val resourceManager = MCEF.INSTANCE.newResourceManager()

if (!resourceManager.isSystemCompatible) {
    throw JcefIsntCompatible()
}
JCEF requires specific system configurations. Not all systems support hardware acceleration.

Client Interop Server

HTTP/WebSocket server for browser-client communication (ClientInteropServer.kt:44).

Server Configuration

LB_INTEROP_SKIP
boolean
default:"false"
Skip interop server initialization
LB_INTEROP_PORT
int
default:"random"
Server port (defaults to random available port)
LB_INTEROP_AUTH_CODE
string
default:"random"
Authentication code (16 random alphanumeric characters)

Server Initialization

1

Port Selection

Automatically selects an available port if not specified
2

Endpoint Registration

Registers all REST API and WebSocket endpoints
3

Middleware Setup

Adds CORS and authentication middleware
4

Resource Mounting

Mounts theme files and marketplace resources
5

Start Listening

Begins accepting connections
suspend fun start() {
    httpServer.apply {
        routing {
            get("/", ::getRootResponse)
            registerInteropFunctions()
            
            LiquidBounce.resource("themes/liquidbounce.zip").use { stream ->
                zip("/resource/liquidbounce", stream)
            }
            file("/local", ThemeManager.themesFolder)
            file("/marketplace", MarketplaceManager.marketplaceRoot)
        }
        
        middleware(CorsMiddleware())
        middleware(AuthMiddleware())
    }
    
    this.PORT = startServer(this.PORT)
}

API Endpoints

The server exposes extensive REST API endpoints organized by category:
  • /api/v1/client/info - Client information
  • /api/v1/client/modules - Module management
  • /api/v1/client/accounts - Account management
  • /api/v1/client/session - Session data
  • /api/v1/client/theme - Theme operations
  • /api/v1/client/components - HUD components
  • /api/v1/game/player - Player data
  • /api/v1/game/world - World information
  • /api/v1/game/servers - Server list
  • /api/v1/game/textures - Texture access
  • /api/v1/game/input - Input handling
  • /api/v1/game/registry - Game registries
  • /api/v1/features/browser - Browser control
  • /api/v1/features/protocol - Protocol switching
  • /api/v1/features/reconnect - Auto-reconnect

WebSocket Events

Real-time event streaming to the browser:
// Register events with @WebSocketEvent annotation
SocketEventListener.registerAll()
WebSocket events allow the browser UI to react instantly to in-game changes.

Authentication System

Secure authentication using randomly generated codes (AuthMiddleware.kt):
val AUTH_CODE: String = env("LB_INTEROP_AUTH_CODE", "net.ccbluex.liquidbounce.interop.authCode")
    ?: RandomStringUtils.secure().nextAlphanumeric(16)
The auth code is generated on startup and must be included in requests from the browser.

ViaFabricPlus Integration

Support for protocol version switching when ViaFabricPlus is installed.

Protocol Detection

val usesViaFabricPlus: Boolean
    get() = FabricLoader.getInstance().isModLoaded("viafabricplus")

Automatic Protocol Switching

When loading auto-configs with different protocol versions:
if (usesViaFabricPlus) {
    if (inGame) {
        chat(markAsError("Please reconnect to the server to apply the correct protocol."))
    } else {
        selectProtocolVersion(pVersion)
    }
} else {
    chat(markAsError("Please install ViaFabricPlus to apply the correct protocol."))
}

Theme System

Manage custom themes and UI components.

Theme Structure

themes/
directory
Theme storage directory

HUD Components

The integration system supports various HUD component types:

Web Components

Browser-rendered HUD elements

Native Components

Kotlin-rendered components

Minimap

Real-time world minimap

Browser Lifecycle Management

Creating Browsers

val browser = backend.createBrowser(
    url = "https://example.com",
    position = BrowserViewport(x, y, width, height),
    settings = BrowserSettings(),
    priority = 0,
    inputAcceptor = customInputHandler
)

Browser States

Loading
state
Browser is loading the page
Success
state
Page loaded successfully (includes HTTP status code)
Failure
state
Failed to load page (includes error code and message)

Force Update

Refresh all browser viewports:
fun forceUpdate() = mc.execute {
    val browserBackend = backend ?: return@execute
    
    for (browser in browserBackend.browsers) {
        try {
            browser.viewport = browser.viewport
        } catch (e: Exception) {
            logger.error("Failed to update tab of '${browser.url}'", e)
        }
    }
}

External System Browser Backend

Fallback browser backend using the system’s default browser (ExternalSystemBrowserBackend.kt).
The external backend opens URLs in the system browser when CEF is unavailable or disabled.

Screen Management

Custom screen types for browser integration:
Full-screen browser window

Performance Considerations

Render Thread

Browser operations must run on the render thread

Message Loop

CEF message loop runs on every frame render

Hardware Acceleration

Can be disabled for compatibility

Priority System

Browsers render in priority order

Troubleshooting

Check internet connection and firewall settings. The system will automatically retry with a random port.
Ensure you’re on the render thread and the backend is initialized.
The server automatically retries with different ports (up to 5 attempts).
Verify the auth code is correctly passed from the interop server to the browser.

Best Practices

1

Initialize Early

Start browser backend during client initialization
2

Handle Failures

Always provide fallback for systems where CEF is unavailable
3

Clean Up Resources

Properly shutdown browsers and servers on client exit
4

Use Events

Listen to BrowserReadyEvent before creating browsers

MCEF Project

LiquidBounce’s MCEF fork

Theme System

Creating custom themes

Build docs developers (and LLMs) love