Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
3e266b0
depth test / block outline start / immediate region esp where you upd…
beanbag44 Jan 12, 2026
5622e6e
Merge branch '1.21.11' into improvement/renders
beanbag44 Jan 12, 2026
ad88469
fix static and dynamic render events
beanbag44 Jan 12, 2026
0aec9f4
remove shape caching
beanbag44 Jan 13, 2026
1efc938
initial working standard and sdf text world rendering
beanbag44 Jan 15, 2026
05e3c61
remove per render region origin
beanbag44 Jan 15, 2026
9edbe8f
move font rendering into RenderBuilder and fix dashed lines.
beanbag44 Jan 17, 2026
88ef317
Merge branch '1.21.11' into improvement/renders
beanbag44 Jan 17, 2026
f4980a9
cleanup
beanbag44 Jan 17, 2026
1c16e88
screen rendering
beanbag44 Jan 18, 2026
811efe0
render dash animation through end caps and fix antialiasing on dash ends
beanbag44 Jan 18, 2026
8d8a49e
fix glow rendering under outline and store a map of text style to tex…
beanbag44 Jan 18, 2026
8f82a34
improved line anti-aliasing
beanbag44 Jan 19, 2026
0e9eff8
fix zoom not affecting tracers
beanbag44 Jan 19, 2026
f0bbefd
have tracers go off-screen when a target is behind the camera
beanbag44 Jan 20, 2026
900a5e2
tracer improvements
beanbag44 Jan 20, 2026
a6e6a6f
item screen rendering
beanbag44 Jan 20, 2026
69038ea
vertex attribute based text sdf info
beanbag44 Jan 20, 2026
7aee494
Merge branch '1.21.11' into improvement/renders
beanbag44 Jan 20, 2026
0bf9d34
custom depth buffer layer indexing for the performance of batched ren…
beanbag44 Jan 21, 2026
30af1c2
world line rendering improvements
beanbag44 Jan 21, 2026
fbb6c52
more tracer improvements
beanbag44 Jan 21, 2026
ea9aefc
nametags
beanbag44 Jan 22, 2026
8708ad3
nametags improvements
beanbag44 Jan 23, 2026
d3653b0
fix world lines not rotating to face the camera
beanbag44 Jan 23, 2026
f329011
Merge branch '1.21.11' into improvement/renders
beanbag44 Jan 24, 2026
e3ce66a
Merge branch '1.21.11' into improvement/renders
beanbag44 Jan 27, 2026
7ee3e58
merge bug
beanbag44 Jan 27, 2026
63f3765
Merge remote-tracking branch 'NeoLambda/improvement/renders' into imp…
beanbag44 Jan 28, 2026
f762d5f
threaded font atlas generation
beanbag44 Jan 28, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/main/java/com/lambda/mixin/entity/EntityMixin.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

package com.lambda.mixin.entity;

