Documentation Index
Fetch the complete documentation index at: https://mintlify.com/CCBlueX/LiquidBounce/llms.txt
Use this file to discover all available pages before exploring further.
Overview
LiquidBounce provides extensive rendering utilities for drawing 2D overlays, 3D world objects, and managing render state.
Core Rendering Packages
net.ccbluex.liquidbounce.render - Core rendering engine
net.ccbluex.liquidbounce.utils.render - Rendering utilities and extensions
3D World Rendering
usePoseStack
Borrows a pose stack from the pool for transformations.
inline fun <T> usePoseStack(block: PoseStack.() -> T): T
Example:
usePoseStack {
translate(x, y, z)
scale(2.0f, 2.0f, 2.0f)
// Render at transformed position
}
withPush
Pushes the pose stack, executes a block, then pops.
inline fun PoseStack.withPush(block: PoseStack.() -> Unit)
Example:
matrices.withPush {
translate(0.5, 0.5, 0.5)
// Transformation only applies within this block
}
DrawMode
Controls how geometry is submitted:
IMMEDIATE - Draw immediately
BATCH - Collect and draw in batch
enum class DrawMode {
IMMEDIATE,
BATCH
}
Rendering Context
WorldRenderEnvironment
Provides context for world rendering:
val renderHandler = handler<WorldRenderEvent> { event ->
val env = event.worldRenderEnvironment
env.withPush {
// Your rendering code
}
}
Common Rendering Utilities
Render Boxes
// Draw a box outline
fun drawBox(box: AABB, color: Color4b) {
// Box rendering
}
// Draw filled box
fun drawFilledBox(box: AABB, color: Color4b) {
// Filled box rendering
}
Render Lines
// Draw a line between two points
fun drawLine(
from: Vec3,
to: Vec3,
color: Color4b,
lineWidth: Float = 2.0f
)
Render Text in World
// Render text at world position
fun renderTextAtPosition(
text: String,
pos: Vec3,
scale: Float = 1.0f
)
Rendering Events
WorldRenderEvent
Fired during world rendering.
val renderHandler = handler<WorldRenderEvent> { event ->
// Draw ESP boxes, tracers, etc.
for (entity in world.entities) {
if (entity.shouldBeAttacked()) {
drawBox(entity.boundingBox, Color4b(255, 0, 0, 100))
}
}
}
OverlayRenderEvent
Fired during overlay rendering (2D HUD).
val overlayHandler = handler<OverlayRenderEvent> { event ->
// Draw 2D elements on screen
}
ScreenRenderEvent
Fired when rendering GUI screens.
Rendering Primitives
Color4b
Represents RGBA color.
val red = Color4b(255, 0, 0, 255)
val transparentBlue = Color4b(0, 0, 255, 100)
// From hex
val color = Color4b.fromHex(0xFF0000FF)
Vec3f
3D vector for positions and directions.
val position = Vec3f(x, y, z)
Batch Rendering
For performance, batch similar draw calls:
val batchCollector = BatchCollector()
// Collect draws
for (entity in entities) {
batchCollector.draw(entity.box, color)
}
// Render all at once
batchCollector.flush()
Shader Usage
ClientShaders
Access built-in shaders:
ClientShaders.POSITION_COLOR
ClientShaders.POSITION_COLOR_TEXTURE
Custom Rendering Pipeline
val pipeline = RenderPipeline(
vertexFormat = VertexFormat.POSITION_COLOR,
mode = VertexFormat.Mode.QUADS
)
Rendering Examples
ESP Box Rendering
val espHandler = handler<WorldRenderEvent> { event ->
val env = event.worldRenderEnvironment
for (entity in world.entities) {
if (!entity.shouldBeAttacked()) continue
val box = entity.boundingBox
val color = if (entity.isPlayer) {
Color4b(255, 0, 0, 100) // Red for players
} else {
Color4b(0, 255, 0, 100) // Green for mobs
}
env.drawBox(box, color)
}
}
Tracer Rendering
val tracerHandler = handler<WorldRenderEvent> { event ->
val env = event.worldRenderEnvironment
val eyePos = player.eyePosition
for (entity in world.entities) {
if (!entity.shouldBeAttacked()) continue
val targetPos = entity.position()
env.drawLine(
from = eyePos,
to = targetPos,
color = Color4b(255, 255, 255, 200),
lineWidth = 2.0f
)
}
}
val nameTagHandler = handler<WorldRenderEvent> { event ->
val env = event.worldRenderEnvironment
for (entity in world.entities) {
val namePos = entity.position().add(0.0, entity.bbHeight + 0.3, 0.0)
env.renderTextAtPosition(
text = entity.name.string,
pos = namePos,
scale = 0.02f
)
}
}
Block ESP
val blockEspHandler = handler<WorldRenderEvent> { event ->
val env = event.worldRenderEnvironment
val searchRadius = 50
for (x in -searchRadius..searchRadius) {
for (y in -searchRadius..searchRadius) {
for (z in -searchRadius..searchRadius) {
val pos = player.blockPosition().offset(x, y, z)
val block = world.getBlockState(pos).block
if (block == Blocks.DIAMOND_ORE) {
val box = AABB.ofSize(pos.center(), 1.0, 1.0, 1.0)
env.drawFilledBox(box, Color4b(0, 255, 255, 50))
env.drawBox(box, Color4b(0, 255, 255, 200))
}
}
}
}
}
Custom Shapes
val customShapeHandler = handler<WorldRenderEvent> { event ->
val env = event.worldRenderEnvironment
env.withPush {
translate(player.x, player.y, player.z)
// Draw circle on ground
val radius = 3.0
val segments = 32
for (i in 0 until segments) {
val angle1 = (i.toDouble() / segments) * 2 * Math.PI
val angle2 = ((i + 1).toDouble() / segments) * 2 * Math.PI
val x1 = cos(angle1) * radius
val z1 = sin(angle1) * radius
val x2 = cos(angle2) * radius
val z2 = sin(angle2) * radius
drawLine(
Vec3(x1, 0.0, z1),
Vec3(x2, 0.0, z2),
Color4b(255, 255, 0, 255)
)
}
}
}
2D Overlay Rendering
Screen Coordinates
val overlayHandler = handler<OverlayRenderEvent> { event ->
val screenWidth = mc.window.guiScaledWidth
val screenHeight = mc.window.guiScaledHeight
// Draw at screen position
drawText(
text = "LiquidBounce",
x = 5f,
y = 5f
)
}
Render Statistics
val statsHandler = handler<OverlayRenderEvent> { event ->
val stats = listOf(
"FPS: ${mc.fps}",
"Position: ${player.blockPosition()}",
"Speed: ${getSpeed()}"
)
stats.forEachIndexed { index, stat ->
drawText(
text = stat,
x = 5f,
y = 5f + (index * 10f)
)
}
}
World to Screen Conversion
Convert 3D world positions to 2D screen coordinates:
fun worldToScreen(worldPos: Vec3): Vec2? {
// Projection logic
// Returns null if position is behind camera
}
Use batch rendering for multiple objects with the same render state to improve performance.
Avoid creating new objects in render handlers - reuse objects or use object pools.
Rendering happens on the render thread - don’t perform game logic in render handlers.
Best Practices
- Use appropriate events -
WorldRenderEvent for 3D, OverlayRenderEvent for 2D
- Batch similar draws - Reduce state changes
- Reuse resources - Don’t create new buffers every frame
- Cull invisible objects - Don’t render what’s not visible
- Use appropriate precision - Float for most rendering, Double for positions
Common Utilities
Distance Checks
fun shouldRender(entity: Entity): Boolean {
val distance = player.distanceTo(entity)
return distance <= renderDistance
}
Frustum Culling
fun isInView(box: AABB): Boolean {
// Check if box is in camera frustum
}
See Also