Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
12 changes: 7 additions & 5 deletions src/main/kotlin/me/odinmain/clickgui/ClickGUI.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import me.odinmain.utils.ui.mouseX
import me.odinmain.utils.ui.mouseY
import me.odinmain.utils.ui.rendering.NVGRenderer
import net.minecraftforge.common.MinecraftForge
import me.odinmain.utils.ui.SearchBar
import kotlin.math.sign

/**
Expand All @@ -25,6 +26,7 @@ import kotlin.math.sign
* @see [Panel]
*/
object ClickGUI : Screen() {
val searchBar = SearchBar()

private val panels: ArrayList<Panel> = arrayListOf<Panel>().apply {
if (Category.entries.any { ClickGUIModule.panelSetting[it] == null }) ClickGUIModule.resetPositions()
Expand All @@ -47,7 +49,7 @@ object ClickGUI : Screen() {
}

for (i in 0 until panels.size) { panels[i].draw(mouseX, mouseY) }
SearchBar.draw(mc.displayWidth / 2f - 175f, mc.displayHeight - 110f, mouseX, mouseY)
searchBar.draw(mc.displayWidth / 2f - 175f, mc.displayHeight - 110f, 350f, 40f, mouseX, mouseY)
desc.render()

NVGRenderer.endFrame()
Expand All @@ -62,24 +64,24 @@ object ClickGUI : Screen() {
}

override fun mouseClicked(x: Int, y: Int, mouseButton: Int) {
SearchBar.mouseClicked(mouseX, mouseY, mouseButton)
searchBar.mouseClicked(mouseX, mouseY, mouseButton)
for (i in panels.size - 1 downTo 0) {
if (panels[i].mouseClicked(mouseX, mouseY, mouseButton)) return
}
super.mouseClicked(x, y, mouseButton)
}

override fun mouseReleased(mouseX: Int, mouseY: Int, state: Int) {
SearchBar.mouseReleased()
searchBar.mouseReleased()
for (i in panels.size - 1 downTo 0) {
panels[i].mouseReleased(state)
}
super.mouseReleased(mouseX, mouseY, state)
}

override fun keyTyped(typedChar: Char, keyCode: Int) {
val searchTyped = SearchBar.keyTyped(typedChar)
val searchPressed = SearchBar.keyPressed(keyCode)
val searchTyped = searchBar.keyTyped(typedChar)
val searchPressed = searchBar.keyPressed(keyCode)
if (searchTyped || searchPressed) return

for (i in panels.size - 1 downTo 0) {
Expand Down
12 changes: 6 additions & 6 deletions src/main/kotlin/me/odinmain/clickgui/Panel.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package me.odinmain.clickgui

import me.odinmain.clickgui.ClickGUI.gray26
import me.odinmain.clickgui.ClickGUI.searchBar
import me.odinmain.clickgui.settings.ModuleButton
import me.odinmain.features.Category
import me.odinmain.features.ModuleManager
Expand All @@ -21,7 +22,6 @@ import kotlin.math.floor
* @see [ModuleButton]
*/
class Panel(private val category: Category) {

val moduleButtons: ArrayList<ModuleButton> = ArrayList<ModuleButton>().apply {
ModuleManager.modules
.filter { it.category == category && (!it.isDevModule || PlayerSize.isRandom) }
Expand Down Expand Up @@ -55,7 +55,7 @@ class Panel(private val category: Category) {
var startY = scrollOffset + HEIGHT
if (panelSetting.extended) {
for (button in moduleButtons) {
if (!button.module.name.contains(SearchBar.currentSearch, true)) continue
if (!button.module.name.contains(searchBar.currentSearch, true)) continue
startY += button.draw(panelSetting.x, startY + panelSetting.y)
}
}
Expand Down Expand Up @@ -84,7 +84,7 @@ class Panel(private val category: Category) {
}
} else if (isMouseOverExtended) {
return moduleButtons.reversed().any {
if (!it.module.name.contains(SearchBar.currentSearch, true)) return@any false
if (!it.module.name.contains(searchBar.currentSearch, true)) return@any false
it.mouseClicked(mouseX, mouseY, button)
}
}
Expand All @@ -96,7 +96,7 @@ class Panel(private val category: Category) {

if (panelSetting.extended)
moduleButtons.reversed().forEach {
if (!it.module.name.contains(SearchBar.currentSearch, true)) return@forEach
if (!it.module.name.contains(searchBar.currentSearch, true)) return@forEach
it.mouseReleased(state)
}
}
Expand All @@ -105,7 +105,7 @@ class Panel(private val category: Category) {
if (!panelSetting.extended) return false

return moduleButtons.reversed().any {
if (!it.module.name.contains(SearchBar.currentSearch, true)) return@any false
if (!it.module.name.contains(searchBar.currentSearch, true)) return@any false
it.keyTyped(typedChar)
}
}
Expand All @@ -114,7 +114,7 @@ class Panel(private val category: Category) {
if (!panelSetting.extended) return false

return moduleButtons.reversed().any {
if (!it.module.name.contains(SearchBar.currentSearch, true)) return@any false
if (!it.module.name.contains(searchBar.currentSearch, true)) return@any false
it.keyPressed(keyCode)
}
}
Expand Down
56 changes: 0 additions & 56 deletions src/main/kotlin/me/odinmain/clickgui/SearchBar.kt

This file was deleted.

2 changes: 1 addition & 1 deletion src/main/kotlin/me/odinmain/features/ModuleManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ object ModuleManager {
//skyblock
NoCursorReset, AutoSprint, BlazeAttunement, ChatCommands, DeployableTimer, DianaHelper,
Ragnarock, MobSpawn, Splits, WardrobeKeybinds, InvincibilityTimer, ItemsHighlight, PlayerDisplay,
FarmKeys, PetKeybinds, CommandKeybinds, SpringBoots, AbilityTimers, SlotBinds,
FarmKeys, PetKeybinds, CommandKeybinds, SpringBoots, AbilityTimers, SlotBinds, SearchBar,

// kuudra
BuildHelper, FreshTools, KuudraDisplay, NoPre, PearlWaypoints, RemovePerks, SupplyHelper, TeamHighlight,
Expand Down
69 changes: 69 additions & 0 deletions src/main/kotlin/me/odinmain/features/impl/skyblock/SearchBar.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package me.odinmain.features.impl.skyblock

import me.odinmain.clickgui.settings.impl.ColorSetting
import me.odinmain.events.impl.GuiEvent
import me.odinmain.features.Module
import me.odinmain.utils.render.Color.Companion.withAlpha
import me.odinmain.utils.render.Colors
import me.odinmain.utils.skyblock.lore
import me.odinmain.utils.ui.SearchBar
import me.odinmain.utils.ui.mouseX
import me.odinmain.utils.ui.mouseY
import me.odinmain.utils.ui.rendering.NVGRenderer
import net.minecraft.client.gui.ScaledResolution
import net.minecraft.client.gui.inventory.GuiContainer
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent

object SearchBar: Module(
name = "Search Bar",
description = "Search bar for inventories."
) {
private val highlightColor by ColorSetting("Highlight Color", Colors.MINECRAFT_BLUE.withAlpha(0.5f), true, desc = "Color of the highlight for matching items.")

private val searchBar = SearchBar()

@SubscribeEvent
fun onRenderInventory(event: GuiEvent.DrawGuiForeground) {
NVGRenderer.beginFrame(mc.displayWidth.toFloat(), mc.displayHeight.toFloat())

searchBar.draw(mc.displayWidth / 2f - 175f, mc.displayHeight - 110f, 350f, 40f, mouseX, mouseY)

val scale = ScaledResolution(mc).scaleFactor.toFloat()
NVGRenderer.scale(scale, scale)

if (searchBar.currentSearch.isNotEmpty()) {
for (inventorySlot in event.gui.inventorySlots.inventorySlots) {
if (inventorySlot?.stack?.displayName?.contains(searchBar.currentSearch, ignoreCase = true) == true || inventorySlot?.stack?.lore?.any { it.contains(searchBar.currentSearch, ignoreCase = true) } == true) {
val slotX = inventorySlot.xDisplayPosition.toFloat() + event.guiLeft
val slotY = inventorySlot.yDisplayPosition.toFloat() + event.guiTop
NVGRenderer.rect(slotX, slotY, 16f, 16f, highlightColor.rgba)
}
Comment on lines +36 to +40
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This conditional logic for checking the item name and lore can be made safer and more readable by using a let scope function to handle the nullable stack. This avoids the long chain of safe calls and the == true check.

                inventorySlot?.stack?.let { stack ->
                    if (stack.displayName.contains(searchBar.currentSearch, ignoreCase = true) || stack.lore.any { it.contains(searchBar.currentSearch, ignoreCase = true) }) {
                        val slotX = inventorySlot.xDisplayPosition.toFloat() + event.guiLeft
                        val slotY = inventorySlot.yDisplayPosition.toFloat() + event.guiTop
                        NVGRenderer.rect(slotX, slotY, 16f, 16f, highlightColor.rgba)
                    }
                }

}
}

NVGRenderer.scale(1f / scale, 1f / scale)
NVGRenderer.endFrame()
}
Comment on lines +26 to +46
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Calling NVGRenderer.beginFrame() and NVGRenderer.endFrame() within this event handler might lead to issues if other modules also render using NVG on the same event. This can cause nested frames or other rendering artifacts. While this follows a pattern seen elsewhere (ClickGUI), a more robust solution would be to have a single, centralized place that manages the frame for GUI overlays, with modules only responsible for their specific drawing calls. This would improve both performance and stability.


@SubscribeEvent
fun onGuiMouseClick(event: GuiEvent.MouseClick) {
if (event.gui !is GuiContainer) return
if (searchBar.mouseClicked(mouseX, mouseY, event.button)) {
event.isCanceled = true
}
}

@SubscribeEvent
fun onGuiMouseRelease(event: GuiEvent.MouseRelease) {
if (event.gui !is GuiContainer) return
searchBar.mouseReleased()
}

@SubscribeEvent
fun onGuiKeyPress(event: GuiEvent.KeyPress) {
if (event.gui !is GuiContainer) return
if (searchBar.keyTyped(event.char) || searchBar.keyPressed(event.key)) {
event.isCanceled = true
}
}
}
46 changes: 46 additions & 0 deletions src/main/kotlin/me/odinmain/utils/ui/SearchBar.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package me.odinmain.utils.ui

import me.odinmain.clickgui.ClickGUI.gray38
import me.odinmain.features.impl.render.ClickGUIModule
import me.odinmain.utils.render.Colors
import me.odinmain.utils.ui.rendering.NVGRenderer

class SearchBar {
var currentSearch = ""
private set (value) {
if (value == field || value.length > 16) return
field = value
searchWidth = NVGRenderer.textWidth(value, 20f, NVGRenderer.defaultFont)
}

private var placeHolderWidth = NVGRenderer.textWidth("Search here...", 20f, NVGRenderer.defaultFont)
private var searchWidth = NVGRenderer.textWidth(currentSearch, 20f, NVGRenderer.defaultFont)

private val textInputHandler = TextInputHandler(
textProvider = { currentSearch },
textSetter = { currentSearch = it }
)

fun draw(x: Float, y: Float, width: Float, height: Float, mouseX: Float, mouseY: Float) {
NVGRenderer.dropShadow(x, y, width, height, 10f, 0.75f, 9f)
NVGRenderer.rect(x, y, width, height, gray38.rgba, 9f)
NVGRenderer.hollowRect(x, y, width, height, 3f, ClickGUIModule.clickGUIColor.rgba, 9f)

val textY = y + 10f

if (currentSearch.isEmpty()) NVGRenderer.text("Search here...", x + (width / 2) - placeHolderWidth / 2, textY, 20f, Colors.WHITE.rgba, NVGRenderer.defaultFont)
textInputHandler.x = (x + (width / 2) - searchWidth / 2 - if (currentSearch.isEmpty()) placeHolderWidth / 2 + 2f else 0f).coerceAtLeast(x)
textInputHandler.y = textY - 1
textInputHandler.width = width - 100 // ?? not sure if these should be handled like this but whatever
textInputHandler.height = height - 18 // ??
Comment on lines +34 to +35
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The magic numbers 100 and 18 make the code's intent unclear and harder to maintain. It would be better to define these as named constants (e.g., in a companion object) to describe what they represent, like padding or offsets. The comments indicating uncertainty should also be removed, as the code should be self-explanatory or have clear comments about its logic.

textInputHandler.draw(mouseX, mouseY)
}

fun mouseClicked(mouseX: Float, mouseY: Float, mouseButton: Int): Boolean = textInputHandler.mouseClicked(mouseX, mouseY, mouseButton)

fun mouseReleased() = textInputHandler.mouseReleased()

fun keyPressed(keyCode: Int): Boolean = textInputHandler.keyPressed(keyCode)

fun keyTyped(typedChar: Char): Boolean = textInputHandler.keyTyped(typedChar)
}
Loading