Skip to content

Commit 44e569e

Browse files
committed
updated the gui to look better wowowowowow (now with animations!)
added some crazy keybind stuffs readded the player model (but it gets hidden when the dropdown is run since it would render in front and look bad... maybe fix later) added a uuid cache to stop unnecessary mojang api calls.
1 parent c5077ff commit 44e569e

37 files changed

+1141
-548
lines changed

gradle.properties

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ org.gradle.jvmargs=-Xmx2g
33
baseGroup = com.github.subat0m1c.hatecheaters
44
mcVersion = 1.8.9
55
modid = hatecheaters
6-
version=0.2.2
6+
version=0.2.3
77
# requiredOdin and the latest action must have the same name if useActions is true.
88
requiredOdin=Odin-1.3.3.jar
99
odinRepository = odtheking/Odin
10-
useActions=true
10+
useActions=false

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ import com.github.subat0m1c.hatecheaters.utils.ChatUtils.modMessage
66
val HCCommand = Commodore("hc", "hatecheaters") {
77
runs {
88
modMessage("""
9-
Commands List:
9+
§bHate§3Cheaters §fmodules are accessible through the odin config menu §8(§7/odin§8)§f.
10+
11+
§fCommands List:
1012
§3| §f/hc §7: §8Main command.
1113
§3| §f/hcpv <name> §8|§f /pv <name> §7: §8Opens the profile viewer. Will use your own ign if name is left blank.
1214
§3| §f/hcs <name> §8|§f /ds <name> §7: §8Displays dungeon stats about the ign. Will use your own ign if name is left blank.

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.github.subat0m1c.hatecheaters.commands.impl
22

33
import com.github.stivais.commodore.Commodore
4+
import com.github.subat0m1c.hatecheaters.modules.render.ProfileViewer
45
import com.github.subat0m1c.hatecheaters.modules.render.ProfileViewer.pvCommand
56
import com.github.subat0m1c.hatecheaters.modules.render.launchPV
67
import com.github.subat0m1c.hatecheaters.utils.ChatUtils.modMessage
@@ -18,7 +19,7 @@ val PVCommand = Commodore("pv") {
1819

1920
runs { name: String?, profile: String? ->
2021
if (!pvCommand) return@runs modMessage("This command has been disabled! Restart your game to fully remove this command and allow neu's pv.")
21-
launchPV(name, profile)
22+
launchPV(ProfileViewer.PvPlayer(name ?: mc.thePlayer.name, profile = profile))
2223
}
2324
}
2425
}
@@ -32,7 +33,7 @@ val HCPVCommand = Commodore("hcpv") {
3233
param("profile").suggests { profileNames }
3334

3435
runs { name: String?, profile: String? ->
35-
launchPV(name, profile)
36+
launchPV(ProfileViewer.PvPlayer(name ?: mc.thePlayer.name, profile = profile))
3637
}
3738
}
3839
}

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.github.subat0m1c.hatecheaters.modules.dungeons
22

33
import com.github.subat0m1c.hatecheaters.HateCheaters.Companion.launch
4+
import com.github.subat0m1c.hatecheaters.modules.render.ProfileViewer
45
import com.github.subat0m1c.hatecheaters.pvgui.v2.utils.Utils.formatted
56
import com.github.subat0m1c.hatecheaters.pvgui.v2.utils.Utils.without
67
import com.github.subat0m1c.hatecheaters.utils.ChatUtils.modMessage
@@ -313,6 +314,8 @@ object BetterPartyFinder : Module(
313314
partyMessage("Kicked $name for: ${kickedReasons.joinToString(", ")}")
314315
} else sendCommand("party kick $name")
315316

317+
ProfileViewer.addForKeybind(name)
318+
316319
return@launch modMessage("Kicking $name for: \n${kickedReasons.joinToString(" \n")}")
317320
}
318321

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ import com.github.subat0m1c.hatecheaters.utils.ChatUtils.chatConstructor
77
import com.github.subat0m1c.hatecheaters.utils.ChatUtils.modMessage
88
import com.github.subat0m1c.hatecheaters.utils.ExtraStatsHandler
99
import com.github.subat0m1c.hatecheaters.utils.apiutils.HypixelApi.getSecrets
10-
import kotlinx.coroutines.*
10+
import com.github.subat0m1c.hatecheaters.utils.networkutils.WebUtils
11+
import kotlinx.coroutines.CompletableDeferred
12+
import kotlinx.coroutines.Deferred
1113
import me.odinmain.clickgui.settings.impl.BooleanSetting
1214
import me.odinmain.features.Module
1315
import me.odinmain.utils.noControlCodes
@@ -62,6 +64,9 @@ object ClearSecrets : Module(
6264
event.teammates.forEach {
6365
val teammate = it.asTeammate()
6466
if (teammate in teammateList) return@forEach
67+
teammate.dungeonPlayer.entity?.uniqueID?.let { uuid ->
68+
WebUtils.UuidCache.addToCache(teammate.name, uuid.toString())
69+
}
6570
teammateList.add(teammate.apply { if (it.name != mc.thePlayer.name) pullSecrets() })
6671
}
6772
}

src/main/kotlin/com/github/subat0m1c/hatecheaters/modules/render/ProfileViewer.kt

Lines changed: 58 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,15 @@ package com.github.subat0m1c.hatecheaters.modules.render
33
import com.github.subat0m1c.hatecheaters.HateCheaters.Companion.screen
44
import com.github.subat0m1c.hatecheaters.pvgui.v2.PVGui
55
import com.github.subat0m1c.hatecheaters.pvgui.v2.PVGui.loadPlayer
6-
import com.github.subat0m1c.hatecheaters.utils.ChatUtils.setHover
76
import com.github.subat0m1c.hatecheaters.utils.LogHandler.Logger
87
import me.odinmain.clickgui.settings.AlwaysActive
98
import me.odinmain.clickgui.settings.Setting.Companion.withDependency
109
import me.odinmain.clickgui.settings.impl.*
1110
import me.odinmain.features.Module
1211
import me.odinmain.utils.render.Color
1312
import me.odinmain.utils.render.Colors
14-
import net.minecraft.event.ClickEvent
15-
import net.minecraftforge.client.event.ClientChatReceivedEvent
16-
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
13+
import net.minecraft.entity.player.EntityPlayer
14+
import java.util.*
1715

1816
@AlwaysActive
1917
object ProfileViewer : Module(
@@ -30,19 +28,22 @@ object ProfileViewer : Module(
3028
default = false,
3129
desc = "Uses /hcpv in the stats command instead of /pv."
3230
)
33-
val messagePv by BooleanSetting(
34-
"Message PV",
35-
default = false,
36-
desc = "Runs /pv when you click a name in chat. might have lots of compatibility issues."
37-
)
31+
// val messagePv by BooleanSetting(
32+
// "Message PV",
33+
// default = false,
34+
// desc = "Runs /pv when you click a name in chat. might have lots of compatibility issues."
35+
// )
36+
37+
val animations by BooleanSetting("Animations", default = true, desc = "Animations for the gui.")
38+
3839
val invwalk by BooleanSetting(
3940
"GUI Move",
4041
default = false,
4142
desc = "Lets you move in the gui. USE AT YOUR OWN RISK. It should be fine in theory but hypixel is funky."
4243
)
4344
val scale by NumberSetting(
4445
"Scale",
45-
default = 1.5,
46+
default = 1.0,
4647
increment = 0.1,
4748
min = 0.1,
4849
max = 1.5,
@@ -125,18 +126,18 @@ object ProfileViewer : Module(
125126
//https://regex101.com/r/dl1MqJ/1
126127
private inline val messageRegex get() = Regex("^(((?:Party|Guild|Co-op) >|(?:From|To)|(?:\\[\\d+])?) ?(\\[[^]]*?])? ?(\\w{1,16}) ?(\\[[^]]*?]|[ቾ⚒])?): ?(.+)$")
127128

128-
@SubscribeEvent
129-
fun onMessage(event: ClientChatReceivedEvent) {
130-
if (!messagePv) return
131-
val (_, _, _, name) = messageRegex.matchEntire(event.message.unformattedText)?.destructured ?: return
132-
event.message.siblings.find { it.unformattedText.contains(name) }?.chatStyle?.apply {
133-
chatClickEvent = ClickEvent(
134-
ClickEvent.Action.RUN_COMMAND,
135-
"/${if (statsPv) "hcpv" else "pv"} $name"
136-
)
137-
setHover(listOf("Click to view ${name}'s profile"))
138-
}
139-
}
129+
// @SubscribeEvent
130+
// fun onMessage(event: ClientChatReceivedEvent) {
131+
// if (!messagePv) return
132+
// val (_, _, _, name) = messageRegex.matchEntire(event.message.unformattedText)?.destructured ?: return
133+
// event.message.siblings.find { it.unformattedText.contains(name) }?.chatStyle?.apply {
134+
// chatClickEvent = ClickEvent(
135+
// ClickEvent.Action.RUN_COMMAND,
136+
// "/${if (statsPv) "hcpv" else "pv"} $name"
137+
// )
138+
// setHover(listOf("Click to view ${name}'s profile"))
139+
// }
140+
// }
140141

141142
val themeEntries = listOf(
142143
Theme(
@@ -202,20 +203,50 @@ object ProfileViewer : Module(
202203
inventoryRound
203204
)
204205

206+
data class PvPlayer(val name: String, val uuid: UUID? = null, val profile: String? = null)
207+
data class LoadPlayer(var player: PvPlayer, var added: Long = System.currentTimeMillis())
208+
209+
private val toPv by lazy { LoadPlayer(PvPlayer(mc.thePlayer.name, mc.thePlayer.uniqueID), 0) }
210+
private val lastLoaded by lazy { LoadPlayer(PvPlayer(mc.thePlayer.name, mc.thePlayer.uniqueID), 0) }
211+
212+
fun loaded(name: String, profile: String?) {
213+
lastLoaded.player = PvPlayer(
214+
name,
215+
profile = profile
216+
) // we technically could pass uuid in, but it will be in the uuid cache here anyways.
217+
lastLoaded.added = System.currentTimeMillis()
218+
}
219+
220+
fun addForKeybind(player: String) {
221+
toPv.player = PvPlayer(player) // we also have uuid here but it will be in the cache by now.
222+
toPv.added = System.currentTimeMillis()
223+
}
224+
205225
override fun onKeybind() {
206-
launchPV()
226+
val entity = mc.objectMouseOver.entityHit
227+
val player: PvPlayer = when {
228+
System.currentTimeMillis() - toPv.added <= 5000 -> toPv.player
229+
entity != null && entity is EntityPlayer && entity.uniqueID.version() != 2 -> PvPlayer(
230+
entity.name,
231+
entity.uniqueID
232+
)
233+
234+
System.currentTimeMillis() - lastLoaded.added <= 5000 -> lastLoaded.player
235+
else -> PvPlayer(mc.thePlayer.name, mc.thePlayer.uniqueID)
236+
}
237+
238+
launchPV(player)
207239
}
208240

209241
override fun onEnable() {
210-
launchPV()
211-
super.onEnable()
242+
launchPV(PvPlayer(mc.thePlayer.name, mc.thePlayer.uniqueID))
212243
toggle()
213244
}
214245

215246
}
216247

217-
fun launchPV(name: String? = null, profile: String? = null) {
218-
loadPlayer(name, profile)
248+
fun launchPV(player: ProfileViewer.PvPlayer) {
249+
loadPlayer(player)
219250
screen = PVGui
220251
Logger.info("Trying to display pvgui")
221252
}

src/main/kotlin/com/github/subat0m1c/hatecheaters/modules/skyblock/HateCheatersModule.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ object HateCheatersModule : Module(
2121
ArrayList(ToastRenderer.ToastCorner.entries.map { it.displayName }),
2222
desc = "The corner the toasts will be in."
2323
).withDependency { toasts }
24-
2524
// val logJson by BooleanSetting("Log Json", default = false, desc = "Logs requested json data to Config/hatecheaters/json_logs")
2625
val debugMessages by BooleanSetting(
2726
"Debug messages",

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

Lines changed: 47 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,33 @@
11
package com.github.subat0m1c.hatecheaters.pvgui.v2
22

33
import com.github.subat0m1c.hatecheaters.HateCheaters.Companion.launch
4+
import com.github.subat0m1c.hatecheaters.modules.render.ProfileViewer
45
import com.github.subat0m1c.hatecheaters.modules.render.ProfileViewer.invwalk
56
import com.github.subat0m1c.hatecheaters.modules.render.ProfileViewer.scale
6-
import com.github.subat0m1c.hatecheaters.pvgui.v2.Pages.currentPage
77
import com.github.subat0m1c.hatecheaters.pvgui.v2.pages.Overview.setPlayer
88
import com.github.subat0m1c.hatecheaters.pvgui.v2.utils.InvWalkInput
9-
import com.github.subat0m1c.hatecheaters.pvgui.v2.utils.ProfileLazy
9+
import com.github.subat0m1c.hatecheaters.pvgui.v2.utils.ResettableLazy
1010
import com.github.subat0m1c.hatecheaters.utils.ChatUtils.modMessage
1111
import com.github.subat0m1c.hatecheaters.utils.apiutils.HypixelApi.getProfile
12+
import com.github.subat0m1c.hatecheaters.utils.apiutils.HypixelApi.getProfileUUID
1213
import com.github.subat0m1c.hatecheaters.utils.apiutils.HypixelData.PlayerInfo
1314
import com.github.subat0m1c.hatecheaters.utils.odinwrappers.Shaders
1415
import me.odinmain.OdinMain
16+
import me.odinmain.clickgui.settings.impl.KeybindSetting
17+
import me.odinmain.utils.ui.animations.LinearAnimation
1518
import net.minecraft.client.gui.GuiScreen
1619
import net.minecraft.client.gui.ScaledResolution
1720
import net.minecraft.client.renderer.GlStateManager
1821
import net.minecraft.util.MovementInputFromOptions
1922

2023
object PVGui : GuiScreen() {
24+
val animation = LinearAnimation<Float>(400)
2125

2226
var playerData: PlayerInfo? = null
2327
var profileName: String? = null
2428
set(value) {
2529
field = value
26-
ProfileLazy.resetAll()
30+
ResettableLazy.resetAll()
2731
}
2832

2933
var loadText = "Loading..."
@@ -40,7 +44,12 @@ object PVGui : GuiScreen() {
4044
GlStateManager.translate(OdinMain.mc.displayWidth / 2.0, OdinMain.mc.displayHeight / 2.0, 0.0)
4145
GlStateManager.scale(scale, scale, 1.0)
4246

43-
currentPage.page.preDraw()
47+
if (animation.isAnimating()) {
48+
Shaders.translate(0f, animation.get(-10f, 0f))
49+
Shaders.globalAlpha(animation.get(0f, 1f))
50+
}
51+
52+
PageHandler.preDraw()
4453
Shaders.popMatrix()
4554
Shaders.stopDraw()
4655
// scale(1f / scale, 1f / scale, 1.0)
@@ -50,12 +59,13 @@ object PVGui : GuiScreen() {
5059
}
5160

5261
override fun mouseClicked(mouseX: Int, mouseY: Int, mouseButton: Int) {
53-
currentPage.page.handleClick(mouseX, mouseY, mouseButton)
62+
PageHandler.handleClick(mouseButton)
5463
super.mouseClicked(mouseX, mouseY, mouseButton)
5564
}
5665

5766
override fun initGui() {
58-
currentPage = Pages.PageEntries.Overview
67+
animation.start()
68+
PageHandler.reset()
5969

6070
if (!invwalk) return
6171
mc.thePlayer?.let { player ->
@@ -69,28 +79,44 @@ object PVGui : GuiScreen() {
6979

7080
override fun onGuiClosed() {
7181
mc.thePlayer.movementInput = MovementInputFromOptions(mc.gameSettings)
82+
playerData?.name?.let { ProfileViewer.loaded(it, profileName) }
83+
7284
loadText = "Loading..."
7385
playerData = null
7486
profileName = null
7587
}
7688

7789
fun updateProfile(profile: String?) = playerData?.profileOrSelected(profile)?.cuteName?.let { profileName = it }
7890

79-
fun loadPlayer(name: String?, profileName: String? = null) = launch {
80-
getProfile(name ?: mc.thePlayer.name).fold(
81-
onSuccess = {
82-
if (it.profileData.profiles.isEmpty()) {
83-
loadText = "No profiles found for ${name}."
84-
return@launch
85-
}
86-
playerData = it
87-
setPlayer(it)
88-
updateProfile(profileName)
89-
}, onFailure = {
90-
modMessage(it.message)
91-
loadText = "Failed to grab profile data."
92-
}
93-
)
91+
fun loadPlayer(player: ProfileViewer.PvPlayer) = launch {
92+
if (player.uuid != null) getProfileUUID(
93+
player.uuid.toString().replace("-", ""),
94+
player.name
95+
).fold(::successfulLoad, ::loadFail)
96+
else getProfile(player.name).fold(::successfulLoad, ::loadFail)
97+
}
98+
99+
private fun successfulLoad(player: PlayerInfo) {
100+
if (player.profileData.profiles.isEmpty()) {
101+
loadText = "No profiles found for ${player.name}."
102+
return
103+
}
104+
playerData = player
105+
setPlayer(player)
106+
updateProfile(profileName)
107+
}
108+
109+
private fun loadFail(error: Throwable) {
110+
modMessage(error.message)
111+
loadText = "Failed to grab profile data."
112+
}
113+
114+
override fun keyTyped(typedChar: Char, keyCode: Int) {
115+
if ((ProfileViewer.settings.find { it.name == "Keybind" } as KeybindSetting).value.key == keyCode) {
116+
mc.displayGuiScreen(null)
117+
}
118+
119+
super.keyTyped(typedChar, keyCode)
94120
}
95121

96122
override fun doesGuiPauseGame(): Boolean = false
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package com.github.subat0m1c.hatecheaters.pvgui.v2
2+
3+
import com.github.subat0m1c.hatecheaters.pvgui.v2.PVGui.playerData
4+
import com.github.subat0m1c.hatecheaters.pvgui.v2.PVGui.profileName
5+
import com.github.subat0m1c.hatecheaters.pvgui.v2.PageHandler.pageData
6+
import com.github.subat0m1c.hatecheaters.utils.apiutils.HypixelData.MemberData
7+
import com.github.subat0m1c.hatecheaters.utils.apiutils.HypixelData.PlayerInfo
8+
import com.github.subat0m1c.hatecheaters.utils.apiutils.HypixelData.PlayerInfo.Companion.dummyPlayer
9+
import com.github.subat0m1c.hatecheaters.utils.odinwrappers.Colors
10+
import com.github.subat0m1c.hatecheaters.utils.odinwrappers.Text
11+
12+
abstract class PVPage(val name: String) {
13+
protected inline val player: PlayerInfo
14+
get() = playerData ?: dummyPlayer
15+
protected inline val profile: MemberData
16+
get() = player.profileOrSelected(profileName)?.members?.get(player.uuid) ?: MemberData(playerId = "")
17+
18+
protected inline val ct get() = pageData.ct
19+
protected inline val totalHeight get() = pageData.totalHeight
20+
protected inline val spacer get() = pageData.spacer
21+
protected inline val mainWidth get() = pageData.mainWidth
22+
protected inline val mainHeight get() = pageData.mainHeight
23+
protected inline val mainX get() = pageData.mainStart
24+
25+
protected val mainCenterX = pageData.mainStart + mainWidth / 2
26+
protected val quadrantWidth = (mainWidth / 2) - (spacer / 2)
27+
28+
open fun draw(mouseX: Int, mouseY: Int) = Text.text(
29+
"This page is not yet implemented!",
30+
mainCenterX,
31+
totalHeight / 2,
32+
3f,
33+
Colors.WHITE,
34+
alignment = Text.Alignment.MIDDLE
35+
)
36+
37+
open fun mouseClick(x: Int, y: Int, button: Int) {}
38+
}

0 commit comments

Comments
 (0)