Skip to content

Commit

Permalink
refactor/fix(legacy): HUD config & memory leak in writeJson/readJson (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
MukjepScarlet authored Dec 22, 2024
1 parent 64dcde0 commit 921f2e8
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 86 deletions.
103 changes: 51 additions & 52 deletions src/main/java/net/ccbluex/liquidbounce/file/configs/HudConfig.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ package net.ccbluex.liquidbounce.file.configs
import com.google.gson.JsonArray
import com.google.gson.JsonObject
import net.ccbluex.liquidbounce.file.FileConfig
import net.ccbluex.liquidbounce.file.FileManager.PRETTY_GSON
import net.ccbluex.liquidbounce.ui.client.hud.HUD
import net.ccbluex.liquidbounce.ui.client.hud.element.ElementInfo
import net.ccbluex.liquidbounce.ui.client.hud.element.Side
import net.ccbluex.liquidbounce.utils.client.ClientUtils
import net.ccbluex.liquidbounce.config.FontValue
import net.ccbluex.liquidbounce.utils.io.json
import net.ccbluex.liquidbounce.utils.io.jsonArray
import net.ccbluex.liquidbounce.utils.io.readJson
import net.ccbluex.liquidbounce.utils.io.writeJson
import java.io.File
import java.io.IOException

Expand All @@ -28,57 +30,56 @@ class HudConfig(file: File) : FileConfig(file) {
*/
@Throws(IOException::class)
override fun loadConfig() {
val jsonArray = PRETTY_GSON.fromJson(file.bufferedReader(), JsonArray::class.java)
val jsonArray = file.readJson().takeIf { it is JsonArray } as? JsonArray ?: return

HUD.clearElements()

try {
for (jsonObject in jsonArray) {
try {
if (jsonObject !is JsonObject)
continue

if (!jsonObject.has("Type"))
continue
if (jsonObject !is JsonObject)
continue

val type = jsonObject["Type"].asString
if (!jsonObject.has("Type"))
continue

for (elementClass in HUD.ELEMENTS) {
val classType = elementClass.getAnnotation(ElementInfo::class.java).name
val type = jsonObject["Type"].asString

if (classType == type) {
val element = elementClass.newInstance()
try {
val elementClass = HUD.ELEMENTS.entries.find { it.value.name == type }?.key

element.x = jsonObject["X"].asDouble
element.y = jsonObject["Y"].asDouble
element.scale = jsonObject["Scale"].asFloat
element.side = Side(
Side.Horizontal.getByName(jsonObject["HorizontalFacing"].asString) ?: Side.Horizontal.RIGHT,
Side.Vertical.getByName(jsonObject["VerticalFacing"].asString) ?: Side.Vertical.UP
)
if (elementClass == null) {
ClientUtils.LOGGER.warn("Unrecognized HUD element: '$type'")
continue
}

for (value in element.values) {
if (jsonObject.has(value.name))
value.fromJson(jsonObject[value.name])
}
val element = elementClass.newInstance()

// Support for old HUD files
if (jsonObject.has("font"))
element.values.find { it is FontValue }?.fromJson(jsonObject["font"])
element.x = jsonObject["X"].asDouble
element.y = jsonObject["Y"].asDouble
element.scale = jsonObject["Scale"].asFloat
element.side = Side(
Side.Horizontal.getByName(jsonObject["HorizontalFacing"].asString) ?: Side.Horizontal.RIGHT,
Side.Vertical.getByName(jsonObject["VerticalFacing"].asString) ?: Side.Vertical.UP
)

HUD.addElement(element)
break
}
for (value in element.values) {
if (jsonObject.has(value.name))
value.fromJson(jsonObject[value.name])
}

// Support for old HUD files
if (jsonObject.has("font"))
element.values.find { it is FontValue }?.fromJson(jsonObject["font"])

HUD.addElement(element)
} catch (e: Exception) {
ClientUtils.LOGGER.error("Error while loading custom hud element from config.", e)
ClientUtils.LOGGER.error("Error while loading custom HUD element '$type' from config.", e)
}
}

// Add forced elements when missing
for (elementClass in HUD.ELEMENTS) {
if (elementClass.getAnnotation(ElementInfo::class.java).force
&& HUD.elements.none { it.javaClass == elementClass }) {
for ((elementClass, info) in HUD.ELEMENTS) {
if (info.force && HUD.elements.none { it.javaClass == elementClass }) {
HUD.addElement(elementClass.newInstance())
}
}
Expand All @@ -95,25 +96,23 @@ class HudConfig(file: File) : FileConfig(file) {
*/
@Throws(IOException::class)
override fun saveConfig() {
val jsonArray = JsonArray()

for (element in HUD.elements) {
val elementObject = JsonObject()
elementObject.run {
addProperty("Type", element.name)
addProperty("X", element.x)
addProperty("Y", element.y)
addProperty("Scale", element.scale)
addProperty("HorizontalFacing", element.side.horizontal.sideName)
addProperty("VerticalFacing", element.side.vertical.sideName)
val jsonArray = jsonArray {
for (element in HUD.elements) {
+json {
"Type" to element.name
"X" to element.x
"Y" to element.y
"Scale" to element.scale
"HorizontalFacing" to element.side.horizontal.sideName
"VerticalFacing" to element.side.vertical.sideName

element.values.forEach {
it.name to it.toJson()
}
}
}

for (value in element.values)
elementObject.add(value.name, value.toJson())

jsonArray.add(elementObject)
}

file.writeText(PRETTY_GSON.toJson(jsonArray))
file.writeJson(jsonArray)
}
}
8 changes: 7 additions & 1 deletion src/main/java/net/ccbluex/liquidbounce/ui/client/hud/HUD.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package net.ccbluex.liquidbounce.ui.client.hud

import net.ccbluex.liquidbounce.ui.client.hud.designer.GuiHudDesigner
import net.ccbluex.liquidbounce.ui.client.hud.element.Element
import net.ccbluex.liquidbounce.ui.client.hud.element.ElementInfo
import net.ccbluex.liquidbounce.ui.client.hud.element.elements.*
import net.ccbluex.liquidbounce.ui.client.hud.element.elements.Target
import net.ccbluex.liquidbounce.utils.client.ClientUtils.LOGGER
Expand All @@ -15,6 +16,7 @@ import net.ccbluex.liquidbounce.utils.extensions.component1
import net.ccbluex.liquidbounce.utils.extensions.component2
import net.minecraft.client.gui.ScaledResolution
import org.lwjgl.opengl.GL11.*
import java.util.*
import kotlin.math.max
import kotlin.math.min

Expand All @@ -23,7 +25,7 @@ object HUD : MinecraftInstance {
val elements = mutableListOf<Element>()
val notifications = mutableListOf<Notification>()

val ELEMENTS = arrayOf(
private val ALL_ELEMENT_CLASSES = arrayOf(
Armor::class.java,
Arraylist::class.java,
Effects::class.java,
Expand All @@ -43,6 +45,10 @@ object HUD : MinecraftInstance {
Keystrokes::class.java
)

val ELEMENTS = ALL_ELEMENT_CLASSES.associateWithTo(IdentityHashMap(ALL_ELEMENT_CLASSES.size)) {
it.getAnnotation(ElementInfo::class.java)
}

/** Create default HUD */
fun setDefault() {
elements.clear()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,7 @@ class EditorPanel(private val hudDesigner: GuiHudDesigner, var x: Int, var y: In
realHeight = 15
width = 90

for (element in ELEMENTS) {
val info = element.getAnnotation(ElementInfo::class.java) ?: continue

for ((element, info) in ELEMENTS) {
if (info.single && HUD.elements.any { it.javaClass == element }) continue

val name = info.name
Expand Down
46 changes: 21 additions & 25 deletions src/main/java/net/ccbluex/liquidbounce/ui/font/GameFontRenderer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class GameFontRenderer(font: Font) : FontRenderer(
fun drawCenteredString(s: String, x: Float, y: Float, color: Int, shadow: Boolean) = drawString(s, x - getStringWidth(s) / 2F, y, color, shadow)

fun drawCenteredString(s: String, x: Float, y: Float, color: Int) =
drawStringWithShadow(s, x - getStringWidth(s) / 2F, y, color)
drawStringWithShadow(s, x - getStringWidth(s) / 2F, y, color)

override fun drawString(text: String, x: Float, y: Float, color: Int, shadow: Boolean): Int {
glEnable(GL_BLEND)
Expand Down Expand Up @@ -100,8 +100,8 @@ class GameFontRenderer(font: Font) : FontRenderer(

val alpha = (currentColor shr 24 and 0xff)

if ("§" in text) {
val parts = text.split("§")
if ('§' in text) {
val parts = text.split('§')

var currentFont = defaultFont

Expand Down Expand Up @@ -168,26 +168,24 @@ class GameFontRenderer(font: Font) : FontRenderer(
}
}

currentFont = if (bold && italic)
boldItalicFont
else if (bold)
boldFont
else if (italic)
italicFont
else
defaultFont
currentFont = when {
bold && italic -> boldItalicFont
bold -> boldFont
italic -> italicFont
else -> defaultFont
}

currentFont.drawString(if (randomCase) ColorUtils.randomMagicText(words) else words, width, 0.0, currentColor)

if (strikeThrough)
drawLine(width / 2.0 + 1, currentFont.height / 3.0,
(width + currentFont.getStringWidth(words)) / 2.0 + 1, currentFont.height / 3.0,
fontHeight / 16F)
(width + currentFont.getStringWidth(words)) / 2.0 + 1, currentFont.height / 3.0,
fontHeight / 16F)

if (underline)
drawLine(width / 2.0 + 1, currentFont.height / 2.0,
(width + currentFont.getStringWidth(words)) / 2.0 + 1, currentFont.height / 2.0,
fontHeight / 16F)
(width + currentFont.getStringWidth(words)) / 2.0 + 1, currentFont.height / 2.0,
fontHeight / 16F)

width += currentFont.getStringWidth(words)
}
Expand All @@ -209,8 +207,8 @@ class GameFontRenderer(font: Font) : FontRenderer(
override fun getStringWidth(text: String): Int {
val currentText = NameProtect.handleTextMessage(text)

return if ("§" in currentText) {
val parts = currentText.split("§")
return if ('§' in currentText) {
val parts = currentText.split('§')

var currentFont = defaultFont
var width = 0
Expand Down Expand Up @@ -241,14 +239,12 @@ class GameFontRenderer(font: Font) : FontRenderer(
}
}

currentFont = if (bold && italic)
boldItalicFont
else if (bold)
boldFont
else if (italic)
italicFont
else
defaultFont
currentFont = when {
bold && italic -> boldItalicFont
bold -> boldFont
italic -> italicFont
else -> defaultFont
}

width += currentFont.getStringWidth(words)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ import java.io.File

private val parser = JsonParser()

fun File.writeJson(content: JsonElement, gson: Gson = PRETTY_GSON) = gson.toJson(content, bufferedWriter())
fun File.writeJson(content: JsonElement, gson: Gson = PRETTY_GSON) = bufferedWriter().use { gson.toJson(content, it) }

fun File.writeJson(content: Any?, gson: Gson = PRETTY_GSON) = gson.toJson(content, bufferedWriter())
fun File.writeJson(content: Any?, gson: Gson = PRETTY_GSON) = bufferedWriter().use { gson.toJson(content, it) }

fun File.readJson(): JsonElement = parser.parse(bufferedReader())
fun File.readJson(): JsonElement = bufferedReader().use { parser.parse(it) }

fun File.sha256(): String = DigestUtils.sha256Hex(inputStream())
fun File.sha256(): String = inputStream().use { DigestUtils.sha256Hex(it) }

val File.isEmpty: Boolean get() = length() == 0L
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package net.ccbluex.liquidbounce.utils.io
import com.google.gson.*
import com.google.gson.reflect.TypeToken
import net.ccbluex.liquidbounce.file.FileManager.PRETTY_GSON
import java.io.File

private val EMPTY_JSON_ARRAY = JsonArray()

Expand Down Expand Up @@ -32,6 +31,21 @@ class JsonObjectBuilder {
backend.addProperty(this, value)
}

/**
* Fallback
*/
infix fun String.to(value: Any?) {
when (value) {
null -> backend.add(this, JsonNull.INSTANCE)
is String -> backend.addProperty(this, value)
is Number -> backend.addProperty(this, value)
is Boolean -> backend.addProperty(this, value)
is JsonElement -> backend.add(this, value)
is JsonObjectBuilder -> backend.add(this, value.build())
else -> throw IllegalArgumentException("Unsupported type: ${value::class.java}")
}
}

fun build() = backend
}

Expand Down

0 comments on commit 921f2e8

Please sign in to comment.