Skip to content

Commit a7864cf

Browse files
chore(render): StorageESP(tracers) & Nametags optimization (#7590)
1 parent d183a60 commit a7864cf

File tree

11 files changed

+132
-85
lines changed

11 files changed

+132
-85
lines changed

gradle/libs.versions.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ httpServer = "2.5.2"
2727
discordIpc = "4.0.0"
2828
semver4j = "3.1.0"
2929
ahocorasick = "0.6.3"
30-
fastutil4k = "0.2.3"
30+
fastutil4k = "0.2.5"
3131

3232
# Recommended mods
3333
modmenu = "17.0.0-beta.1"

src/main/java/net/ccbluex/liquidbounce/injection/mixins/blaze3d/MixinRenderSystem.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
import com.mojang.blaze3d.platform.Window;
2424
import com.mojang.blaze3d.systems.RenderSystem;
2525
import net.ccbluex.liquidbounce.render.ClientTesselator;
26+
import net.ccbluex.liquidbounce.render.GrowableMappableRingBuffer;
27+
import net.minecraft.client.renderer.MappableRingBuffer;
2628
import org.spongepowered.asm.mixin.Mixin;
2729
import org.spongepowered.asm.mixin.injection.At;
2830
import org.spongepowered.asm.mixin.injection.Inject;
@@ -34,6 +36,12 @@ public abstract class MixinRenderSystem {
3436
@Inject(method = "flipFrame", at = @At("RETURN"))
3537
private static void onFlipFrame(Window window, TracyFrameCapture tracyFrameCapture, CallbackInfo ci) {
3638
ClientTesselator.Shared.clear();
39+
if (!GrowableMappableRingBuffer.DISCARD_QUEUE.isEmpty()) {
40+
for (MappableRingBuffer mappableRingBuffer : GrowableMappableRingBuffer.DISCARD_QUEUE) {
41+
mappableRingBuffer.close();
42+
}
43+
GrowableMappableRingBuffer.DISCARD_QUEUE.clear();
44+
}
3745
}
3846

3947
}

src/main/kotlin/net/ccbluex/liquidbounce/config/types/nesting/Configurable.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ open class Configurable(
408408
vararg default: T,
409409
canBeNone: Boolean = true,
410410
) where T : Enum<T>, T : NamedChoice =
411-
multiEnumChoice(name, enumSetOf(elements = default), canBeNone = canBeNone)
411+
multiEnumChoice(name, default.toEnumSet(), canBeNone = canBeNone)
412412

413413
inline fun <reified T> multiEnumChoice(
414414
name: String,

src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/ModuleCombineMobs.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ object ModuleCombineMobs : ClientModule("CombineMobs", Category.RENDER) {
9191
}
9292

9393
fun getCombinedCount(entity: Entity): Int {
94+
if (!running) return 1
95+
9496
val key = keyFor(entity)
9597
val pos = entity.blockPosition().asLong()
9698

src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/ModuleStorageESP.kt

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -113,15 +113,19 @@ object ModuleStorageESP : ClientModule("StorageESP", Category.RENDER, aliases =
113113
object Pot : ChestType("Pot", Color4b(209, 134, 0))
114114
}
115115

116+
private val allTypes = arrayOf(
117+
ChestType.Chest,
118+
ChestType.EnderChest,
119+
ChestType.Furnace,
120+
ChestType.BrewingStand,
121+
ChestType.Dispenser,
122+
ChestType.Hopper,
123+
ChestType.ShulkerBox,
124+
ChestType.Pot,
125+
)
126+
116127
init {
117-
tree(ChestType.Chest)
118-
tree(ChestType.EnderChest)
119-
tree(ChestType.Furnace)
120-
tree(ChestType.BrewingStand)
121-
tree(ChestType.Dispenser)
122-
tree(ChestType.Hopper)
123-
tree(ChestType.ShulkerBox)
124-
tree(ChestType.Pot)
128+
allTypes.forEach { tree(it) }
125129
}
126130

127131
private val requiresChestStealer by boolean("RequiresChestStealer", false)
@@ -327,9 +331,10 @@ object ModuleStorageESP : ClientModule("StorageESP", Category.RENDER, aliases =
327331

328332
@Suppress("unused")
329333
private val renderHandler = handler<WorldRenderEvent> { event ->
330-
if (StorageScanner.isEmpty()) {
331-
return@handler
332-
}
334+
if (StorageScanner.isEmpty()) return@handler
335+
336+
val types = allTypes.filter { it.tracers && !it.color.isTransparent }
337+
if (types.isEmpty()) return@handler
333338

334339
renderEnvironmentForWorld(event.matrixStack) {
335340
val eyeVector = Vec3f(0.0, 0.0, 1.0)
@@ -338,11 +343,13 @@ object ModuleStorageESP : ClientModule("StorageESP", Category.RENDER, aliases =
338343

339344
startBatch()
340345
longLines {
341-
for ((blockPos, type) in StorageScanner.iterate()) {
342-
if (!type.tracers || type.color.isTransparent || !type.shouldRender(blockPos)) continue
343-
val pos = relativeToCamera(blockPos.center).toVec3f()
346+
for (type in types) {
347+
for (blockPos in StorageScanner.iterate(type)) {
348+
if (!type.shouldRender(blockPos)) continue
349+
val pos = relativeToCamera(blockPos.center).toVec3f()
344350

345-
drawLine(eyeVector, pos, type.color.argb)
351+
drawLine(eyeVector, pos, type.color.argb)
352+
}
346353
}
347354
}
348355
commitBatch()

src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/nametags/ModuleNametags.kt

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
*/
1919
package net.ccbluex.liquidbounce.features.module.modules.render.nametags
2020

21+
import net.ccbluex.fastutil.Pool
2122
import net.ccbluex.liquidbounce.event.events.OverlayRenderEvent
2223
import net.ccbluex.liquidbounce.event.handler
2324
import net.ccbluex.liquidbounce.features.module.Category
@@ -54,11 +55,12 @@ object ModuleNametags : ClientModule("Nametags", Category.RENDER) {
5455
val fontRenderer
5556
get() = FontManager.FONT_RENDERER
5657

57-
private val nametagsToRender = mutableListOf<Nametag>()
58+
private val nametagsToRender = mutableListOf<NametagRenderState>()
59+
private val nametagPool = Pool(::NametagRenderState, NametagRenderState::clear)
5860

5961
override fun onDisabled() {
6062
RenderedEntities.unsubscribe(this)
61-
nametagsToRender.clear()
63+
nametagPool.recycleAll(nametagsToRender)
6264
}
6365

6466
override fun onEnabled() {
@@ -87,9 +89,10 @@ object ModuleNametags : ClientModule("Nametags", Category.RENDER) {
8789

8890
/**
8991
* Collects all entities that should be rendered, gets the screen position, where the name tag should be displayed,
90-
* add what should be rendered ([Nametag]). The nametags are sorted in order of rendering.
92+
* add what should be rendered. The nametags are sorted in order of rendering.
9193
*/
9294
private fun collectAndSortNametagsToRender() {
95+
nametagPool.recycleAll(nametagsToRender)
9396
nametagsToRender.clear()
9497
val maximumDistanceSquared = maximumDistance.sq()
9598

@@ -98,13 +101,13 @@ object ModuleNametags : ClientModule("Nametags", Category.RENDER) {
98101
continue
99102
}
100103

101-
nametagsToRender += Nametag(entity)
104+
nametagsToRender += nametagPool.borrow().update(entity)
102105
}
103106
nametagsToRender.sortWith(NAMETAG_COMPARATOR)
104107
}
105108

106-
private val NAMETAG_COMPARATOR = Comparator.comparingDouble<Nametag> { nametag ->
107-
nametag.entity.distanceToSqr(mc.cameraEntity!!)
109+
private val NAMETAG_COMPARATOR = Comparator.comparingDouble<NametagRenderState> { nametag ->
110+
nametag.entity!!.distanceToSqr(mc.cameraEntity!!)
108111
}
109112

110113
fun shouldRenderVanillaNametag(state: EntityRenderState): Boolean {

src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/nametags/Nametag.kt renamed to src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/nametags/NametagRenderState.kt

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,39 +21,47 @@ package net.ccbluex.liquidbounce.features.module.modules.render.nametags
2121
import net.ccbluex.liquidbounce.render.engine.type.Vec3f
2222
import net.ccbluex.liquidbounce.utils.entity.interpolateCurrentPosition
2323
import net.ccbluex.liquidbounce.utils.render.WorldToScreen
24+
import net.ccbluex.liquidbounce.utils.text.PlainText
2425
import net.minecraft.world.entity.Entity
2526
import net.minecraft.world.entity.LivingEntity
2627
import net.minecraft.world.item.ItemStack
2728
import net.minecraft.network.chat.Component
2829

29-
class Nametag private constructor(
30-
val entity: Entity,
31-
/**
32-
* The text to render as nametag
33-
*/
34-
val text: Component,
35-
/**
36-
* The items that should be rendered above the name tag
37-
*/
38-
val items: List<ItemStack>
39-
) {
30+
class NametagRenderState {
31+
@JvmField
32+
var entity: Entity? = null
4033

34+
@JvmField
35+
var text: Component = PlainText.EMPTY
36+
37+
@JvmField
38+
var items: List<ItemStack> = emptyList()
39+
40+
@JvmField
4141
var screenPos: Vec3f? = null
42-
private set
4342

44-
constructor(entity: LivingEntity) : this(
45-
entity,
46-
NametagTextFormatter.format(entity),
47-
NametagEquipment.createItemList(entity),
48-
)
43+
fun update(entity: Entity) = apply {
44+
this.entity = entity
45+
this.text = NametagTextFormatter.format(entity)
46+
if (entity is LivingEntity) {
47+
this.items = NametagEquipment.createItemList(entity)
48+
}
49+
}
4950

5051
fun calculateScreenPos(tickDelta: Float): Vec3f? {
52+
val entity = this.entity ?: return null
5153
val nametagPos = entity.interpolateCurrentPosition(tickDelta)
5254
.add(0.0, entity.getEyeHeight(entity.pose) + 0.55, 0.0)
5355

5456
screenPos = WorldToScreen.calculateScreenPos(nametagPos)
5557
return screenPos
5658
}
5759

58-
}
60+
fun clear() {
61+
this.entity = null
62+
this.text = PlainText.EMPTY
63+
this.items = emptyList()
64+
this.screenPos = null
65+
}
5966

67+
}

src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/nametags/NametagRenderer.kt

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,11 @@ private const val BACKGROUND_Y_OFFSET_TOP = -0.1f
3737
private const val BACKGROUND_Y_OFFSET_BOTTOM = 1.1f
3838
private const val BACKGROUND_X_PADDING = 0.2f * FONT_SIZE
3939

40-
internal fun GuiGraphics.drawNametag(nametag: Nametag, posX: Float, posY: Float) {
40+
internal fun GuiGraphics.drawNametag(nametag: NametagRenderState, posX: Float, posY: Float) {
41+
val entity = nametag.entity
4142
if (nametag.items.any { !it.isEmpty }) {
4243
val currentItemStackRenderer = if (NametagEquipment.showInfo) {
43-
if (nametag.entity === player) {
44+
if (entity === player) {
4445
ItemStackListRenderer.SingleItemStackRenderer.All
4546
} else {
4647
ItemStackListRenderer.SingleItemStackRenderer.ForOtherPlayer
@@ -89,13 +90,13 @@ internal fun GuiGraphics.drawNametag(nametag: Nametag, posX: Float, posY: Float)
8990
}
9091

9192
// Draw enchantments directly for the entity (regardless of whether items are shown)
92-
if (NametagEnchantmentRenderer.running && nametag.entity is LivingEntity) {
93-
val entityPos = nametag.entity.position()
93+
if (NametagEnchantmentRenderer.running && entity is LivingEntity) {
94+
val entityPos = entity.position()
9495
val worldX = entityPos.x.toFloat()
95-
val worldY = (entityPos.y + nametag.entity.bbHeight + 0.5f).toFloat()
96+
val worldY = (entityPos.y + entity.bbHeight + 0.5f).toFloat()
9697

9798
drawEntityEnchantments(
98-
nametag.entity,
99+
entity,
99100
worldX,
100101
worldY,
101102
)

src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/render/nametags/NametagTextFormatter.kt

Lines changed: 22 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ import net.ccbluex.liquidbounce.features.module.modules.misc.antibot.ModuleAntiB
2525
import net.ccbluex.liquidbounce.features.module.modules.render.ModuleCombineMobs
2626
import net.ccbluex.liquidbounce.utils.text.PlainText
2727
import net.ccbluex.liquidbounce.utils.client.asPlainText
28-
import net.ccbluex.liquidbounce.utils.client.asText
2928
import net.ccbluex.liquidbounce.utils.client.joinToText
3029
import net.ccbluex.liquidbounce.utils.client.player
3130
import net.ccbluex.liquidbounce.utils.client.textOf
@@ -94,28 +93,24 @@ internal object NametagTextFormatter : Configurable("Text") {
9493
},
9594

9695
NAME("Name") {
97-
override fun apply(entity: Entity): Component = buildList(4) {
98-
val name = entity.displayName
99-
val nameColor = entity.nameColor
100-
101-
if (entity is LivingEntity && entity.isBaby) {
102-
this += BABY_TEXT
103-
}
104-
105-
this += if (nameColor != null) {
106-
name.copy().withColor(nameColor)
107-
} else {
108-
name
96+
override fun apply(entity: Entity): Component {
97+
val isBaby = entity is LivingEntity && entity.isBaby
98+
99+
// Optimized entity.getDisplayName()
100+
val displayName = entity.team?.getFormattedName(entity.name) ?: entity.name
101+
102+
val coloredName = entity.nameColor?.let { nameColor ->
103+
displayName.copy().withColor(nameColor)
104+
} ?: displayName
105+
106+
val count = ModuleCombineMobs.getCombinedCount(entity)
107+
return when {
108+
isBaby && count > 1 -> textOf(BABY_TEXT, coloredName, " ($count)".asPlainText(COUNT_STYLE))
109+
isBaby -> textOf(BABY_TEXT, coloredName)
110+
count > 1 -> textOf(coloredName, " ($count)".asPlainText(COUNT_STYLE))
111+
else -> coloredName
109112
}
110-
111-
if (ModuleCombineMobs.running) {
112-
val count = ModuleCombineMobs.getCombinedCount(entity)
113-
if (count > 1) {
114-
this += PlainText.SPACE
115-
this += ("x $count").asPlainText(COUNT_STYLE)
116-
}
117-
}
118-
}.asText()
113+
}
119114
},
120115

121116
HEALTH("Health") {
@@ -151,16 +146,11 @@ internal object NametagTextFormatter : Configurable("Text") {
151146
private val Entity.isBot get() = ModuleAntiBot.isBot(this)
152147

153148
private val Entity.nameColor: TextColor?
154-
get() {
155-
val tagColor = EntityTaggingManager.getTag(this).color
156-
157-
return when {
158-
isBot -> ChatFormatting.DARK_AQUA.toTextColor()
159-
isInvisible -> ChatFormatting.GOLD.toTextColor()
160-
isShiftKeyDown -> ChatFormatting.DARK_RED.toTextColor()
161-
tagColor != null -> tagColor.toTextColor()
162-
else -> null
163-
}
149+
get() = when {
150+
isBot -> ChatFormatting.DARK_AQUA.toTextColor()
151+
isInvisible -> ChatFormatting.GOLD.toTextColor()
152+
isShiftKeyDown -> ChatFormatting.DARK_RED.toTextColor()
153+
else -> EntityTaggingManager.getTag(this).color?.toTextColor()
164154
}
165155

166156
private fun ChatFormatting.toTextColor(): TextColor {

src/main/kotlin/net/ccbluex/liquidbounce/render/GrowableMappableRingBuffer.kt

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import com.mojang.blaze3d.buffers.GpuBuffer
2424
import com.mojang.blaze3d.buffers.GpuBufferSlice
2525
import net.ccbluex.liquidbounce.utils.client.formatAsCapacity
2626
import net.ccbluex.liquidbounce.utils.client.logger
27-
import net.ccbluex.liquidbounce.utils.client.mc
2827
import net.ccbluex.liquidbounce.utils.render.mapBuffer
2928
import net.minecraft.client.renderer.MappableRingBuffer
3029
import org.lwjgl.system.MemoryUtil
@@ -48,7 +47,7 @@ import java.nio.ByteBuffer
4847
class GrowableMappableRingBuffer @JvmOverloads constructor(
4948
val label: String,
5049
val usage: @GpuBuffer.Usage Int,
51-
val growPolicy: GrowPolicy = GrowPolicy.of(paddingScale = 7, min = 0), // 128 bytes padding
50+
val growPolicy: GrowPolicy = GrowPolicy.DEFAULT,
5251
) {
5352

5453
private var ring: MappableRingBuffer? = null
@@ -71,7 +70,7 @@ class GrowableMappableRingBuffer @JvmOverloads constructor(
7170
val newSize = growPolicy.getNewSize(minSize, current?.size() ?: 0)
7271
current?.let {
7372
// Defer closing the old ring buffer to avoid races with GPU usage.
74-
mc.schedule(it::close)
73+
DISCARD_QUEUE.add(it)
7574
}
7675
ring = MappableRingBuffer(
7776
Suppliers.ofInstance(label),
@@ -162,6 +161,12 @@ class GrowableMappableRingBuffer @JvmOverloads constructor(
162161
fun getNewSize(requested: Int, current: Int): Int
163162

164163
companion object {
164+
/**
165+
* 128 bytes padding, minimum 0
166+
*/
167+
@JvmField
168+
val DEFAULT = of(paddingScale = 7, min = 0)
169+
165170
@JvmStatic
166171
fun of(paddingScale: Int, min: Int) = GrowPolicy { requested, current ->
167172
val base = maxOf(min, requested, current)
@@ -170,5 +175,15 @@ class GrowableMappableRingBuffer @JvmOverloads constructor(
170175
}
171176
}
172177
}
178+
179+
companion object {
180+
/**
181+
* [MappableRingBuffer] to be closed.
182+
*
183+
* @see net.ccbluex.liquidbounce.injection.mixins.blaze3d.MixinRenderSystem.onFlipFrame
184+
*/
185+
@JvmField
186+
val DISCARD_QUEUE = ArrayDeque<MappableRingBuffer>()
187+
}
173188
}
174189

0 commit comments

Comments
 (0)