Skip to content

Commit

Permalink
Add features for dynamic atlas allocation, add more than just ascii c…
Browse files Browse the repository at this point in the history
…haracters to the default font, add text processing for minecraft text, liquid bounce font for bed plates and improve bed plates depth management (#3879)
  • Loading branch information
superblaubeere27 committed Sep 5, 2024
1 parent 4758fb7 commit d023dc1
Show file tree
Hide file tree
Showing 19 changed files with 1,104 additions and 493 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ import net.ccbluex.liquidbounce.event.events.OverlayRenderEvent
import net.ccbluex.liquidbounce.event.handler
import net.ccbluex.liquidbounce.features.module.Category
import net.ccbluex.liquidbounce.features.module.Module
import net.ccbluex.liquidbounce.render.Fonts
import net.ccbluex.liquidbounce.render.GUIRenderEnvironment
import net.ccbluex.liquidbounce.render.engine.Color4b
import net.ccbluex.liquidbounce.render.engine.font.FontRenderer
import net.ccbluex.liquidbounce.render.engine.font.FontRendererBuffers
import net.ccbluex.liquidbounce.render.renderEnvironmentForGUI
import net.ccbluex.liquidbounce.utils.block.AbstractBlockLocationTracker
import net.ccbluex.liquidbounce.utils.block.ChunkScanner
Expand All @@ -13,7 +17,6 @@ import net.ccbluex.liquidbounce.utils.render.WorldToScreen
import net.minecraft.block.*
import net.minecraft.client.gui.DrawContext
import net.minecraft.item.ItemStack
import net.minecraft.item.Items
import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.Vec3d
import kotlin.math.abs
Expand Down Expand Up @@ -46,27 +49,53 @@ object ModuleBedPlates : Module("BedPlates", Category.RENDER) {
val maxLayers by int("MaxLayers", 5, 1..5)
val scale by float("Scale", 1.5f, 0.5f..3.0f)

val fontRenderer: FontRenderer
get() = Fonts.DEFAULT_FONT.get()

val renderHandler = handler<OverlayRenderEvent> {
val fontBuffers = FontRendererBuffers()

renderEnvironmentForGUI {
synchronized(BlockTracker.trackedBlockMap) {
val trackedBlockMap = BlockTracker.trackedBlockMap

for ((_, trackState) in trackedBlockMap) {
val bedPlates = trackState.bedPlates
with(matrixStack) {
push()
try {
renderBedPlates(trackState, bedPlates)
} finally {
pop()
val playerPos = player.blockPos

try {
synchronized(BlockTracker.trackedBlockMap) {
val trackedBlockMap = BlockTracker.trackedBlockMap.entries.sortedByDescending {
val bp = BlockPos(it.key.x, it.key.y, it.key.z)

bp.getSquaredDistance(playerPos)
}

val env = this

trackedBlockMap.forEachIndexed { idx, (_, trackState) ->
val bedPlates = trackState.bedPlates
with(matrixStack) {
push()
try {
val z = idx.toFloat() / trackedBlockMap.size.toFloat()

renderBedPlates(env, trackState, fontBuffers, bedPlates, z * 1000.0F)
} finally {
pop()
}
}

}
}
} finally {
fontBuffers.draw(fontRenderer)
}
}
}

private fun renderBedPlates(trackState: TrackedState, bedPlates: List<Block>) {
private fun renderBedPlates(
env: GUIRenderEnvironment,
trackState: TrackedState,
fontBuffers: FontRendererBuffers,
bedPlates: List<Block>,
z: Float
) {
val screenPos = WorldToScreen.calculateScreenPos(
pos = trackState.centerPos,
) ?: return
Expand All @@ -81,28 +110,42 @@ object ModuleBedPlates : Module("BedPlates", Category.RENDER) {
val bedDistance = mc.player?.pos?.distanceTo(trackState.centerPos) ?: 0.0
val text = "Bed (${bedDistance.roundToInt()}m)"

val width = max(bedPlates.size * ITEM_SIZE + ITEM_SIZE, mc.textRenderer.getWidth(text))
val height = ITEM_SIZE + mc.textRenderer.fontHeight
dc.matrices.translate(-width / 2f, -height / 2f, 0.0f)
val c = Fonts.DEFAULT_FONT_SIZE.toFloat()

val scale = 1.0F / (c * 0.15F) * scale

val processedText = fontRenderer.process(text, defaultColor = Color4b.WHITE)
val stringWidth = fontRenderer.getStringWidth(processedText)

val width = max(bedPlates.size * ITEM_SIZE + ITEM_SIZE, (stringWidth * scale * 0.75f).toInt())
val height = ITEM_SIZE + fontRenderer.height * scale
dc.matrices.translate(-width / 2f, -height / 2f, z)

// draw background
dc.fill(
-BACKGROUND_PADDING,
-BACKGROUND_PADDING,
width + BACKGROUND_PADDING,
height + BACKGROUND_PADDING,
(height + BACKGROUND_PADDING).toInt(),
Color4b(0, 0, 0, 128).toRGBA()
)

// draw text
dc.drawTextWithShadow(
mc.textRenderer,
text,
width / 2 - mc.textRenderer.getWidth(text) / 2,
0,
Color4b.WHITE.toRGBA()
fontRenderer.draw(
processedText,
-stringWidth / 2.0f,
0.0f
)

env.matrixStack.push()

env.matrixStack.translate(screenPos.x, screenPos.y, z)
env.matrixStack.translate(0.0f, -height + fontRenderer.height * scale - 6.0F, 0.0f)
env.matrixStack.scale(scale, scale, 1.0F)

fontRenderer.commit(env, fontBuffers)

env.matrixStack.pop()

// draw items
val itemStartX = width / 2 - (bedPlates.size + 1) * ITEM_SIZE / 2
dc.drawItem(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ object ModuleNametags : Module("Nametags", Category.RENDER) {

nametagsToRender.forEachIndexed { index, (pos, nametagInfo) ->
// We want nametags that are closer to the player to be rendered above nametags that are further away.
val renderZ = index / nametagsToRender.size.toFloat()
val renderZ = index / nametagsToRender.size.toFloat() * 1000.0F

nametagRenderer.drawNametag(this, nametagInfo, Vec3(pos.x, pos.y, renderZ))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,13 @@ import net.ccbluex.liquidbounce.utils.item.isNothing
import net.minecraft.entity.Entity
import net.minecraft.entity.LivingEntity
import net.minecraft.item.ItemStack
import net.minecraft.text.Text

class NametagInfo(
/**
* The text to render as nametag
*/
val text: String,
val text: Text,
/**
* The items that should be rendered above the name tag
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ class NametagRenderer {

val x =
ModuleNametags.fontRenderer.draw(
info.text,
ModuleNametags.fontRenderer.process(info.text),
0.0F,
0.0F,
shadow = true,
Expand Down Expand Up @@ -102,6 +102,16 @@ class NametagRenderer {
dc.matrices.scale(ITEM_SCALE * ModuleNametags.scale, ITEM_SCALE * ModuleNametags.scale, 1.0F)
dc.matrices.translate(-itemsToRender.size * ITEM_SIZE / 2.0F, -ITEM_SIZE.toFloat(), 0.0F)

dc.fill(
0,
0,
itemsToRender.size * ITEM_SIZE,
ITEM_SIZE,
Color4b.BLACK.alpha(0).toRGBA()
)

dc.matrices.translate(0.0F, 0.0F, 100.0F)

itemsToRender.forEachIndexed { index, itemStack ->
dc.drawItem(itemStack, index * ITEM_SIZE, 0)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,101 +18,115 @@
*/
package net.ccbluex.liquidbounce.features.module.modules.render.nametags

import net.ccbluex.liquidbounce.features.module.modules.misc.ModuleNameProtect
import net.ccbluex.liquidbounce.features.module.modules.misc.ModuleTeams
import net.ccbluex.liquidbounce.features.module.modules.misc.antibot.ModuleAntiBot
import net.ccbluex.liquidbounce.features.module.modules.render.ModuleESP
import net.ccbluex.liquidbounce.features.module.modules.misc.sanitizeWithNameProtect
import net.ccbluex.liquidbounce.utils.client.asText
import net.ccbluex.liquidbounce.utils.client.mc
import net.ccbluex.liquidbounce.utils.client.regular
import net.ccbluex.liquidbounce.utils.client.withColor
import net.ccbluex.liquidbounce.utils.combat.EntityTaggingManager
import net.ccbluex.liquidbounce.utils.entity.getActualHealth
import net.ccbluex.liquidbounce.utils.entity.ping
import net.minecraft.entity.Entity
import net.minecraft.entity.LivingEntity
import net.minecraft.entity.player.PlayerEntity
import net.minecraft.text.MutableText
import net.minecraft.text.Text
import net.minecraft.text.TextColor
import net.minecraft.util.Formatting
import kotlin.math.roundToInt

class NametagTextFormatter(private val entity: Entity) {
fun format(): String {
val outputBuilder = StringBuilder()
fun format(): Text {
val outputText = Text.empty()

if (ModuleNametags.distance) {
outputBuilder.append(this.distanceText).append(" ")
outputText.append(this.distanceText).append(" ")
}
if (ModuleNametags.ping) {
outputBuilder.append(this.pingText).append(" ")
outputText.append(this.pingText).append(" ")
}

outputBuilder.append("${this.nameColor}${ModuleNameProtect.replace(entity.displayName!!.string)}")
val nameString = entity.displayName!!.sanitizeWithNameProtect().string

outputText.append(nameString.asText().styled { it.withColor(this.nameColor) })

if (ModuleNametags.Health.enabled) {
outputBuilder.append(" ").append(this.healthText)
outputText.append(" ").append(this.healthText)
}

if (this.isBot) {
outputBuilder.append(" §c§lBot")
outputText.append(" ").append("Bot".asText().styled { it.withColor(Formatting.RED).withBold(true) })
}

return outputBuilder.toString()
return outputText
}

private val isBot = ModuleAntiBot.isBot(entity)

private val nameColor: String
private val nameColor: TextColor
get() {
val teamColor = if (ModuleTeams.enabled) {
ModuleTeams.getTeamColor(this.entity)
} else {
null
}
val tagColor = EntityTaggingManager.getTag(this.entity).color

return when {
isBot -> "§3"
entity.isInvisible -> "§6"
entity.isSneaking -> "§4"
teamColor != null -> "§${teamColor.closestFormattingCode()}"
else -> "§7"
isBot -> Formatting.DARK_AQUA.toTextColor()
entity.isInvisible -> Formatting.GOLD.toTextColor()
entity.isSneaking -> Formatting.DARK_RED.toTextColor()
tagColor != null -> TextColor.fromRgb(tagColor.toRGBA())
else -> Formatting.GRAY.toTextColor()
}
}

private val distanceText: String
private val distanceText: Text
get() {
val playerDistanceRounded = mc.player!!.distanceTo(entity).roundToInt()

return "§7${playerDistanceRounded}m"
return withColor("${playerDistanceRounded}m", Formatting.GRAY)
}

private fun getPing(entity: Entity): Int? {
return (entity as? PlayerEntity)?.ping
}

private val pingText: String
private val pingText: Text
get() {
val playerPing = getPing(entity) ?: return ""
val playerPing = getPing(entity) ?: return Text.of("")

val coloringBasedOnPing = when {
playerPing > 200 -> "§c"
playerPing > 100 -> "§e"
else -> "§a"
playerPing > 200 -> Formatting.RED
playerPing > 100 -> Formatting.YELLOW
else -> Formatting.GREEN
}

return " §7[" + coloringBasedOnPing + playerPing + "ms§7]"
return regular(" [") + withColor(playerPing.toString() + "ms", coloringBasedOnPing) + regular("]")
}

private val healthText: String
private val healthText: Text
get() {
if (entity !is LivingEntity) {
return ""
return regular("")
}

val actualHealth = entity.getActualHealth(ModuleNametags.Health.fromScoreboard).toInt()

val healthColor = when {
// Perhaps you should modify the values here
actualHealth >= 14 -> "§a"
actualHealth >= 8 -> "§e"
else -> "§c"
actualHealth >= 14 -> Formatting.GREEN
actualHealth >= 8 -> Formatting.YELLOW
else -> Formatting.RED
}

return "$healthColor$actualHealth HP"
return withColor("$actualHealth HP", healthColor)

}
}

private fun Formatting.toTextColor(): TextColor {
return TextColor(this.colorValue!!, this.name)
}

operator fun MutableText.plus(text: MutableText): MutableText {
this.append(text)

return this
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,12 @@ package net.ccbluex.liquidbounce.render

import net.ccbluex.liquidbounce.render.engine.Color4b
import net.ccbluex.liquidbounce.render.engine.font.FontRendererBuffers
import net.ccbluex.liquidbounce.render.engine.font.processor.LegacyTextProcessor
import net.ccbluex.liquidbounce.render.engine.font.processor.TextProcessor
import net.minecraft.text.Text
import kotlin.random.Random

abstract class AbstractFontRenderer {
abstract class AbstractFontRenderer<T> {
abstract val size: Float
abstract val height: Float

Expand All @@ -39,15 +43,18 @@ abstract class AbstractFontRenderer {
*/
@Suppress("LongParameterList")
abstract fun draw(
text: String,
text: T,
x0: Float,
y0: Float,
defaultColor: Color4b = Color4b.WHITE,
shadow: Boolean = false,
z: Float = 0.0f,
scale: Float = 1.0f
): Float

abstract fun process(text: String, defaultColor: Color4b = Color4b.WHITE): T
abstract fun process(text: Text, defaultColor: Color4b = Color4b.WHITE): T


/**
*/
abstract fun commit(
Expand All @@ -59,7 +66,7 @@ abstract class AbstractFontRenderer {
* Approximates the width of a text. Accurate except for obfuscated (`§k`) formatting
*/
abstract fun getStringWidth(
text: String,
text: TextProcessor.ProcessedText,
shadow: Boolean = false
): Float
}
Loading

0 comments on commit d023dc1

Please sign in to comment.