import com.lambda.Lambda;
import com.lambda.event.EventFlow;
import com.lambda.event.events.EntityEvent;
import com.lambda.event.events.PlayerEvent;
Expand Down Expand Up @@ -151,11 +152,13 @@ private boolean modifyGetFlagGlowing(boolean original) {

@WrapWithCondition(method = "changeLookDirection", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;setYaw(F)V"))
private boolean wrapSetYaw(Entity instance, float yaw) {
if ((Object) this != getMc().player) return true;
return RotationManager.getLockYaw() == null;
}

@WrapWithCondition(method = "changeLookDirection", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;setPitch(F)V"))
private boolean wrapSetPitch(Entity instance, float yaw) {
if ((Object) this != Lambda.getMc().player) return true;
return RotationManager.getLockPitch() == null;
}

Expand Down
22 changes: 20 additions & 2 deletions src/main/java/com/lambda/mixin/render/GameRendererMixin.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import com.lambda.event.events.RenderEvent;
import com.lambda.graphics.RenderMain;
import com.lambda.gui.DearImGui;
import com.lambda.module.modules.render.BlockOutline;
import com.lambda.module.modules.render.NoRender;
import com.lambda.module.modules.render.Zoom;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
Expand All @@ -40,6 +41,7 @@
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

@Mixin(GameRenderer.class)
public class GameRendererMixin {
Expand All @@ -53,8 +55,7 @@ private void updateTargetedEntityInvoke(float tickDelta, CallbackInfo info) {
@WrapOperation(method = "renderWorld", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/WorldRenderer;render(Lnet/minecraft/client/util/ObjectAllocator;Lnet/minecraft/client/render/RenderTickCounter;ZLnet/minecraft/client/render/Camera;Lorg/joml/Matrix4f;Lorg/joml/Matrix4f;Lorg/joml/Matrix4f;Lcom/mojang/blaze3d/buffers/GpuBufferSlice;Lorg/joml/Vector4f;Z)V"))
void onRenderWorld(WorldRenderer instance, ObjectAllocator allocator, RenderTickCounter tickCounter, boolean renderBlockOutline, Camera camera, Matrix4f positionMatrix, Matrix4f basicProjectionMatrix, Matrix4f projectionMatrix, GpuBufferSlice fogBuffer, Vector4f fogColor, boolean renderSky, Operation<Void> original) {
original.call(instance, allocator, tickCounter, renderBlockOutline, camera, positionMatrix, basicProjectionMatrix, projectionMatrix, fogBuffer, fogColor, renderSky);

RenderMain.render3D(positionMatrix, projectionMatrix);
RenderMain.render3D(positionMatrix, basicProjectionMatrix);
}

@ModifyExpressionValue(method = "renderWorld", at = @At(value = "INVOKE", target = "Ljava/lang/Math;max(FF)F", ordinal = 0))
Expand All @@ -69,11 +70,28 @@ private void injectShowFloatingItem(ItemStack floatingItem, CallbackInfo ci) {

@ModifyReturnValue(method = "getFov", at = @At("RETURN"))
private float modifyGetFov(float original) {
Zoom.updateCurrentZoom();
return original / Zoom.getLerpedZoom();
}

/**
* Inject screen rendering after InGameHud.render() but before overlays/screens.
* This makes Lambda's screen renders appear:
* - Above: hotbar, held items, health bars
* - Below: inventory GUI, chat, escape menu
*/
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/hud/InGameHud;render(Lnet/minecraft/client/gui/DrawContext;Lnet/minecraft/client/render/RenderTickCounter;)V", shift = At.Shift.AFTER))
private void onHudRenderComplete(RenderTickCounter tickCounter, boolean tick, CallbackInfo ci) {
RenderMain.renderScreen();
}

@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/render/GuiRenderer;render(Lcom/mojang/blaze3d/buffers/GpuBufferSlice;)V", shift = At.Shift.AFTER))
private void onGuiRenderComplete(RenderTickCounter tickCounter, boolean tick, CallbackInfo ci) {
DearImGui.INSTANCE.render();
}

@Inject(method = "shouldRenderBlockOutline()Z", at = @At("HEAD"), cancellable = true)
private void injectShouldRenderBlockOutline(CallbackInfoReturnable<Boolean> cir) {
if (BlockOutline.INSTANCE.isEnabled()) cir.setReturnValue(false);
}
}
11 changes: 11 additions & 0 deletions src/main/java/com/lambda/mixin/render/InGameHudMixin.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

package com.lambda.mixin.render;

import com.lambda.event.EventFlow;
import com.lambda.event.events.HudRenderEvent;
import com.lambda.module.modules.render.NoRender;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import net.minecraft.client.gui.DrawContext;
Expand Down Expand Up @@ -82,4 +84,13 @@ private void injectRenderScoreboardSidebar(DrawContext drawContext, ScoreboardOb
private void injectRenderCrosshair(DrawContext context, RenderTickCounter tickCounter, CallbackInfo ci) {
if (NoRender.INSTANCE.isEnabled() && NoRender.getNoCrosshair()) ci.cancel();
}

/**
* Fire HudRenderEvent at the end of HUD rendering to allow Lambda modules
* to render items and other GUI elements using the valid DrawContext.
*/
@Inject(method = "render", at = @At("RETURN"))
private void onRenderEnd(DrawContext context, RenderTickCounter tickCounter, CallbackInfo ci) {
EventFlow.post(new HudRenderEvent(context));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,15 @@

import com.lambda.Lambda;
import com.lambda.interaction.managers.rotating.RotationManager;
import com.lambda.module.modules.render.Nametags;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import net.minecraft.client.render.entity.LivingEntityRenderer;
import net.minecraft.entity.LivingEntity;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

import static com.lambda.util.math.LinearKt.lerp;

Expand Down Expand Up @@ -56,4 +59,10 @@ private float wrapGetLerpedPitch(LivingEntity livingEntity, float v, Operation<F

return lerp(v, RotationManager.getPrevServerRotation().getPitchF(), headPitch);
}

@Inject(method = "hasLabel(Lnet/minecraft/entity/LivingEntity;D)Z", at = @At("HEAD"), cancellable = true)
private void injectHasLabel(LivingEntity livingEntity, double d, CallbackInfoReturnable<Boolean> cir) {
if (Nametags.INSTANCE.isEnabled() && Nametags.shouldRenderNametag(livingEntity))
cir.setReturnValue(false);
}
}
2 changes: 1 addition & 1 deletion src/main/kotlin/com/lambda/config/groups/BreakSettings.kt
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ open class BreakSettings(

// Outline
override val outline by c.setting("Outline", true, "Renders the lines of the box to display break progress") { renders }.group(baseGroup, Group.Cosmetic).index()
override val outlineWidth by c.setting("Outline Width", 2, 0..5, 1, "The width of the outline") { renders && outline }.group(baseGroup, Group.Cosmetic).index()
override val outlineWidth by c.setting("Outline Width", 2f, 0f..10f, 0.1f, "The width of the outline") { renders && outline }.group(baseGroup, Group.Cosmetic).index()
override val dynamicOutlineColor by c.setting("Dynamic Outline Color", true, "Enables color interpolation from start to finish for the outline when breaking a block") { renders && outline }.group(baseGroup, Group.Cosmetic).index()
override val staticOutlineColor by c.setting("Outline Color", Color.RED.brighter(), "The Color of the outline at the start of breaking") { renders && !dynamicOutlineColor && outline }.group(baseGroup, Group.Cosmetic).index()
override val startOutlineColor by c.setting("Start Outline Color", Color.RED.brighter(), "The color of the outline at the start of breaking") { renders && dynamicOutlineColor && outline }.group(baseGroup, Group.Cosmetic).index()
Expand Down
104 changes: 21 additions & 83 deletions src/main/kotlin/com/lambda/config/groups/Targeting.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,15 @@ import com.lambda.interaction.managers.rotating.Rotation.Companion.dist
import com.lambda.interaction.managers.rotating.Rotation.Companion.rotation
import com.lambda.interaction.managers.rotating.Rotation.Companion.rotationTo
import com.lambda.threading.runSafe
import com.lambda.util.EntityUtils.EntityGroup
import com.lambda.util.EntityUtils.entityGroup
import com.lambda.util.NamedEnum
import com.lambda.util.extension.fullHealth
import com.lambda.util.math.distSq
import com.lambda.util.world.fastEntitySearch
import net.minecraft.client.network.ClientPlayerEntity
import net.minecraft.client.network.OtherClientPlayerEntity
import net.minecraft.entity.LivingEntity
import net.minecraft.entity.decoration.ArmorStandEntity
import net.minecraft.entity.mob.HostileEntity
import net.minecraft.entity.passive.PassiveEntity
import java.util.*

/**
Expand All @@ -55,77 +54,22 @@ abstract class Targeting(
private val defaultRange: Double,
private val maxRange: Double,
) : SettingGroup(c), TargetingConfig {
/**
* The range within which entities can be targeted. This value is configurable and constrained
* between 1.0 and [maxRange].
*/
override val targetingRange by c.setting("Targeting Range", defaultRange, 1.0..maxRange, 0.05).group(baseGroup)

/**
* Whether players are included in the targeting scope.
*/
override val players by c.setting("Players", true).group(baseGroup)

/**
* Whether friends are included in the targeting scope.
* Requires [players] to be true.
*/
override val friends by c.setting("Friends", false) { players }.group(baseGroup)

/**
* Whether mobs are included in the targeting scope.
*/
private val mobs by c.setting("Mobs", true).group(baseGroup)

/**
* Whether hostile mobs are included in the targeting scope
*/
private val hostilesSetting by c.setting("Hostiles", true) { mobs }.group(baseGroup)

/**
* Whether passive animals are included in the targeting scope
*/
private val animalsSetting by c.setting("Animals", true) { mobs }.group(baseGroup)

/**
* Indicates whether hostile entities are included in the targeting scope.
*/
override val hostiles get() = mobs && hostilesSetting

/**
* Indicates whether passive animals are included in the targeting scope.
*/
override val animals get() = mobs && animalsSetting

/**
* Whether invisible entities are included in the targeting scope.
*/
override val invisible by c.setting("Invisible", true).group(baseGroup)

/**
* Whether dead entities are included in the targeting scope.
*/
override val dead by c.setting("Dead", false).group(baseGroup)

/**
* Validates whether a given entity is targetable by the player based on current settings.
*
* @param player The [ClientPlayerEntity] performing the targeting.
* @param entity The [LivingEntity] being evaluated.
* @return `true` if the entity is valid for targeting, `false` otherwise.
*/
open fun validate(player: ClientPlayerEntity, entity: LivingEntity) = when {
!friends && entity is OtherClientPlayerEntity && entity.isFriend -> false
!players && entity is OtherClientPlayerEntity -> false
!animals && entity is PassiveEntity -> false
!hostiles && entity is HostileEntity -> false
entity is ArmorStandEntity -> false

!invisible && entity.isInvisibleTo(player) -> false
!dead && entity.isDead -> false

else -> true
}
/**
* The range within which entities can be targeted. This value is configurable and constrained
* between 1.0 and [maxRange].
*/
override val targetingRange by c.setting("Targeting Range", defaultRange, 1.0..maxRange, 0.05).group(baseGroup)
override val targets by c.setting("Targets", setOf(EntityGroup.Player, EntityGroup.Mob, EntityGroup.Boss), EntityGroup.entries)

/**
* Validates whether a given entity is targetable by the player based on current settings.
*
* @param player The [ClientPlayerEntity] performing the targeting.
* @param entity The [LivingEntity] being evaluated.
* @return `true` if the entity is valid for targeting, `false` otherwise.
*/
open fun validate(player: ClientPlayerEntity, entity: LivingEntity) =
entity.entityGroup in targets && (entity !is OtherClientPlayerEntity || !entity.isFriend)

/**
* Subclass for targeting entities specifically for combat purposes.
Expand Down Expand Up @@ -160,6 +104,7 @@ abstract class Targeting(
override fun validate(player: ClientPlayerEntity, entity: LivingEntity): Boolean {
if (fov < 180 && player.rotation dist player.eyePos.rotationTo(entity.pos) > fov) return false
if (entity.uuid in illegalTargets) return false
if (entity.isDead) return false
return super.validate(player, entity)
}

Expand All @@ -178,18 +123,11 @@ abstract class Targeting(

private val illegalTargets = setOf(
UUID(5706954458220675710, -6736729783554821869),
UUID(-2945922493004570036, -7599209072395336449)
UUID(-6076316721184881576, -7147993044363569449),
UUID(-2932596226593701300, -7553629058088633089)
)
}

/**
* Subclass for targeting entities for ESP (Extrasensory Perception) purposes.
*/
class ESP(
c: Configurable,
baseGroup: NamedEnum,
) : Targeting(c, baseGroup, 128.0, 1024.0)

/**
* Enum representing the different priority factors used for determining the best target.
*
Expand Down
11 changes: 3 additions & 8 deletions src/main/kotlin/com/lambda/config/groups/TargetingConfig.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,9 @@

package com.lambda.config.groups

import com.lambda.util.EntityUtils

interface TargetingConfig {
val targetingRange: Double

val players: Boolean
val friends: Boolean
val hostiles: Boolean
val animals: Boolean

val invisible: Boolean
val dead: Boolean
val targets: Collection<EntityUtils.EntityGroup>
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2025 Lambda
* Copyright 2026 Lambda
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand All @@ -15,18 +15,14 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package com.lambda.graphics.esp
package com.lambda.event.events

import com.lambda.graphics.mc.ChunkedRegionESP
import com.lambda.module.Module
import com.lambda.event.Event
import net.minecraft.client.gui.DrawContext

@DslMarker
annotation class EspDsl

fun Module.chunkedEsp(
name: String,
depthTest: Boolean = false,
update: ShapeScope.(net.minecraft.world.World, com.lambda.util.world.FastVector) -> Unit
): ChunkedRegionESP {
return ChunkedRegionESP(this, name, depthTest, update)
}
/**
* Event fired during HUD rendering with access to Minecraft's DrawContext.
* Use this for rendering items, textures, and other GUI elements that need
* to integrate with Minecraft's deferred GUI rendering system.
*/
class HudRenderEvent(val context: DrawContext) : Event
14 changes: 8 additions & 6 deletions src/main/kotlin/com/lambda/event/events/RenderEvent.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,18 @@ import com.lambda.event.callback.Cancellable
import com.lambda.event.callback.ICancellable
import com.lambda.event.listener.SafeListener.Companion.listen
import com.lambda.graphics.RenderMain
import com.lambda.graphics.mc.TransientRegionESP
import com.lambda.graphics.mc.renderer.ImmediateRenderer
import com.lambda.graphics.mc.renderer.TickedRenderer

fun Any.onStaticRender(block: SafeContext.(TransientRegionESP) -> Unit) =
listen<RenderEvent.Upload> { block(RenderMain.StaticESP) }
fun Any.onStaticRender(block: SafeContext.(TickedRenderer) -> Unit) =
listen<RenderEvent.UploadStatic> { block(RenderMain.staticESP) }

fun Any.onDynamicRender(block: SafeContext.(TransientRegionESP) -> Unit) =
listen<RenderEvent.Upload> { block(RenderMain.DynamicESP) }
fun Any.onDynamicRender(block: SafeContext.(ImmediateRenderer) -> Unit) =
listen<RenderEvent.UploadDynamic> { block(RenderMain.dynamicESP) }

sealed class RenderEvent {
object Upload : Event
object UploadStatic : Event
object UploadDynamic: Event
object Render : Event

class UpdateTarget : ICancellable by Cancellable()
Expand Down
32 changes: 32 additions & 0 deletions src/main/kotlin/com/lambda/event/events/ScreenRenderEvent.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright 2026 Lambda
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package com.lambda.event.events

import com.lambda.event.Event

/**
* Event fired after Minecraft's GUI has been fully rendered.
*
* This fires after guiRenderer.render() in GameRenderer, ensuring that
* any screen-space rendering done in response to this event will appear
* above all of Minecraft's native GUI elements (hotbar, held items, etc.).
*
* Use this event for screen-space rendering that needs to appear on top of
* Minecraft's HUD. For world-space (3D) rendering, use RenderEvent.Render.
*/
object ScreenRenderEvent : Event
Loading