Skip to content

Commit 58e6093

Browse files
committed
show own secrets in clear secrets
tab autocomplete improvements probably fixed various tooltip issues in profile viewer
1 parent d72fe0a commit 58e6093

File tree

10 files changed

+173
-82
lines changed

10 files changed

+173
-82
lines changed

gradle.properties

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ org.gradle.jvmargs=-Xmx2g
33
baseGroup = com.github.subat0m1c.hatecheaters
44
mcVersion = 1.8.9
55
modid = hatecheaters
6-
version = 0.1.9
6+
version = 0.2.0
77
requiredOdin = Odin-1.3.0.jar
8-
odinRepository = SubAt0m1c/Odin
8+
odinRepository = odtheking/Odin
99

1010

1111

src/main/kotlin/com/github/subat0m1c/hatecheaters/HateCheaters.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import com.github.subat0m1c.hatecheaters.modules.dungeons.ClearSecrets
77
import com.github.subat0m1c.hatecheaters.modules.skyblock.HateCheatersModule
88
import com.github.subat0m1c.hatecheaters.modules.render.ProfileViewer
99
import com.github.subat0m1c.hatecheaters.modules.render.ProfileViewer.pvCommand
10+
import com.github.subat0m1c.hatecheaters.pvgui.v2.utils.ItemGridDSL
11+
import com.github.subat0m1c.hatecheaters.utils.ExtraStatsHandler
1012
import com.github.subat0m1c.hatecheaters.utils.LogHandler
1113
import com.github.subat0m1c.hatecheaters.utils.LogHandler.Logger
1214
import com.github.subat0m1c.hatecheaters.utils.OdinCheck.checkIfOdinIsLoaded
@@ -31,7 +33,7 @@ class HateCheaters {
3133
checkIfOdinIsLoaded()
3234

3335
listOf(
34-
this
36+
this, ItemGridDSL, ExtraStatsHandler
3537
).forEach { MinecraftForge.EVENT_BUS.register(it) }
3638
}
3739

src/main/kotlin/com/github/subat0m1c/hatecheaters/commands/impl/ImportantItemsCommand.kt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,7 @@ val ItemCommand = Commodore("hcitems") {
1717
}
1818

