aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/org/polyfrost/chatting/utils/ChatHeadHooks.kt
blob: aa777c1f300c70a82dcc7f196efd10ed6333f65d (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
package org.polyfrost.chatting.utils

import net.minecraft.client.Minecraft
import net.minecraft.client.gui.ChatLine
import net.minecraft.client.network.NetHandlerPlayClient
import net.minecraft.client.network.NetworkPlayerInfo
import org.polyfrost.chatting.config.ChattingConfig.hideChatHeadOnConsecutiveMessages
import org.polyfrost.chatting.hook.ChatLineHook

object ChatHeadHooks {
    private var lastPlayerInfo: NetworkPlayerInfo? = null
    fun detect(formattedText: String, chatLine: ChatLine?): Boolean {
        if (chatLine !is ChatLineHook) {
            return false
        }
        val netHandler = Minecraft.getMinecraft().netHandler ?: return false
        val nicknameCache: MutableMap<String, NetworkPlayerInfo> = HashMap()
        var detected = false
        try {
            formattedText.split("(§.)|\\W".toRegex()).dropLastWhile { it.isEmpty() }
                .forEach { word ->
                    if (word.isNotEmpty()) {
                        var maybePlayerInfo = netHandler.getPlayerInfo(word)
                        if (maybePlayerInfo == null) {
                            maybePlayerInfo = getPlayerFromNickname(word, netHandler, nicknameCache)
                        }
                        if (maybePlayerInfo != null) {
                            detected = true
                            chatLine.run {
                                playerInfo = maybePlayerInfo
                                detectedPlayerInfo = playerInfo
                                isDetected = true
                                if (playerInfo == lastPlayerInfo) {
                                    isFirstDetection = false
                                    if (hideChatHeadOnConsecutiveMessages) {
                                        playerInfo = null
                                    }
                                } else {
                                    lastPlayerInfo = playerInfo
                                }
                                return@forEach
                            }
                        }
                    }
                }
        } catch (ignored: Exception) {
        }
        return detected
    }

    private fun getPlayerFromNickname(
        word: String,
        connection: NetHandlerPlayClient,
        nicknameCache: MutableMap<String, NetworkPlayerInfo>
    ): NetworkPlayerInfo? {
        if (nicknameCache.isEmpty()) {
            for (p in connection.playerInfoMap) {
                val displayName = p.displayName
                if (displayName != null) {
                    val nickname = displayName.unformattedTextForChat
                    if (word == nickname) {
                        nicknameCache.clear()
                        return p
                    }
                    nicknameCache[nickname] = p
                }
            }
        } else {
            // use prepared cache
            return nicknameCache[word]
        }
        return null
    }
}