blob: 270b52038ce2ccb405966dbbd6ca99928585d363 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
|
package at.hannibal2.skyhanni.utils
import at.hannibal2.skyhanni.SkyHanniMod
import at.hannibal2.skyhanni.api.event.HandleEvent
import at.hannibal2.skyhanni.data.model.TabWidget
import at.hannibal2.skyhanni.events.LorenzTickEvent
import at.hannibal2.skyhanni.events.TabListUpdateEvent
import at.hannibal2.skyhanni.events.TablistFooterUpdateEvent
import at.hannibal2.skyhanni.events.minecraft.packet.PacketReceivedEvent
import at.hannibal2.skyhanni.mixins.hooks.tabListGuard
import at.hannibal2.skyhanni.mixins.transformers.AccessorGuiPlayerTabOverlay
import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule
import at.hannibal2.skyhanni.utils.ConditionalUtils.conditionalTransform
import at.hannibal2.skyhanni.utils.ConditionalUtils.transformIf
import at.hannibal2.skyhanni.utils.StringUtils.removeColor
import com.google.common.collect.ComparisonChain
import com.google.common.collect.Ordering
import kotlinx.coroutines.launch
import net.minecraft.client.Minecraft
import net.minecraft.client.network.NetworkPlayerInfo
import net.minecraft.network.play.server.S38PacketPlayerListItem
import net.minecraft.world.WorldSettings
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
import net.minecraftforge.fml.relauncher.Side
import net.minecraftforge.fml.relauncher.SideOnly
import kotlin.time.Duration.Companion.seconds
@SkyHanniModule
object TabListData {
private var tablistCache = emptyList<String>()
private var debugCache: List<String>? = null
private var header = ""
private var footer = ""
var fullyLoaded = false
// TODO replace with TabListUpdateEvent
@Deprecated("replace with TabListUpdateEvent")
fun getTabList() = debugCache ?: tablistCache
fun getHeader() = header
fun getFooter() = footer
fun toggleDebug() {
if (debugCache != null) {
ChatUtils.chat("Disabled tab list debug.")
debugCache = null
return
}
SkyHanniMod.coroutineScope.launch {
val clipboard = OSUtils.readFromClipboard() ?: return@launch
debugCache = clipboard.lines()
ChatUtils.chat("Enabled tab list debug with your clipboard.")
}
}
fun copyCommand(args: Array<String>) {
if (debugCache != null) {
ChatUtils.clickableChat(
"Tab list debug is enabled!",
onClick = { toggleDebug() },
"§eClick to disable!"
)
return
}
val resultList = mutableListOf<String>()
val noColor = args.size == 1 && args[0] == "true"
for (line in getTabList()) {
val tabListLine = line.transformIf({ noColor }) { removeColor() }
if (tabListLine != "") resultList.add("'$tabListLine'")
}
val tabHeader = header.conditionalTransform(noColor, { this.removeColor() }, { this })
val tabFooter = footer.conditionalTransform(noColor, { this.removeColor() }, { this })
val widgets = TabWidget.entries.filter { it.isActive }
.joinToString("\n") { "\n${it.name} : \n${it.lines.joinToString("\n")}" }
val string =
"Header:\n\n$tabHeader\n\nBody:\n\n${resultList.joinToString("\n")}\n\nFooter:\n\n$tabFooter\n\nWidgets:$widgets"
OSUtils.copyToClipboard(string)
ChatUtils.chat("Tab list copied into the clipboard!")
}
private val playerOrdering = Ordering.from(PlayerComparator())
@SideOnly(Side.CLIENT)
internal class PlayerComparator : Comparator<NetworkPlayerInfo> {
override fun compare(o1: NetworkPlayerInfo, o2: NetworkPlayerInfo): Int {
val team1 = o1.playerTeam
val team2 = o2.playerTeam
return ComparisonChain.start().compareTrueFirst(
o1.gameType != WorldSettings.GameType.SPECTATOR,
o2.gameType != WorldSettings.GameType.SPECTATOR
)
.compare(
if (team1 != null) team1.registeredName else "",
if (team2 != null) team2.registeredName else ""
)
.compare(o1.gameProfile.name, o2.gameProfile.name).result()
}
}
private fun readTabList(): List<String>? {
val thePlayer = Minecraft.getMinecraft()?.thePlayer ?: return null
val players = playerOrdering.sortedCopy(thePlayer.sendQueue.playerInfoMap)
val result = mutableListOf<String>()
tabListGuard = true
for (info in players) {
val name = Minecraft.getMinecraft().ingameGUI.tabList.getPlayerName(info)
result.add(LorenzUtils.stripVanillaMessage(name))
}
tabListGuard = false
return result.dropLast(1)
}
var dirty = false
@HandleEvent(receiveCancelled = true)
fun onPacketReceive(event: PacketReceivedEvent) {
if (event.packet is S38PacketPlayerListItem) {
dirty = true
}
}
@SubscribeEvent
fun onTick(event: LorenzTickEvent) {
if (!dirty) return
dirty = false
val tabList = readTabList() ?: return
if (tablistCache != tabList) {
tablistCache = tabList
TabListUpdateEvent(getTabList()).postAndCatch()
if (!LorenzUtils.onHypixel) {
workaroundDelayedTabListUpdateAgain()
}
}
val tabListOverlay = Minecraft.getMinecraft().ingameGUI.tabList as AccessorGuiPlayerTabOverlay
header = tabListOverlay.header_skyhanni?.formattedText ?: ""
val tabFooter = tabListOverlay.footer_skyhanni?.formattedText ?: ""
if (tabFooter != footer && tabFooter != "") {
TablistFooterUpdateEvent(tabFooter).postAndCatch()
}
footer = tabFooter
}
private fun workaroundDelayedTabListUpdateAgain() {
DelayedRun.runDelayed(2.seconds) {
if (LorenzUtils.onHypixel) {
println("workaroundDelayedTabListUpdateAgain")
TabListUpdateEvent(getTabList()).postAndCatch()
}
}
}
}
|