1919
literal("remove").executable {
20-
param("item") {
21-
suggests { importantItems }
22-
}
20+
param("item").suggests { importantItems }
2321

2422
runs { item: GreedyString ->
2523
val name = item.string.formatted

src/main/kotlin/com/github/subat0m1c/hatecheaters/commands/impl/StatsCommand.kt

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,19 @@ import com.github.stivais.commodore.Commodore
44
import com.github.subat0m1c.hatecheaters.HateCheaters.Companion.launch
55
import com.github.subat0m1c.hatecheaters.utils.ChatUtils.modMessage
66
import com.github.subat0m1c.hatecheaters.utils.DungeonStats.displayDungeonData
7+
import com.github.subat0m1c.hatecheaters.utils.apiutils.ParseUtils.cachedPlayers
78
import com.github.subat0m1c.hatecheaters.utils.apiutils.ParseUtils.getSkyblockProfile
89
import me.odinmain.OdinMain.mc
910
import me.odinmain.utils.containsOneOf
1011
import me.odinmain.utils.skyblock.getChatBreak
1112

1213
val StatsCommand = Commodore("hcs", "ds", "hcstats") {
1314
executable {
14-
param("name") {
15-
suggests { mc.netHandler.playerInfoMap.mapNotNull { it.gameProfile.name.lowercase().takeUnless { it.containsOneOf("!", " ") } } }
15+
param("name").suggests {
16+
mc.netHandler.playerInfoMap.mapNotNull { it.gameProfile.name.lowercase().takeUnless { it.containsOneOf("!", " ") } } + cachedPlayers
1617
}
1718

18-
param("floor") {
19-
suggests { setOf("1", "2", "3", "4", "5", "6", "7") }
20-
}
19+
param("floor").suggests { setOf("1", "2", "3", "4", "5", "6", "7") }
2120

2221
runs { name: String?, floor: Int? ->
2322
val ign = name ?: mc.thePlayer.name

src/main/kotlin/com/github/subat0m1c/hatecheaters/commands/impl/pvcommands.kt

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,39 +4,43 @@ import com.github.stivais.commodore.Commodore
44
import com.github.subat0m1c.hatecheaters.modules.render.ProfileViewer.pvCommand
55
import com.github.subat0m1c.hatecheaters.modules.render.launchPV
66
import com.github.subat0m1c.hatecheaters.utils.ChatUtils.modMessage
7+
import com.github.subat0m1c.hatecheaters.utils.apiutils.ParseUtils.cachedPlayers
78
import me.odinmain.OdinMain.mc
89
import me.odinmain.utils.containsOneOf
910

1011
val PVCommand = Commodore("pv") {
1112
executable {
12-
param("name") {
13-
suggests { mc.netHandler.playerInfoMap.mapNotNull { it.gameProfile.name.lowercase().takeUnless { it.containsOneOf("!", " ") } } }
13+
param("name").suggests {
14+
mc.netHandler.playerInfoMap.mapNotNull { it.gameProfile.name.lowercase().takeUnless { it.containsOneOf("!", " ") } } + cachedPlayers
1415
}
1516

16-
runs { name: String? ->
17+
param("profile").suggests { profileNames }
18+
19+
runs { name: String?, profile: String? ->
1720
if (!pvCommand) return@runs modMessage("This command has been disabled! Restart your game to fully remove this command and allow neu's pv.")
18-
launchPV(name)
21+
launchPV(name, profile)
1922
}
2023
}
21-
22-
literal("profile").runs { name: String?, profile: String? ->
23-
if (!pvCommand) return@runs modMessage("This command has been disabled! Restart your game to fully remove this command and allow neu's pv.")
24-
launchPV(name, profile)
25-
}
2624
}
2725

2826
val HCPVCommand = Commodore("hcpv") {
2927
executable {
30-
param("name") {
31-
suggests { mc.netHandler.playerInfoMap.mapNotNull { it.gameProfile.name.lowercase().takeUnless { it.containsOneOf("!", " ") } } }
28+
param("name").suggests {
29+
mc.netHandler.playerInfoMap.mapNotNull { it.gameProfile.name.lowercase().takeUnless { it.containsOneOf("!", " ") } } + cachedPlayers
3230
}
3331

34-
runs { name: String? ->
35-
launchPV(name)
32+
param("profile").suggests { profileNames }
33+
34+
runs { name: String?, profile: String? ->
35+
launchPV(name, profile)
3636
}
3737
}
38+
}
3839

39-
literal("profile").runs { name: String?, profile: String? ->
40-
launchPV(name, profile)
41-
}
42-
}
40+
val profileNames = setOf(
41+
"apple", "banana", "blueberry", "cucumber", "coconut",
42+
"grapes", "kiwi", "lemon", "lime", "mango", "orange",
43+
"papaya", "pineapple", "peach", "pear", "pomegranate",
44+
"raspberry", "strawberry", "tomato", "watermelon",
45+
"zucchini",
46+
)

src/main/kotlin/com/github/subat0m1c/hatecheaters/modules/dungeons/ClearSecrets.kt

Lines changed: 54 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,11 @@ import com.github.subat0m1c.hatecheaters.HateCheaters.Companion.launchDeferred
55
import com.github.subat0m1c.hatecheaters.events.impl.LoadDungeonPlayers
66
import com.github.subat0m1c.hatecheaters.utils.ChatUtils.chatConstructor
77
import com.github.subat0m1c.hatecheaters.utils.ChatUtils.modMessage
8+
import com.github.subat0m1c.hatecheaters.utils.ExtraStatsHandler
89
import com.github.subat0m1c.hatecheaters.utils.apiutils.ParseUtils.getSecrets
9-
import kotlinx.coroutines.Deferred
10-
import kotlinx.coroutines.async
10+
import kotlinx.coroutines.*
1111
import me.odinmain.features.Module
1212
import me.odinmain.features.settings.impl.BooleanSetting
13-
import me.odinmain.utils.equalsOneOf
1413
import me.odinmain.utils.noControlCodes
1514
import me.odinmain.utils.runIn
1615
import me.odinmain.utils.skyblock.dungeon.DungeonPlayer
@@ -22,36 +21,20 @@ object ClearSecrets : Module(
2221
description = "Displays each team members secrets on run complete.",
2322
) {
2423
private val compactMessage by BooleanSetting("Compact Message", false, description = "Shows teammate data in one line instead of multiple lines.")
25-
private val secretMap = hashMapOf<Teammate, Deferred<Long>>()
26-
private inline val teammates get() = DungeonUtils.dungeonTeammatesNoSelf.map { it.asTeammate() }
2724

28-
data class Teammate(val name: String, val uuid: String?, var dungeonPlayer: DungeonPlayer) {
29-
override fun equals(other: Any?): Boolean {
30-
if (this === other) return true
31-
if (other !is Teammate) return false
32-
33-
return name == other.name && uuid == other.uuid
34-
}
35-
36-
override fun hashCode(): Int = 31 * name.hashCode() + (uuid?.hashCode() ?: 0)
37-
}
25+
private inline val teammates get() = DungeonUtils.dungeonTeammates.map { it.asTeammate() }.toSet()
26+
private val teammateList = hashSetOf<Teammate>()
27+
private var ownSecrets: Long? = null
3828

3929
init {
4030
onMessage(Regex("^\\s*(Master Mode)? ?(?:The)? Catacombs - (Entrance|Floor .{1,3})\$")) {
41-
secretMap.keys.retainAll(teammates.toSet())
31+
teammateList.retainAll(teammates)
4232
runIn(30, true) { // bm waits a bit, figure I should as well? not sure.
4333
launch {
44-
secretMap.entries.map { (k, v) ->
45-
val new = async {
46-
getSecrets(k.name, k.uuid)
47-
.onFailure { modMessage("Failed to get secrets for ${k.name}: ${it.message}") }
48-
.getOrDefault(-1)
49-
}.also { new -> secretMap[k] = new }.await()
50-
val old = v.await()
51-
52-
val dif = (new - old).takeUnless { (-1L).equalsOneOf(old, new) }?.also { if (it !in 0..40) modMessage("Assuming something went wrong. Data: $old -> $new") }
53-
if (compactMessage) "§d${k.name}: §6${dif ?: "§c§l???§7"}"
54-
else "§bH§3C §7|| §d${k.name} §7-> §fSecrets: §6${dif ?: "§c§l???§r"}" // §7, §fDeaths: §c${k.dungeonPlayer.deaths}" // this doesnt work atm, todo: fix odin
34+
teammateList.map {
35+
val secrets = it.calcSecrets()
36+
if (compactMessage) "§d${it.name}: §6${secrets ?: "§c§l???§7"}"
37+
else "§bH§3C §7|| §d${it.name} §7-> §fSecrets: §6${secrets ?: "§c§l???§r"}"
5538
}.let {
5639
chatConstructor {
5740
it.forEachIndexed { i, text ->
@@ -63,22 +46,58 @@ object ClearSecrets : Module(
6346
}
6447
}
6548
}
49+
50+
onMessage(Regex(" {29}> EXTRA STATS <")) { ExtraStatsHandler.waitForOtherMods() }
51+
52+
onMessage(Regex("^\\s*Secrets Found: (\\d+)\$")) {
53+
modMessage("WHATFRICKSECRETS")
54+
ownSecrets = it.groupValues[1].toLongOrNull() ?: 0
55+
}
6656
}
6757

6858
@SubscribeEvent
6959
fun onDungeonLoad(event: LoadDungeonPlayers) {
7060
if (event.teammates.isEmpty()) return
7161
event.teammates.forEach {
72-
if (it.name == mc.thePlayer.name) return@forEach
73-
secretMap.computeIfAbsent(it.asTeammate()) { teammate ->
74-
launchDeferred {
75-
getSecrets(teammate.name, teammate.uuid)
76-
.onFailure { modMessage("Failed to get secrets for ${teammate.name}: ${it.message}") }
77-
.getOrDefault(-1)
78-
}
79-
}
62+
val teammate = it.asTeammate()
63+
if (teammate in teammateList) return@forEach
64+
teammateList.add(teammate.apply { if (it.name != mc.thePlayer.name) pullSecrets() })
8065
}
8166
}
8267

8368
private fun DungeonPlayer.asTeammate() = Teammate(name, entity?.uniqueID?.toString(), this)
69+
70+
data class Teammate(val name: String, val uuid: String?, var dungeonPlayer: DungeonPlayer) {
71+
var secrets: Deferred<Long>? = null
72+
73+
fun pullSecrets() {
74+
secrets = launchDeferred {
75+
getSecrets(name, uuid)
76+
.onFailure { modMessage("Failed to get secrets for ${name}: ${it.message}") }
77+
.getOrDefault(-1)
78+
}
79+
}
80+
81+
suspend fun calcSecrets(): Long? {
82+
if (name == mc.session.username) return ownSecrets.also { ownSecrets = null }
83+
val old = secrets?.await() ?: -1
84+
val new = CompletableDeferred<Long>().apply {
85+
complete(
86+
getSecrets(name, uuid)
87+
.onFailure { modMessage("Failed to get secrets for ${name}: ${it.message}") }
88+
.getOrDefault(-1)
89+
)
90+
}.also { new -> secrets = new }.await()
91+
return if (old == -1L || new == -1L) null else new - old
92+
}
93+
94+
override fun equals(other: Any?): Boolean {
95+
if (this === other) return true
96+
if (other !is Teammate) return false
97+
98+
return name == other.name && uuid == other.uuid
99+
}
100+
101+
override fun hashCode(): Int = 31 * name.hashCode() + (uuid?.hashCode() ?: 0)
102+
}
84103
}

src/main/kotlin/com/github/subat0m1c/hatecheaters/pvgui/v2/utils/ItemGridDSL.kt

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package com.github.subat0m1c.hatecheaters.pvgui.v2.utils
22

3+
import com.github.subat0m1c.hatecheaters.pvgui.v2.PVGui
4+
import com.github.subat0m1c.hatecheaters.pvgui.v2.utils.Utils.getMouseX
5+
import com.github.subat0m1c.hatecheaters.pvgui.v2.utils.Utils.getMouseY
36
import com.github.subat0m1c.hatecheaters.pvgui.v2.utils.Utils.isObjectHovered
47
import me.odinmain.OdinMain.mc
58
import me.odinmain.utils.render.*
@@ -12,8 +15,9 @@ import net.minecraft.client.renderer.GlStateManager.translate
1215
import net.minecraft.client.renderer.GlStateManager.scale
1316
import net.minecraft.client.renderer.RenderHelper
1417
import net.minecraft.item.ItemStack
18+
import net.minecraftforge.client.event.GuiScreenEvent
1519
import net.minecraftforge.fml.client.config.GuiUtils
16-
import org.lwjgl.opengl.GL11
20+
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
1721
import kotlin.math.ceil
1822

1923
fun itemGrid(
@@ -33,18 +37,13 @@ class ItemGridDSL(
3337
private var tooltipHandler: (ItemStack) -> List<String> = { listOf(it.displayName) + it.lore }
3438
private var colorHandler: (index: Int, ItemStack?) -> Color = { _, _ -> Colors.WHITE }
3539

36-
private val fontRenderer: FontRenderer = mc.fontRendererObj
37-
private var hoveredItem: ItemStack? = null
38-
3940
fun draw(mouseX: Int, mouseY: Int) {
4041
GlStateManager.pushMatrix()
4142

4243
Colors.WHITE.bind()
4344
GlStateManager.enableRescaleNormal()
4445
RenderHelper.enableGUIStandardItemLighting()
4546

46-
hoveredItem = null
47-
4847
items.forEach { gridItems ->
4948
val itemWidth = (gridItems.width - (gridItems.columns - 1) * padding) / gridItems.columns.coerceAtLeast(1)
5049

@@ -64,30 +63,35 @@ class ItemGridDSL(
6463
GlStateManager.popMatrix()
6564
}
6665

67-
if (isObjectHovered(Box(x, y, itemWidth, itemWidth), mouseX, mouseY)) {
68-
hoveredItem = itemStack
69-
}
66+
if (isObjectHovered(Box(x, y, itemWidth, itemWidth), mouseX, mouseY)) hoveredItem = itemStack?.let { HoverItem(it, tooltipHandler) }
7067
}
7168
}
7269

7370
RenderHelper.disableStandardItemLighting()
7471
GlStateManager.disableRescaleNormal()
7572
GlStateManager.popMatrix()
76-
77-
hoveredItem?.let {
78-
GlStateManager.pushMatrix()
79-
translate(mouseX.toDouble(), mouseY.toDouble(), 0.0)
80-
scale(2f, 2f, 1f)
81-
GuiUtils.drawHoveringText(tooltipHandler(it), 0, 0, mc.displayWidth, mc.displayHeight, -1, fontRenderer)
82-
GlStateManager.popMatrix()
83-
}
8473
}
85-
8674
fun tooltipHandler(init: (ItemStack) -> List<String>) { tooltipHandler = init }
8775

8876
fun colorHandler(init: (index: Int, ItemStack?) -> Color) { colorHandler = init }
8977

9078
fun updateItems(newItems: List<ItemStack?>, index: Int = 0) { items[index].items = newItems }
79+
80+
companion object {
81+
private val fontRenderer: FontRenderer = mc.fontRendererObj
82+
private var hoveredItem: HoverItem? = null
83+
84+
@SubscribeEvent
85+
fun onGuiRender(event: GuiScreenEvent.DrawScreenEvent.Post) {
86+
if (event.gui != PVGui) return
87+
hoveredItem?.let { (item, tooltipHandler) ->
88+
// rendered outside inventory grid stack since the tooltip code has its own translation and scaling i dont wanna mess up
89+
GuiUtils.drawHoveringText(tooltipHandler(item), getMouseX.toInt(), getMouseY.toInt(), event.gui.width, event.gui.height, -1, fontRenderer)
90+
}
91+
hoveredItem = null
92+
}
93+
}
9194
}
9295

96+
data class HoverItem(val item: ItemStack, val tooltipHandler: (ItemStack) -> List<String>)
9397
data class GridItems(var items: List<ItemStack?>, val x: Int, val centerY: Int, val width: Int, val columns: Int)

0 commit comments

Comments
 (0)