aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/kotlin/cc')
-rw-r--r--src/main/kotlin/cc/woverflow/chatting/Chatting.kt272
-rw-r--r--src/main/kotlin/cc/woverflow/chatting/chat/ChatRegexes.kt11
-rw-r--r--src/main/kotlin/cc/woverflow/chatting/chat/ChatScrollingHook.kt5
-rw-r--r--src/main/kotlin/cc/woverflow/chatting/chat/ChatSearchingManager.kt42
-rw-r--r--src/main/kotlin/cc/woverflow/chatting/chat/ChatShortcuts.kt79
-rw-r--r--src/main/kotlin/cc/woverflow/chatting/chat/ChatSpamBlock.kt124
-rw-r--r--src/main/kotlin/cc/woverflow/chatting/chat/ChatTab.kt112
-rw-r--r--src/main/kotlin/cc/woverflow/chatting/chat/ChatTabs.kt354
-rw-r--r--src/main/kotlin/cc/woverflow/chatting/chat/ChatTabsJson.kt15
-rw-r--r--src/main/kotlin/cc/woverflow/chatting/command/ChattingCommand.kt14
-rw-r--r--src/main/kotlin/cc/woverflow/chatting/config/ChattingConfig.kt313
-rw-r--r--src/main/kotlin/cc/woverflow/chatting/gui/components/CleanButton.kt103
-rw-r--r--src/main/kotlin/cc/woverflow/chatting/gui/components/ClearButton.kt42
-rw-r--r--src/main/kotlin/cc/woverflow/chatting/gui/components/RenderType.kt7
-rw-r--r--src/main/kotlin/cc/woverflow/chatting/gui/components/ScreenshotButton.kt36
-rw-r--r--src/main/kotlin/cc/woverflow/chatting/gui/components/SearchButton.kt70
-rw-r--r--src/main/kotlin/cc/woverflow/chatting/gui/components/TabButton.kt46
-rw-r--r--src/main/kotlin/cc/woverflow/chatting/utils/EaseOutQuart.kt7
-rw-r--r--src/main/kotlin/cc/woverflow/chatting/utils/ModCompatHooks.kt100
-rw-r--r--src/main/kotlin/cc/woverflow/chatting/utils/RenderUtils.kt259
20 files changed, 0 insertions, 2011 deletions
diff --git a/src/main/kotlin/cc/woverflow/chatting/Chatting.kt b/src/main/kotlin/cc/woverflow/chatting/Chatting.kt
deleted file mode 100644
index 9452dcf..0000000
--- a/src/main/kotlin/cc/woverflow/chatting/Chatting.kt
+++ /dev/null
@@ -1,272 +0,0 @@
-package cc.woverflow.chatting
-
-import cc.polyfrost.oneconfig.libs.universal.UDesktop
-import cc.polyfrost.oneconfig.libs.universal.UMinecraft
-import cc.polyfrost.oneconfig.libs.universal.UResolution
-import cc.polyfrost.oneconfig.utils.Notifications
-import cc.polyfrost.oneconfig.utils.commands.CommandManager
-import cc.polyfrost.oneconfig.utils.dsl.browseLink
-import cc.woverflow.chatting.chat.ChatSearchingManager
-import cc.woverflow.chatting.chat.ChatShortcuts
-import cc.woverflow.chatting.chat.ChatSpamBlock
-import cc.woverflow.chatting.chat.ChatTabs
-import cc.woverflow.chatting.command.ChattingCommand
-import cc.woverflow.chatting.config.ChattingConfig
-import cc.woverflow.chatting.hook.ChatLineHook
-import cc.woverflow.chatting.mixin.GuiNewChatAccessor
-import cc.woverflow.chatting.utils.ModCompatHooks
-import cc.woverflow.chatting.utils.copyToClipboard
-import cc.woverflow.chatting.utils.createBindFramebuffer
-import cc.woverflow.chatting.utils.screenshot
-import net.minecraft.client.Minecraft
-import net.minecraft.client.gui.*
-import net.minecraft.client.renderer.GlStateManager
-import net.minecraft.client.renderer.OpenGlHelper
-import net.minecraft.client.settings.KeyBinding
-import net.minecraft.client.shader.Framebuffer
-import net.minecraft.util.MathHelper
-import net.minecraftforge.client.event.RenderGameOverlayEvent
-import net.minecraftforge.common.MinecraftForge.EVENT_BUS
-import net.minecraftforge.fml.client.registry.ClientRegistry
-import net.minecraftforge.fml.common.Loader
-import net.minecraftforge.fml.common.Mod
-import net.minecraftforge.fml.common.event.FMLInitializationEvent
-import net.minecraftforge.fml.common.event.FMLLoadCompleteEvent
-import net.minecraftforge.fml.common.event.FMLPostInitializationEvent
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
-import net.minecraftforge.fml.common.gameevent.TickEvent
-import org.lwjgl.input.Keyboard
-import java.awt.image.BufferedImage
-import java.io.File
-import java.text.SimpleDateFormat
-import java.util.*
-
-
-@Mod(
- modid = Chatting.ID,
- name = Chatting.NAME,
- version = Chatting.VER,
- modLanguageAdapter = "cc.polyfrost.oneconfig.utils.KotlinLanguageAdapter"
-)
-object Chatting {
-
- val keybind = KeyBinding("Screenshot Chat", Keyboard.KEY_NONE, "Chatting")
- const val NAME = "@NAME@"
- const val VER = "@VER@"
- const val ID = "@ID@"
- var doTheThing = false
- var isPatcher = false
- private set
- var isBetterChat = false
- private set
- var isSkytils = false
- private set
- var isHychat = false
- private set
-
- private var time = -1L
- var deltaTime = 17L
-
- private val fileFormatter: SimpleDateFormat = SimpleDateFormat("yyyy-MM-dd_HH.mm.ss'.png'")
-
- val oldModDir = File(File(Minecraft.getMinecraft().mcDataDir, "W-OVERFLOW"), NAME)
-
- @Mod.EventHandler
- fun onInitialization(event: FMLInitializationEvent) {
- ChattingConfig
- CommandManager.INSTANCE.registerCommand(ChattingCommand())
- ClientRegistry.registerKeyBinding(keybind)
- EVENT_BUS.register(this)
- EVENT_BUS.register(ChatSpamBlock)
- ChatTabs.initialize()
- ChatShortcuts.initialize()
- }
-
- @Mod.EventHandler
- fun onPostInitialization(event: FMLPostInitializationEvent) {
- isPatcher = Loader.isModLoaded("patcher")
- isBetterChat = Loader.isModLoaded("betterchat")
- isSkytils = Loader.isModLoaded("skytils")
- isHychat = Loader.isModLoaded("hychat")
- }
-
- @Mod.EventHandler
- fun onForgeLoad(event: FMLLoadCompleteEvent) {
- if (ChattingConfig.informForAlternatives) {
- if (isHychat) {
- Notifications.INSTANCE.send(
- NAME,
- "Hychat can be removed as it is replaced by Chatting. Click here for more information.",
- Runnable {
- UDesktop.browseLink("https://microcontrollersdev.github.io/Alternatives/1.8.9/hychat")
- })
- }
- if (isSkytils) {
- try {
- skytilsCompat(Class.forName("gg.skytils.skytilsmod.core.Config"))
- } catch (e: Exception) {
- e.printStackTrace()
- try {
- skytilsCompat(Class.forName("skytils.skytilsmod.core.Config"))
- } catch (e: Exception) {
- e.printStackTrace()
- }
- }
- }
- if (isBetterChat) {
- Notifications.INSTANCE.send(
- NAME,
- "BetterChat can be removed as it is replaced by Chatting. Click here to open your mods folder to delete the BetterChat file.",
- Runnable {
- UDesktop.open(File("./mods"))
- })
- }
- }
- }
-
- private fun skytilsCompat(skytilsClass: Class<*>) {
- val instance = skytilsClass.getDeclaredField("INSTANCE")
- val chatTabs = skytilsClass.getDeclaredField("chatTabs")
- chatTabs.isAccessible = true
- if (chatTabs.getBoolean(instance)) {
- Notifications.INSTANCE.send(
- NAME,
- "Skytils' chat tabs can be disabled as it is replace by Chatting.\nClick here to automatically do this.",
- Runnable {
- chatTabs.setBoolean(instance, false)
- ChattingConfig.chatTabs = true
- ChattingConfig.hypixelOnlyChatTabs = true
- ChattingConfig.save()
- skytilsClass.getMethod("markDirty").invoke(instance)
- skytilsClass.getMethod("writeData").invoke(instance)
- })
- }
- val copyChat = skytilsClass.getDeclaredField("copyChat")
- copyChat.isAccessible = true
- if (copyChat.getBoolean(instance)) {
- Notifications.INSTANCE.send(
- NAME,
- "Skytils' copy chat messages can be disabled as it is replace by Chatting.\nClick here to automatically do this.",
- Runnable {
- copyChat.setBoolean(instance, false)
- skytilsClass.getMethod("markDirty").invoke(instance)
- skytilsClass.getMethod("writeData").invoke(instance)
- })
- }
- }
-
- @SubscribeEvent
- fun onRenderTick(event: RenderGameOverlayEvent.Pre) {
- if (event.type == RenderGameOverlayEvent.ElementType.ALL) {
- if (time == -1L) {
- time = UMinecraft.getTime()
- } else {
- val currentTime = UMinecraft.getTime()
- deltaTime = currentTime - time
- time = currentTime
- }
- }
- }
-
- @SubscribeEvent
- fun onTickEvent(event: TickEvent.ClientTickEvent) {
- if (event.phase == TickEvent.Phase.START && Minecraft.getMinecraft().theWorld != null && Minecraft.getMinecraft().thePlayer != null && (Minecraft.getMinecraft().currentScreen == null || Minecraft.getMinecraft().currentScreen is GuiChat)) {
- if (doTheThing) {
- screenshotChat()
- doTheThing = false
- }
- }
- }
-
- fun getChatHeight(opened: Boolean): Int {
- var height = if (opened) ChattingConfig.focusedHeight else ChattingConfig.unfocusedHeight
- height = (height * Minecraft.getMinecraft().gameSettings.chatScale).toInt()
- val chatY = ModCompatHooks.yOffset + ModCompatHooks.chatPosition
- if (height + chatY + 27 > (UResolution.scaledHeight / Minecraft.getMinecraft().gameSettings.chatScale).toInt() - 27 - chatY) {
- height = (UResolution.scaledHeight / Minecraft.getMinecraft().gameSettings.chatScale).toInt() - 27 - chatY
- }
- return height
- }
-
- fun screenshotLine(line: ChatLine): BufferedImage? {
- val hud = Minecraft.getMinecraft().ingameGUI
- val chat = hud.chatGUI
- val i = MathHelper.floor_float(chat.chatWidth / chat.chatScale)
- return screenshot(
- hashMapOf<ChatLine, String>().also {
- GuiUtilRenderComponents.splitText(
- line.chatComponent,
- i,
- Minecraft.getMinecraft().fontRendererObj,
- false,
- false
- ).map { it.formattedText }.reversed().forEach { string ->
- it[line] = string
- }
- }
- )
- }
-
- private fun screenshotChat() {
- screenshotChat(0)
- }
-
- fun screenshotChat(scrollPos: Int) {
- val hud = Minecraft.getMinecraft().ingameGUI
- val chat = hud.chatGUI
- val chatLines = LinkedHashMap<ChatLine, String>()
- ChatSearchingManager.filterMessages(
- ChatSearchingManager.lastSearch,
- (chat as GuiNewChatAccessor).drawnChatLines
- )?.let { drawnLines ->
- val chatHeight =
- if (ChattingConfig.customChatHeight) getChatHeight(true) / 9 else GuiNewChat.calculateChatboxHeight(
- Minecraft.getMinecraft().gameSettings.chatHeightFocused / 9
- )
- for (i in scrollPos until drawnLines.size.coerceAtMost(scrollPos + chatHeight)) {
- chatLines[drawnLines[i]] = drawnLines[i].chatComponent.formattedText
- }
-
- screenshot(chatLines)?.copyToClipboard()
- }
- }
-
- private fun screenshot(messages: HashMap<ChatLine, String>): BufferedImage? {
- if (messages.isEmpty()) {
- Notifications.INSTANCE.send("Chatting", "Chat window is empty.")
- return null
- }
- if (!OpenGlHelper.isFramebufferEnabled()) {
- Notifications.INSTANCE.send(
- "Chatting",
- "Screenshot failed, please disable “Fast Render” in OptiFine’s “Performance” tab."
- )
- return null
- }
-
- val fr: FontRenderer = ModCompatHooks.fontRenderer
- val width = messages.maxOf { fr.getStringWidth(it.value) + (if (ChattingConfig.showChatHeads && ((it.key as ChatLineHook).hasDetected() || ChattingConfig.offsetNonPlayerMessages)) 10 else 0) } + 4
- val fb: Framebuffer = createBindFramebuffer(width * 2, (messages.size * 9) * 2)
- val file = File(Minecraft.getMinecraft().mcDataDir, "screenshots/chat/" + fileFormatter.format(Date()))
-
- GlStateManager.scale(2f, 2f, 1f)
- val scale = Minecraft.getMinecraft().gameSettings.chatScale
- GlStateManager.scale(scale, scale, 1f)
- messages.entries.forEachIndexed { i: Int, entry: MutableMap.MutableEntry<ChatLine, String> ->
- ModCompatHooks.redirectDrawString(entry.value, 0f, (messages.size - 1 - i) * 9f, 0xffffff, entry.key, true)
- }
-
- val image = fb.screenshot(file)
- Minecraft.getMinecraft().entityRenderer.setupOverlayRendering()
- Minecraft.getMinecraft().framebuffer.bindFramebuffer(true)
- Notifications.INSTANCE.send(
- "Chatting",
- "Chat screenshotted successfully." + (if (ChattingConfig.copyMode != 1) "\nClick to open." else ""),
- Runnable {
- if (!UDesktop.open(file)) {
- Notifications.INSTANCE.send("Chatting", "Could not browse!")
- }
- })
- return image
- }
-}
diff --git a/src/main/kotlin/cc/woverflow/chatting/chat/ChatRegexes.kt b/src/main/kotlin/cc/woverflow/chatting/chat/ChatRegexes.kt
deleted file mode 100644
index a0a8e86..0000000
--- a/src/main/kotlin/cc/woverflow/chatting/chat/ChatRegexes.kt
+++ /dev/null
@@ -1,11 +0,0 @@
-package cc.woverflow.chatting.chat
-
-data class ChatRegexes(val regexList: List<String>?) {
- val compiledRegexList: MutableList<Regex> = arrayListOf()
-
- init {
- regexList?.forEach {
- compiledRegexList.add(Regex(it))
- }
- }
-}
diff --git a/src/main/kotlin/cc/woverflow/chatting/chat/ChatScrollingHook.kt b/src/main/kotlin/cc/woverflow/chatting/chat/ChatScrollingHook.kt
deleted file mode 100644
index b81de94..0000000
--- a/src/main/kotlin/cc/woverflow/chatting/chat/ChatScrollingHook.kt
+++ /dev/null
@@ -1,5 +0,0 @@
-package cc.woverflow.chatting.chat
-
-object ChatScrollingHook {
- var shouldSmooth = false
-} \ No newline at end of file
diff --git a/src/main/kotlin/cc/woverflow/chatting/chat/ChatSearchingManager.kt b/src/main/kotlin/cc/woverflow/chatting/chat/ChatSearchingManager.kt
deleted file mode 100644
index 33a2642..0000000
--- a/src/main/kotlin/cc/woverflow/chatting/chat/ChatSearchingManager.kt
+++ /dev/null
@@ -1,42 +0,0 @@
-package cc.woverflow.chatting.chat
-
-import cc.polyfrost.oneconfig.libs.caffeine.cache.Cache
-import cc.polyfrost.oneconfig.libs.caffeine.cache.Caffeine
-import cc.polyfrost.oneconfig.libs.universal.wrappers.message.UTextComponent
-import net.minecraft.client.gui.ChatLine
-import java.util.concurrent.LinkedBlockingQueue
-import java.util.concurrent.ThreadPoolExecutor
-import java.util.concurrent.TimeUnit
-import java.util.concurrent.atomic.AtomicInteger
-
-object ChatSearchingManager {
- private var counter: AtomicInteger = AtomicInteger(0)
- private var POOL: ThreadPoolExecutor = ThreadPoolExecutor(
- 50, 50,
- 0L, TimeUnit.SECONDS,
- LinkedBlockingQueue()
- ) { r ->
- Thread(
- r,
- "Chat Filter Cache Thread ${counter.incrementAndGet()}"
- )
- }
-
- @JvmStatic
- val cache: Cache<String, List<ChatLine>> = Caffeine.newBuilder().executor(POOL).maximumSize(5000).build()
-
- var lastSearch = ""
-
- @JvmStatic
- fun filterMessages(text: String, list: List<ChatLine>): List<ChatLine>? {
- if (text.isBlank()) return list
- val cached = cache.getIfPresent(text)
- return cached ?: run {
- cache.put(text, list.filter {
- UTextComponent.stripFormatting(it.chatComponent.unformattedText).lowercase()
- .contains(text.lowercase())
- })
- cache.getIfPresent(text)
- }
- }
-} \ No newline at end of file
diff --git a/src/main/kotlin/cc/woverflow/chatting/chat/ChatShortcuts.kt b/src/main/kotlin/cc/woverflow/chatting/chat/ChatShortcuts.kt
deleted file mode 100644
index ef1881d..0000000
--- a/src/main/kotlin/cc/woverflow/chatting/chat/ChatShortcuts.kt
+++ /dev/null
@@ -1,79 +0,0 @@
-package cc.woverflow.chatting.chat
-
-import cc.polyfrost.oneconfig.config.core.ConfigUtils
-import cc.woverflow.chatting.Chatting
-import com.google.gson.JsonObject
-import com.google.gson.JsonParser
-import java.io.File
-
-object ChatShortcuts {
- private val oldShortcutsFile = File(Chatting.oldModDir, "chatshortcuts.json")
- private val shortcutsFile = ConfigUtils.getProfileFile("chatshortcuts.json")
- private val PARSER = JsonParser()
-
- private var initialized = false
-
- val shortcuts = object : ArrayList<Pair<String, String>>() {
- private val comparator = Comparator<Pair<String, String>> { o1, o2 ->
- return@Comparator o2.first.length.compareTo(o1.first.length)
- }
-
- override fun add(element: Pair<String, String>): Boolean {
- val value = super.add(element)
- sortWith(comparator)
- return value
- }
- }
-
- fun initialize() {
- if (initialized) {
- return
- } else {
- initialized = true
- }
- if (shortcutsFile.exists()) {
- try {
- val jsonObj = PARSER.parse(shortcutsFile.readText()).asJsonObject
- for (shortcut in jsonObj.entrySet()) {
- shortcuts.add(shortcut.key to shortcut.value.asString)
- }
- return
- } catch (_: Throwable) {
- shortcutsFile.renameTo(File(shortcutsFile.parentFile, "chatshortcuts.json.bak"))
- }
- }
- shortcutsFile.createNewFile()
- if (oldShortcutsFile.exists()) {
- shortcutsFile.writeText(
- oldShortcutsFile.readText()
- )
- } else {
- shortcutsFile.writeText(JsonObject().toString())
- }
- }
-
- fun removeShortcut(key: String) {
- shortcuts.removeIf { it.first == key }
- val jsonObj = PARSER.parse(shortcutsFile.readText()).asJsonObject
- jsonObj.remove(key)
- shortcutsFile.writeText(jsonObj.toString())
- }
-
- fun writeShortcut(key: String, value: String) {
- shortcuts.add(key to value)
- val jsonObj = PARSER.parse(shortcutsFile.readText()).asJsonObject
- jsonObj.addProperty(key, value)
- shortcutsFile.writeText(jsonObj.toString())
- }
-
- fun handleSentCommand(command: String): String {
- shortcuts.forEach {
- if (command == it.first || (command.startsWith(it.first) && command.substringAfter(it.first)
- .startsWith(" "))
- ) {
- return command.replaceFirst(it.first, it.second)
- }
- }
- return command
- }
-} \ No newline at end of file
diff --git a/src/main/kotlin/cc/woverflow/chatting/chat/ChatSpamBlock.kt b/src/main/kotlin/cc/woverflow/chatting/chat/ChatSpamBlock.kt
deleted file mode 100644
index 471eec8..0000000
--- a/src/main/kotlin/cc/woverflow/chatting/chat/ChatSpamBlock.kt
+++ /dev/null
@@ -1,124 +0,0 @@
-package cc.woverflow.chatting.chat
-
-import cc.woverflow.chatting.config.ChattingConfig
-import com.google.gson.JsonObject
-import com.google.gson.JsonParser
-import java.text.Normalizer
-import net.minecraft.util.ChatComponentText
-import net.minecraft.util.EnumChatFormatting
-import net.minecraftforge.client.event.ClientChatReceivedEvent
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
-
-object ChatSpamBlock {
- /*
- Made by @KTibow
- Based off of Unspam (also by @KTibow)
- Algorithm based off of https://paulgraham.com/spam.html
- */
- private val PLAYER_MESSAGE = Regex("^(\\[VIP\\+?\\] |\\[MVP\\+?\\+?\\] |)(\\w{2,16}): (.*)$")
-
- @SubscribeEvent
- fun onChat(event: ClientChatReceivedEvent) {
- val message = event.message.unformattedText.replace(Regex("\u00A7."), "")
- if (!PLAYER_MESSAGE.matches(message)) return
-
- val (rank, player, content) = PLAYER_MESSAGE.matchEntire(message)!!.destructured
-
- if (ChattingConfig.spamThreshold != 100) {
- val tokens = tokenize(content)
- val spamProb = findSpamProbability(tokens)
- if (spamProb * 100 > ChattingConfig.spamThreshold) {
- if (ChattingConfig.hideSpam) {
- event.isCanceled = true
- } else {
- var newMessage =
- EnumChatFormatting.DARK_GRAY.toString() +
- EnumChatFormatting.STRIKETHROUGH.toString()
- if (!ChattingConfig.customChatFormatting) {
- newMessage += rank
- }
- newMessage += "$player${EnumChatFormatting.DARK_GRAY}: $content"
- event.message = ChatComponentText(newMessage)
- }
- return
- }
- }
- if (ChattingConfig.customChatFormatting) {
- val coloredPlayer = findRankColor(rank) + player + EnumChatFormatting.RESET.toString()
- event.message = ChatComponentText("$coloredPlayer: $content")
- }
- }
-
- private fun tokenize(message: String): MutableList<String> {
- val strippedMessage =
- Normalizer.normalize(message, Normalizer.Form.NFKC)
- .replace(Regex("[^\\w\\s/]"), " ")
- .lowercase()
- .trim()
- val tokens = strippedMessage.split(Regex("\\s+")).toMutableList()
- if (tokens.size <= 2) {
- tokens.add("TINY_LENGTH")
- } else if (tokens.size <= 4) {
- tokens.add("SMALL_LENGTH")
- } else if (tokens.size <= 7) {
- tokens.add("MEDIUM_LENGTH")
- } else {
- tokens.add("LONG_LENGTH")
- }
- if (message.replace(Regex("[\\w\\s]"), "").length > 2) {
- tokens.add("SPECIAL_CHARS")
- } else if (message.replace(Regex("[\\w\\s]"), "").isNotEmpty()) {
- tokens.add("SPECIAL_CHAR")
- } else {
- tokens.add("LOW_SPECIAL_CHARS")
- }
- if (message.replace(Regex("[^A-Z]"), "").length >= message.length / 4) {
- tokens.add("HIGH_CAPS")
- } else {
- tokens.add("LOW_CAPS")
- }
- return tokens
- }
-
- private fun findSpamProbability(tokens: MutableList<String>): Double {
- val tokenProbs = mutableMapOf<String, Double>()
- for (token in tokens) {
- if (!spamInfoJson.has(token)) continue
- val spamInToken = spamInfoJson.get(token).asJsonObject.get("spam").asDouble
- val fineInToken = spamInfoJson.get(token).asJsonObject.get("fine").asDouble
- tokenProbs[token] =
- ((spamInToken / messageCountsJson.get("spam").asInt) /
- (fineInToken / messageCountsJson.get("fine").asInt +
- spamInToken / messageCountsJson.get("spam").asInt))
- }
- val spamProbs = tokenProbs.values.toMutableList()
- val fineProbs = tokenProbs.values.map { 1 - it }.toMutableList()
- val spamProbability = spamProbs.reduce { a, b -> a * b }
- val fineProbability = fineProbs.reduce { a, b -> a * b }
- return spamProbability / (spamProbability + fineProbability)
- }
-
- private fun findRankColor(rank: String): String {
- println(rank)
- return when (rank) {
- "[VIP] ",
- "[VIP+] " -> EnumChatFormatting.GREEN.toString()
- "[MVP] ",
- "[MVP+] " -> EnumChatFormatting.AQUA.toString()
- "[MVP++] " -> EnumChatFormatting.GOLD.toString()
- else -> EnumChatFormatting.GRAY.toString()
- }
- }
-
- private fun getResourceAsText(path: String): String? =
- object {}.javaClass.getResource(path)?.readText()
- private val spamInfoJson: JsonObject
- private val messageCountsJson: JsonObject
-
- init {
- // Load the file spamInfo.json from resources/
- val spamInfo = getResourceAsText("/spamInfo.json")
- spamInfoJson = JsonParser().parse(spamInfo).asJsonObject
- messageCountsJson = JsonParser().parse(" { \"fine\": 668, \"spam\": 230 }").asJsonObject
- }
-}
diff --git a/src/main/kotlin/cc/woverflow/chatting/chat/ChatTab.kt b/src/main/kotlin/cc/woverflow/chatting/chat/ChatTab.kt
deleted file mode 100644
index 50de1f4..0000000
--- a/src/main/kotlin/cc/woverflow/chatting/chat/ChatTab.kt
+++ /dev/null
@@ -1,112 +0,0 @@
-package cc.woverflow.chatting.chat
-
-import cc.woverflow.chatting.gui.components.TabButton
-import com.google.gson.annotations.SerializedName
-import net.minecraft.client.Minecraft
-import net.minecraft.util.EnumChatFormatting
-import net.minecraft.util.IChatComponent
-import java.util.*
-
-data class ChatTab(
- val enabled: Boolean,
- val name: String,
- val unformatted: Boolean,
- val lowercase: Boolean?,
- @SerializedName("starts") val startsWith: List<String>?,
- val contains: List<String>?,
- @SerializedName("ends") val endsWith: List<String>?,
- val equals: List<String>?,
- @SerializedName("regex") val uncompiledRegex: List<String>?,
- @SerializedName("ignore_starts") val ignoreStartsWith: List<String>?,
- @SerializedName("ignore_contains") val ignoreContains: List<String>?,
- @SerializedName("ignore_ends") val ignoreEndsWith: List<String>?,
- @SerializedName("ignore_equals") val ignoreEquals: List<String>?,
- @SerializedName("ignore_regex") val uncompiledIgnoreRegex: List<String>?,
- val color: Int?,
- @SerializedName("hovered_color") val hoveredColor: Int?,
- @SerializedName("selected_color") val selectedColor: Int?,
- val prefix: String?,
-) {
- lateinit var button: TabButton
- lateinit var compiledRegex: ChatRegexes
- lateinit var compiledIgnoreRegex: ChatRegexes
-
- //Ugly hack to make GSON not make button / regex null
- fun initialize() {
- compiledRegex = ChatRegexes(uncompiledRegex)
- compiledIgnoreRegex = ChatRegexes(uncompiledIgnoreRegex)
- val width = Minecraft.getMinecraft().fontRendererObj.getStringWidth(name)
- button = TabButton(653452, run {
- val returnValue = x - 2
- x += 6 + width
- return@run returnValue
- }, width + 4, 12, this)
- }
-
- fun shouldRender(chatComponent: IChatComponent): Boolean {
- val message =
- (if (unformatted) EnumChatFormatting.getTextWithoutFormattingCodes(chatComponent.unformattedText) else chatComponent.formattedText).let {
- if (lowercase == true) it.lowercase(
- Locale.ENGLISH
- ) else it
- }
- ignoreStartsWith?.forEach {
- if (message.startsWith(it)) {
- return false
- }
- }
- ignoreEquals?.forEach {
- if (message == it) {
- return false
- }
- }
- ignoreEndsWith?.forEach {
- if (message.endsWith(it)) {
- return false
- }
- }
- ignoreContains?.forEach {
- if (message.contains(it)) {
- return false
- }
- }
- compiledIgnoreRegex.compiledRegexList.forEach {
- if (it.matches(message)) {
- return false
- }
- }
- if (startsWith.isNullOrEmpty() && equals.isNullOrEmpty() && endsWith.isNullOrEmpty() && contains.isNullOrEmpty() && uncompiledRegex.isNullOrEmpty()) {
- return true
- }
- equals?.forEach {
- if (message == it) {
- return true
- }
- }
- startsWith?.forEach {
- if (message.startsWith(it)) {
- return true
- }
- }
- endsWith?.forEach {
- if (message.endsWith(it)) {
- return true
- }
- }
- contains?.forEach {
- if (message.contains(it)) {
- return true
- }
- }
- compiledRegex.compiledRegexList.forEach {
- if (it.matches(message)) {
- return true
- }
- }
- return false
- }
-
- companion object {
- private var x = 4
- }
-}
diff --git a/src/main/kotlin/cc/woverflow/chatting/chat/ChatTabs.kt b/src/main/kotlin/cc/woverflow/chatting/chat/ChatTabs.kt
deleted file mode 100644
index 08423e5..0000000
--- a/src/main/kotlin/cc/woverflow/chatting/chat/ChatTabs.kt
+++ /dev/null
@@ -1,354 +0,0 @@
-package cc.woverflow.chatting.chat
-
-import cc.polyfrost.oneconfig.config.core.ConfigUtils
-import cc.woverflow.chatting.Chatting
-import cc.woverflow.chatting.gui.components.TabButton
-import com.google.gson.GsonBuilder
-import com.google.gson.JsonArray
-import com.google.gson.JsonObject
-import com.google.gson.JsonParser
-import com.google.gson.JsonPrimitive
-import net.minecraft.client.Minecraft
-import net.minecraft.util.IChatComponent
-import java.io.File
-
-object ChatTabs {
- private val GSON = GsonBuilder().setPrettyPrinting().create()
- private val PARSER = JsonParser()
- val tabs = arrayListOf<ChatTab>()
- var currentTabs: ArrayList<ChatTab?> = object : ArrayList<ChatTab?>() {
- override fun add(element: ChatTab?): Boolean {
- if (element == null) return false
- val returnValue = super.add(element)
- if (Minecraft.getMinecraft().theWorld != null && returnValue) {
- Minecraft.getMinecraft().ingameGUI.chatGUI.refreshChat()
- }
- return returnValue
- }
- }
- var hasCancelledAnimation = false
- private var initialized = false
-
- private val tabFile = ConfigUtils.getProfileFile("chattabs.json")
- private val oldTabFile = File(Chatting.oldModDir, "chattabs.json")
-
- fun initialize() {
- if (initialized) {
- return
- } else {
- initialized = true
- }
- if (!tabFile.exists()) {
- if (oldTabFile.exists()) {
- tabFile.writeText(oldTabFile.readText())
- handleFile()
- } else {
- generateNewFile()
- }
- } else {
- handleFile()
- }
- tabs.forEach {
- it.initialize()
- }
- currentTabs.clear()
- currentTabs.add(tabs[0])
- }
-
- private fun handleFile() {
- try {
- val chatTabJson = GSON.fromJson(tabFile.readText(), ChatTabsJson::class.java)
- when (chatTabJson.version) {
- 1 -> {
- // ver 2 adds `enabled`
- chatTabJson.tabs.forEach {
- applyVersion2Changes(it.asJsonObject)
- applyVersion3Changes(it.asJsonObject)
- applyVersion4Changes(it.asJsonObject)
- applyVersion5Changes(it.asJsonObject)
- applyVersion6Changes(it.asJsonObject)
- }
- chatTabJson.version = ChatTabsJson.VERSION
- tabFile.writeText(GSON.toJson(chatTabJson))
- }
- 2 -> {
- // ver 3 adds ignore_
- chatTabJson.tabs.forEach {
- applyVersion3Changes(it.asJsonObject)
- applyVersion4Changes(it.asJsonObject)
- applyVersion5Changes(it.asJsonObject)
- applyVersion6Changes(it.asJsonObject)
- }
- chatTabJson.version = ChatTabsJson.VERSION
- tabFile.writeText(GSON.toJson(chatTabJson))
- }
- 3 -> {
- // ver 4 adds color options
- chatTabJson.tabs.forEach {
- applyVersion4Changes(it.asJsonObject)
- applyVersion5Changes(it.asJsonObject)
- applyVersion6Changes(it.asJsonObject)
- }
- chatTabJson.version = ChatTabsJson.VERSION
- tabFile.writeText(GSON.toJson(chatTabJson))
- }
- 4 -> {
- // ver 5 adds lowercase
- chatTabJson.tabs.forEach {
- applyVersion5Changes(it.asJsonObject)
- applyVersion6Changes(it.asJsonObject)
- }
- chatTabJson.version = ChatTabsJson.VERSION
- tabFile.writeText(GSON.toJson(chatTabJson))
- }
- 5 -> {
- // ver 6 changes pm regex
- chatTabJson.tabs.forEach {
- applyVersion6Changes(it.asJsonObject)
- }
- chatTabJson.version = ChatTabsJson.VERSION
- tabFile.writeText(GSON.toJson(chatTabJson))
- }
- }
- chatTabJson.tabs.forEach {
- val chatTab = GSON.fromJson(it.toString(), ChatTab::class.java)
- if (chatTab.enabled) {
- tabs.add(chatTab)
- }
- }
- } catch (e: Throwable) {
- e.printStackTrace()
- tabFile.delete()
- generateNewFile()
- }
- }
-
- private fun applyVersion2Changes(json: JsonObject) {
- json.addProperty("enabled", true)
- }
-
- private fun applyVersion3Changes(json: JsonObject) {
- json.add("ignore_starts", JsonArray())
- json.add("ignore_contains", JsonArray())
- json.add("ignore_ends", JsonArray())
- json.add("ignore_equals", JsonArray())
- json.add("ignore_regex", JsonArray())
- }
-
- private fun applyVersion4Changes(json: JsonObject) {
- json.addProperty("color", TabButton.color)
- json.addProperty("hovered_color", TabButton.hoveredColor)
- json.addProperty("selected_color", TabButton.selectedColor)
- }
-
- private fun applyVersion5Changes(json: JsonObject) {
- json.addProperty("lowercase", false)
- }
-
- private fun applyVersion6Changes(json: JsonObject) {
- if (json.has("starts")) {
- val starts = json["starts"].asJsonArray
- var detected = false
- starts.iterator().let {
- while (it.hasNext()) {
- when (it.next().asString) {
- "To " -> {
- detected = true
- it.remove()
- }
- "From " -> {
- detected = true
- it.remove()
- }
- }
- }
- }
- if (detected) {
- json.add("regex", JsonArray().apply {
- add(JsonPrimitive("^(?<type>§dTo|§dFrom) (?<prefix>.+): §r(?<message>.*)(?:§r)?\$"))
- })
- json.remove("unformatted")
- json.addProperty("unformatted", false)
- }
- }
- if (json.has("ends")) {
- val ends = json["ends"].asJsonArray
- var detected = false
- ends.iterator().let {
- while (it.hasNext()) {
- when (it.next().asString) {
- "§r§ehas invited you to join their party!", -> {
- detected = true
- it.remove()
- }
- }
- }
- }
- if (detected) {
- json.add("contains", JsonArray().apply {
- add(JsonPrimitive("§r§ehas invited you to join their party!"))
- })
- }
- }
- }
-
- fun shouldRender(message: IChatComponent): Boolean {
- if (currentTabs.isEmpty()) return true
- for (tab in currentTabs) {
- if (tab?.shouldRender(message) == true) {
- return true
- }
- }
- return false
- }
-
- private fun generateNewFile() {
- tabFile.createNewFile()
- val jsonObject = JsonObject()
- val defaultTabs = generateDefaultTabs()
- jsonObject.add("tabs", defaultTabs)
- jsonObject.addProperty("version", ChatTabsJson.VERSION)
- tabFile.writeText(GSON.toJson(jsonObject))
- }
-
- private fun generateDefaultTabs(): JsonArray {
- val all = ChatTab(
- true,
- "ALL",
- unformatted = false,
- lowercase = false,
- startsWith = null,
- contains = null,
- endsWith = null,
- equals = null,
- uncompiledRegex = null,
- ignoreStartsWith = null,
- ignoreContains = null,
- ignoreEndsWith = null,
- ignoreEquals = null,
- uncompiledIgnoreRegex = null,
- color = TabButton.color,
- hoveredColor = TabButton.hoveredColor,
- selectedColor = TabButton.selectedColor,
- prefix = ""
- )
- val party = ChatTab(
- true,
- "PARTY",
- unformatted = false,
- lowercase = false,
- startsWith = listOf("§r§9Party §8> ", "§r§9P §8> ", "§eThe party was transferred to §r", "§eKicked §r"),
- contains = listOf("§r§ehas invited you to join their party!"),
- endsWith = listOf(
- "§r§eto the party! They have §r§c60 §r§eseconds to accept.§r",
- "§r§ehas disbanded the party!§r",
- "§r§ehas disconnected, they have §r§c5 §r§eminutes to rejoin before they are removed from the party.§r",
- " §r§ejoined the party.§r",
- " §r§ehas left the party.§r",
- " §r§ehas been removed from the party.§r",
- "§r§e because they were offline.§r"
- ),
- equals = listOf("§cThe party was disbanded because all invites expired and the party was empty§r"),
- uncompiledRegex = listOf( //regexes from https://github.com/kwevin/Hychat-Tabs/blob/main/tabs/re-add%20prefixes%20%26%20fix%20shortened%20tags/chat.json cause i cant write regex
- "(§r)*(§9Party §8\u003e)+(.*)",
- "(?:(?:§[a-zA-Z0-9])*\\[(?:(?:VIP)|(?:VIP§r§6\\+)|(?:MVP)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+\\+)|(?:(?:§r)?§fYOUTUBE))(?:§r)?(?:(?:§[a-zA-Z0-9]))?\\] [a-zA-Z0-9_]+|§7[a-zA-Z0-9_]+) §r§einvited §r(?:(?:§[a-zA-Z0-9])*\\[(?:(?:VIP)|(?:VIP§r§6\\+)|(?:MVP)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+\\+)|(?:(?:§r)?§fYOUTUBE))(?:§r)?(?:(?:§[a-zA-Z0-9]))?\\] [a-zA-Z0-9_]+|§7[a-zA-Z0-9_]+) §r§eto the party! They have §r§c60 §r§eseconds to accept\\.§r",
- "(?:(?:§[a-zA-Z0-9])*\\[(?:(?:VIP)|(?:VIP§r§6\\+)|(?:MVP)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+\\+)|(?:(?:§r)?§fYOUTUBE))(?:§r)?(?:(?:§[a-zA-Z0-9]))?\\] [a-zA-Z0-9_]+|§7[a-zA-Z0-9_]+) §r§ehas left the party\\.§r",
- "(?:(?:§[a-zA-Z0-9])*\\[(?:(?:VIP)|(?:VIP§r§6\\+)|(?:MVP)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+\\+)|(?:(?:§r)?§fYOUTUBE))(?:§r)?(?:(?:§[a-zA-Z0-9]))?\\] [a-zA-Z0-9_]+|§7[a-zA-Z0-9_]+) §r§ejoined the party\\.§r",
- "§eYou left the party\\.§r",
- "§eYou have joined §r(?:(?:§[a-zA-Z0-9])*\\[(?:(?:VIP)|(?:VIP§r§6\\+)|(?:MVP)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+\\+)|(?:(?:§r)?§fYOUTUBE))(?:§r)?(?:(?:§[a-zA-Z0-9]))?\\] [a-zA-Z0-9_]+|§7[a-zA-Z0-9_]+)\u0027s §r§eparty!§r",
- "§cThe party was disbanded because all invites expired and the party was empty§r",
- "§cYou cannot invite that player since they\u0027re not online\\.§r",
- "§eThe party leader, §r(?:(?:§[a-zA-Z0-9])*\\[(?:(?:VIP)|(?:VIP§r§6\\+)|(?:MVP)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+\\+)|(?:(?:§r)?§fYOUTUBE))(?:§r)?(?:(?:§[a-zA-Z0-9]))?\\] [a-zA-Z0-9_]+|§7[a-zA-Z0-9_]+)§r§e, warped you to §r(?:(?:§[a-zA-Z0-9])*\\[(?:(?:VIP)|(?:VIP§r§6\\+)|(?:MVP)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+\\+)|(?:(?:§r)?§fYOUTUBE))(?:§r)?(?:(?:§[a-zA-Z0-9]))?\\] [a-zA-Z0-9_]+|§7[a-zA-Z0-9_]+)§r§e\u0027s house\\.§r",
- "§eSkyBlock Party Warp §r§7\\([0-9]+ players?\\)§r",
- "§a. §r(?:(?:§[a-zA-Z0-9])*\\[(?:(?:VIP)|(?:VIP§r§6\\+)|(?:MVP)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+\\+)|(?:(?:§r)?§fYOUTUBE))(?:§r)?(?:(?:§[a-zA-Z0-9]))?\\] [a-zA-Z0-9_]+|§7[a-zA-Z0-9_]+)§r§f §r§awarped to your server§r",
- "§eYou summoned §r(?:(?:§[a-zA-Z0-9])*\\[(?:(?:VIP)|(?:VIP§r§6\\+)|(?:MVP)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+\\+)|(?:(?:§r)?§fYOUTUBE))(?:§r)?(?:(?:§[a-zA-Z0-9]))?\\] [a-zA-Z0-9_]+|§7[a-zA-Z0-9_]+)§r§f §r§eto your server\\.§r",
- "§eThe party leader, §r(?:(?:§[a-zA-Z0-9])*\\[(?:(?:VIP)|(?:VIP§r§6\\+)|(?:MVP)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+\\+)|(?:(?:§r)?§fYOUTUBE))(?:§r)?(?:(?:§[a-zA-Z0-9]))?\\] [a-zA-Z0-9_]+|§7[a-zA-Z0-9_]+)§r§e, warped you to their house\\.§r",
- "(?:(?:§[a-zA-Z0-9])*\\[(?:(?:VIP)|(?:VIP§r§6\\+)|(?:MVP)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+\\+)|(?:(?:§r)?§fYOUTUBE))(?:§r)?(?:(?:§[a-zA-Z0-9]))?\\] [a-zA-Z0-9_]+|§7[a-zA-Z0-9_]+) §r§aenabled Private Game§r",
- "(?:(?:§[a-zA-Z0-9])*\\[(?:(?:VIP)|(?:VIP§r§6\\+)|(?:MVP)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+\\+)|(?:(?:§r)?§fYOUTUBE))(?:§r)?(?:(?:§[a-zA-Z0-9]))?\\] [a-zA-Z0-9_]+|§7[a-zA-Z0-9_]+) §r§cdisabled Private Game§r",
- "§cThe party is now muted\\. §r",
- "§aThe party is no longer muted\\.§r",
- "§cThere are no offline players to remove\\.§r",
- "(?:(?:§[a-zA-Z0-9])*\\[(?:(?:VIP)|(?:VIP§r§6\\+)|(?:MVP)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+\\+)|(?:(?:§r)?§fYOUTUBE))(?:§r)?(?:(?:§[a-zA-Z0-9]))?\\] [a-zA-Z0-9_]+|§7[a-zA-Z0-9_]+) §r§ehas been removed from the party\\.§r",
- "§eThe party was transferred to §r(?:(?:§[a-zA-Z0-9])*\\[(?:(?:VIP)|(?:VIP§r§6\\+)|(?:MVP)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+\\+)|(?:(?:§r)?§fYOUTUBE))(?:§r)?(?:(?:§[a-zA-Z0-9]))?\\] [a-zA-Z0-9_]+|§7[a-zA-Z0-9_]+) §r§eby §r(?:(?:§[a-zA-Z0-9])*\\[(?:(?:VIP)|(?:VIP§r§6\\+)|(?:MVP)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+\\+)|(?:(?:§r)?§fYOUTUBE))(?:§r)?(?:(?:§[a-zA-Z0-9]))?\\] [a-zA-Z0-9_]+|§7[a-zA-Z0-9_]+)§r",
- "(?:(?:§[a-zA-Z0-9])*\\[(?:(?:VIP)|(?:VIP§r§6\\+)|(?:MVP)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+\\+)|(?:(?:§r)?§fYOUTUBE))(?:§r)?(?:(?:§[a-zA-Z0-9]))?\\] [a-zA-Z0-9_]+|§7[a-zA-Z0-9_]+)§r§e has promoted §r(?:(?:§[a-zA-Z0-9])*\\[(?:(?:VIP)|(?:VIP§r§6\\+)|(?:MVP)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+\\+)|(?:(?:§r)?§fYOUTUBE))(?:§r)?(?:(?:§[a-zA-Z0-9]))?\\] [a-zA-Z0-9_]+|§7[a-zA-Z0-9_]+) §r§eto Party Leader§r",
- "(?:(?:§[a-zA-Z0-9])*\\[(?:(?:VIP)|(?:VIP§r§6\\+)|(?:MVP)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+\\+)|(?:(?:§r)?§fYOUTUBE))(?:§r)?(?:(?:§[a-zA-Z0-9]))?\\] [a-zA-Z0-9_]+|§7[a-zA-Z0-9_]+)§r§e has promoted §r(?:(?:§[a-zA-Z0-9])*\\[(?:(?:VIP)|(?:VIP§r§6\\+)|(?:MVP)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+\\+)|(?:(?:§r)?§fYOUTUBE))(?:§r)?(?:(?:§[a-zA-Z0-9]))?\\] [a-zA-Z0-9_]+|§7[a-zA-Z0-9_]+) §r§eto Party Moderator§r",
- "(?:(?:§[a-zA-Z0-9])*\\[(?:(?:VIP)|(?:VIP§r§6\\+)|(?:MVP)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+\\+)|(?:(?:§r)?§fYOUTUBE))(?:§r)?(?:(?:§[a-zA-Z0-9]))?\\] [a-zA-Z0-9_]+|§7[a-zA-Z0-9_]+) §r§eis now a Party Moderator§r",
- "(?:(?:§[a-zA-Z0-9])*\\[(?:(?:VIP)|(?:VIP§r§6\\+)|(?:MVP)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+\\+)|(?:(?:§r)?§fYOUTUBE))(?:§r)?(?:(?:§[a-zA-Z0-9]))?\\] [a-zA-Z0-9_]+|§7[a-zA-Z0-9_]+)§r§e has demoted §r(?:(?:§[a-zA-Z0-9])*\\[(?:(?:VIP)|(?:VIP§r§6\\+)|(?:MVP)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+\\+)|(?:(?:§r)?§fYOUTUBE))(?:§r)?(?:(?:§[a-zA-Z0-9]))?\\] [a-zA-Z0-9_]+|§7[a-zA-Z0-9_]+) §r§eto Party Member§r",
- "§cYou can\u0027t demote yourself!§r",
- "§6Party Members \\([0-9]+\\)§r",
- "§eParty Leader: §r(?:(?:§[a-zA-Z0-9])*\\[(?:(?:VIP)|(?:VIP§r§6\\+)|(?:MVP)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+\\+)|(?:(?:§r)?§fYOUTUBE))(?:§r)?(?:(?:§[a-zA-Z0-9]))?\\] [a-zA-Z0-9_]+|§7[a-zA-Z0-9_]+) ?§r(?:§[a-zA-Z0-9]).§r",
- "§eParty Members: §r(?:(?:(?:§[a-zA-Z0-9])*\\[(?:(?:VIP)|(?:VIP§r§6\\+)|(?:MVP)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+\\+)|(?:(?:§r)?§fYOUTUBE))(?:§r)?(?:(?:§[a-zA-Z0-9]))?\\] [a-zA-Z0-9_]+|§7[a-zA-Z0-9_]+)§r(?:§[a-zA-Z0-9]) . §r)+",
- "§eParty Moderators: §r(?:(?:(?:§[a-zA-Z0-9])*\\[(?:(?:VIP)|(?:VIP§r§6\\+)|(?:MVP)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+\\+)|(?:(?:§r)?§fYOUTUBE))(?:§r)?(?:(?:§[a-zA-Z0-9]))?\\] [a-zA-Z0-9_]+|§7[a-zA-Z0-9_]+)§r(?:§[a-zA-Z0-9]) . §r)+",
- "§eThe party invite to §r(?:(?:§[a-zA-Z0-9])*\\[(?:(?:VIP)|(?:VIP§r§6\\+)|(?:MVP)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+\\+)|(?:(?:§r)?§fYOUTUBE))(?:§r)?(?:(?:§[a-zA-Z0-9]))?\\] [a-zA-Z0-9_]+|§7[a-zA-Z0-9_]+) §r§ehas expired§r",
- "(?:(?:§[a-zA-Z0-9])*\\[(?:(?:VIP)|(?:VIP§r§6\\+)|(?:MVP)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+\\+)|(?:(?:§r)?§fYOUTUBE))(?:§r)?(?:(?:§[a-zA-Z0-9]))?\\] [a-zA-Z0-9_]+|§7[a-zA-Z0-9_]+) §r§cdisabled All Invite§r",
- "(?:(?:§[a-zA-Z0-9])*\\[(?:(?:VIP)|(?:VIP§r§6\\+)|(?:MVP)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+\\+)|(?:(?:§r)?§fYOUTUBE))(?:§r)?(?:(?:§[a-zA-Z0-9]))?\\] [a-zA-Z0-9_]+|§7[a-zA-Z0-9_]+) §r§aenabled All Invite§r",
- "§cYou cannot invite that player\\.§r",
- "§cYou are not allowed to invite players\\.§r",
- "§eThe party leader, §r(?:(?:§[a-zA-Z0-9])*\\[(?:(?:VIP)|(?:VIP§r§6\\+)|(?:MVP)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+\\+)|(?:(?:§r)?§fYOUTUBE))(?:§r)?(?:(?:§[a-zA-Z0-9]))?\\] [a-zA-Z0-9_]+|§7[a-zA-Z0-9_]+) §r§ehas disconnected, they have §r§c5 §r§eminutes to rejoin before the party is disbanded\\.§r",
- "(?:(?:§[a-zA-Z0-9])*\\[(?:(?:VIP)|(?:VIP§r§6\\+)|(?:MVP)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+)|(?:MVP(?:§r)?(?:§[a-zA-Z0-9])\\+\\+)|(?:(?:§r)?§fYOUTUBE))(?:§r)?(?:(?:§[a-zA-Z0-9]))?\\] [a-zA-Z0-9_]+|§7[a-zA-Z0-9_]+) §r§ehas disconnected, they have §r§c5 §r§eminutes to rejoin before they are removed from the party.§r",
- "§cYou are not in a party right now\\.§r",
- "§cThis party is currently muted\\.§r",
- "(§r)*(§9P §8\u003e)+(.*)"
- ),
- ignoreStartsWith = null,
- ignoreContains = null,
- ignoreEndsWith = null,
- ignoreEquals = null,
- uncompiledIgnoreRegex = null,
- color = TabButton.color,
- hoveredColor = TabButton.hoveredColor,
- selectedColor = TabButton.selectedColor,
- prefix = "/pc "
- )
- val guild = ChatTab(
- true,
- "GUILD",
- unformatted = true,
- lowercase = false,
- startsWith = listOf("Guild >", "G >"),
- contains = null,
- endsWith = null,
- equals = null,
- uncompiledRegex = null,
- ignoreStartsWith = null,
- ignoreContains = null,
- ignoreEndsWith = null,
- ignoreEquals = null,
- uncompiledIgnoreRegex = null,
- color = TabButton.color,
- hoveredColor = TabButton.hoveredColor,
- selectedColor = TabButton.selectedColor,
- prefix = "/gc "
- )
- val pm = ChatTab(
- true,
- "PM",
- unformatted = false,
- lowercase = false,
- startsWith = null,
- contains = null,
- endsWith = null,
- equals = null,
- uncompiledRegex = listOf("^(?<type>§dTo|§dFrom) (?<prefix>.+): §r(?<message>.*)(?:§r)?\$"),
- ignoreStartsWith = null,
- ignoreContains = null,
- ignoreEndsWith = null,
- ignoreEquals = null,
- uncompiledIgnoreRegex = null,
- color = TabButton.color,
- hoveredColor = TabButton.hoveredColor,
- selectedColor = TabButton.selectedColor,
- prefix = "/r "
- )
- tabs.add(all)
- tabs.add(party)
- tabs.add(guild)
- tabs.add(pm)
- val jsonArray = JsonArray()
- jsonArray.add(PARSER.parse(GSON.toJson(all)).asJsonObject)
- jsonArray.add(PARSER.parse(GSON.toJson(party)).asJsonObject)
- jsonArray.add(PARSER.parse(GSON.toJson(guild)).asJsonObject)
- jsonArray.add(PARSER.parse(GSON.toJson(pm)).asJsonObject)
- return jsonArray
- }
-}
diff --git a/src/main/kotlin/cc/woverflow/chatting/chat/ChatTabsJson.kt b/src/main/kotlin/cc/woverflow/chatting/chat/ChatTabsJson.kt
deleted file mode 100644
index c632561..0000000
--- a/src/main/kotlin/cc/woverflow/chatting/chat/ChatTabsJson.kt
+++ /dev/null
@@ -1,15 +0,0 @@
-package cc.woverflow.chatting.chat
-
-import com.google.gson.JsonArray
-import com.google.gson.annotations.SerializedName
-
-data class ChatTabsJson(@SerializedName("tabs") val tabs: JsonArray, var version: Int) {
-
- override fun toString(): String {
- return "{\"tabs\": $tabs, \"version\": $version}"
- }
-
- companion object {
- const val VERSION = 6
- }
-} \ No newline at end of file
diff --git a/src/main/kotlin/cc/woverflow/chatting/command/ChattingCommand.kt b/src/main/kotlin/cc/woverflow/chatting/command/ChattingCommand.kt
deleted file mode 100644
index 7fcd4a8..0000000
--- a/src/main/kotlin/cc/woverflow/chatting/command/ChattingCommand.kt
+++ /dev/null
@@ -1,14 +0,0 @@
-package cc.woverflow.chatting.command
-
-import cc.polyfrost.oneconfig.utils.commands.annotations.Command
-import cc.polyfrost.oneconfig.utils.commands.annotations.Main
-import cc.woverflow.chatting.Chatting
-import cc.woverflow.chatting.config.ChattingConfig
-
-@Command(value = Chatting.ID, description = "Access the " + Chatting.NAME + " GUI.")
-class ChattingCommand {
- @Main
- fun main() {
- ChattingConfig.openGui()
- }
-} \ No newline at end of file
diff --git a/src/main/kotlin/cc/woverflow/chatting/config/ChattingConfig.kt b/src/main/kotlin/cc/woverflow/chatting/config/ChattingConfig.kt
deleted file mode 100644
index 711250f..0000000
--- a/src/main/kotlin/cc/woverflow/chatting/config/ChattingConfig.kt
+++ /dev/null
@@ -1,313 +0,0 @@
-package cc.woverflow.chatting.config
-
-import cc.polyfrost.oneconfig.config.Config
-import cc.polyfrost.oneconfig.config.annotations.*
-import cc.polyfrost.oneconfig.config.core.OneColor
-import cc.polyfrost.oneconfig.config.data.InfoType
-import cc.polyfrost.oneconfig.config.data.Mod
-import cc.polyfrost.oneconfig.config.data.ModType
-import cc.polyfrost.oneconfig.config.migration.VigilanceMigrator
-import cc.polyfrost.oneconfig.utils.hypixel.HypixelUtils
-import cc.woverflow.chatting.Chatting
-import cc.woverflow.chatting.chat.ChatShortcuts
-import cc.woverflow.chatting.chat.ChatTab
-import cc.woverflow.chatting.chat.ChatTabs
-import cc.woverflow.chatting.gui.components.TabButton
-import cc.woverflow.chatting.hook.ChatLineHook
-import cc.woverflow.chatting.utils.ModCompatHooks
-import java.io.File
-
-object ChattingConfig : Config(
- Mod(
- Chatting.NAME,
- ModType.UTIL_QOL,
- "/chatting_dark.svg",
- VigilanceMigrator(File(Chatting.oldModDir, Chatting.ID + ".toml").toPath().toString())
- ), "chatting.json"
-) {
-
- @Dropdown(
- name = "Text Render Type", category = "General", options = ["No Shadow", "Shadow", "Full Shadow"],
- description = "Specifies how text should be rendered in the chat. Full Shadow displays a shadow on all sides of the text, while Shadow only displays a shadow on the right and bottom sides of the text."
- )
- var textRenderType = 1
-
- @Color(
- name = "Chat Background Color", category = "General",
- description = "The color of the chat background."
- )
- var chatBackgroundColor = OneColor(0, 0, 0, 128)
-
- @Color(
- name = "Copy Chat Message Background Color", category = "General",
- description = "The color of the chat background when hovering over a message."
- )
- var hoveredChatBackgroundColor = OneColor(80, 80, 80, 128)
-
- @Switch(
- name = "Right Click to Copy Chat Message", category = "General",
- description = "Enable right clicking on a chat message to copy it."
- )
- var rightClickCopy = false
-
- @Switch(
- name = "Compact Input Box", category = "General",
- description = "Make the chat input box the same width as the chat box."
- )
- var compactInputBox = false
-
- @Color(
- name = "Input Box Background Color", category = "General",
- description = "The color of the chat input box background."
- )
- var inputBoxBackgroundColor = OneColor(0, 0, 0, 128)
-
- @Color(
- name = "Chat Button Background Color", category = "General",
- description = "The color of the chat button background."
- )
- var chatButtonBackgroundColor = OneColor(0, 0, 0, 128)
-
- @Color(
- name = "Chat Button Hovered Background Color", category = "General",
- description = "The color of the chat button background when hovered."
- )
- var chatButtonHoveredBackgroundColor = OneColor(255, 255, 255, 128)
-
- @Switch(
- name = "Inform Outdated Mods", category = "General",
- description = "Inform the user when a mod can be replaced by Chatting."
- )
- var informForAlternatives = true
-
- @Switch(
- name = "Smooth Chat Messages",
- category = "Animations", subcategory = "Messages",
- description = "Smoothly animate chat messages when they appear."
- )
- var smoothChat = true
-
- @Slider(
- name = "Message Animation Speed",
- category = "Animations", subcategory = "Messages",
- min = 0.0f, max = 1.0f,
- description = "The speed at which chat messages animate."
- )
- var messageSpeed = 0.5f
-
- @Switch(
- name = "Smooth Chat Scrolling",
- category = "Animations", subcategory = "Scrolling",
- description = "Smoothly animate scrolling when scrolling through the chat."
- )
- var smoothScrolling = true
-
- @Slider(
- name = "Scrolling Animation Speed",
- category = "Animations", subcategory = "Scrolling",
- min = 0.0f, max = 1.0f,
- description = "The speed at which scrolling animates."
- )
- var scrollingSpeed = 0.15f
-
- @Switch(
- name = "Remove Scroll Bar",
- category = "Animations", subcategory = "Scrolling",
- description = "Removes the vanilla scroll bar from the chat."
- )
- var removeScrollBar = true
-
- @Switch(
- name = "Show Chat Heads", description = "Show the chat heads of players in chat", category = "Chat Heads",
- )
- var showChatHeads = true
-
- @Switch(
- name = "Offset Non-Player Messages",
- description = "Offset all messages, even if a player has not been detected.",
- category = "Chat Heads"
- )
- var offsetNonPlayerMessages = false
-
- @Switch(
- name = "Hide Chat Head on Consecutive Messages",
- description = "Hide the chat head if the previous message was from the same player.",
- category = "Chat Heads"
- )
- var hideChatHeadOnConsecutiveMessages = true
-
- /*/
- @Property(
- type = PropertyType.SWITCH,
- name = "Show Timestamp",
- description = "Show message timestamp.",
- category = "General"
- )
- var showTimestamp = false
-
- @Property(
- type = PropertyType.SWITCH,
- name = "Timestamp Only On Hover",
- description = "Show timestamp only on mouse hover.",
- category = "General"
- )
- var showTimestampHover = true
-
- */
-
- @Info(
- text = "If Chatting detects a public chat message that seems like spam, and the probability is higher than this, it will hide it.\n" + "Made for Hypixel Skyblock. Set to 100% to disable. 95% is a reasonable threshold to use it at.\n" + "Note that this is not and never will be 100% accurate; however, it's pretty much guaranteed to block most spam.",
- size = 2,
- category = "Player Chats",
- type = InfoType.INFO
- )
- var ignored = false
-
- @Slider(
- min = 80F, max = 100F, name = "Spam Blocker Threshold", category = "Player Chats"
- )
- var spamThreshold = 100
-
- @Switch(
- name = "Custom SkyBlock Chat Formatting (remove ranks)", category = "Player Chats"
- )
- var customChatFormatting = false
-
- @Switch(
- name = "Completely Hide Spam", category = "Player Chats"
- )
- var hideSpam = false
-
- @Switch(
- name = "Custom Chat Height", category = "Chat Window",
- description = "Set a custom height for the chat window. Allows for more customization than the vanilla chat height options."
- )
- var customChatHeight = false
-
- @Slider(
- min = 180F, max = 2160F, name = "Focused Height (px)", category = "Chat Window",
- description = "The height of the chat window when focused."
- )
- var focusedHeight = 180
-
- @Slider(
- min = 180F, max = 2160F, name = "Unfocused Height (px)", category = "Chat Window",
- description = "The height of the chat window when unfocused."
- )
- var unfocusedHeight = 180
-
- @Dropdown(
- name = "Screenshot Mode", category = "Screenshotting", options = ["Save To System", "Add To Clipboard", "Both"],
- description = "What to do when taking a screenshot."
- )
- var copyMode = 0
-
- @Checkbox(
- name = "Chat Searching", category = "Searching",
- description = "Enable searching through chat messages."
- )
- var chatSearch = true
-
- @Switch(
- name = "Chat Tabs", category = "Tabs",
- description = "Allow filtering chat messages by a tab."
- )
- var chatTabs = true
- get() {
- if (!field) return false
- return if (hypixelOnlyChatTabs) {
- HypixelUtils.INSTANCE.isHypixel
- } else {
- true
- }
- }
-
- @Checkbox(
- name = "Enable Tabs Only on Hypixel", category = "Tabs",
- description = "Only enable chat tabs on Hypixel"
- )
- var hypixelOnlyChatTabs = true
-
- @Switch(
- name = "Chat Shortcuts", category = "Shortcuts"
- )
- var chatShortcuts = false
- get() {
- if (!field) return false
- return if (hypixelOnlyChatShortcuts) {
- HypixelUtils.INSTANCE.isHypixel
- } else {
- true
- }
- }
-
- @Checkbox(
- name = "Enable Shortcuts Only on Hypixel", category = "Shortcuts"
- )
- var hypixelOnlyChatShortcuts = true
-
- @Switch(
- name = "Remove Tooltip Background", category = "Tooltips",
- description = "Removes the background from tooltips."
- )
- var removeTooltipBackground = false
-
- @Dropdown(
- name = "Tooltip Text Render Type", category = "Tooltips", options = ["No Shadow", "Shadow", "Full Shadow"],
- description = "The type of shadow to render on tooltips."
- )
- var tooltipTextRenderType = 1
-
- init {
- initialize()
- addDependency("offsetNonPlayerMessages", "showChatHeads")
- addDependency("hideChatHeadOnConsecutiveMessages", "showChatHeads")
- addDependency("hypixelOnlyChatTabs", "chatTabs")
- addDependency("hypixelOnlyChatShortcuts", "chatShortcuts")
- addDependency("focusedHeight", "customChatHeight")
- addDependency("unfocusedHeight", "customChatHeight")
- addDependency("scrollingSpeed", "smoothScrolling")
- addDependency("messageSpeed", "smoothChat")
- addDependency("smoothChat", "BetterChat Smooth Chat") {
- return@addDependency !ModCompatHooks.betterChatSmoothMessages
- }
- addListener("hideChatHeadOnConsecutiveMessages") {
- ChatLineHook.chatLines.map { it.get() as ChatLineHook? }.forEach { it?.updatePlayerInfo() }
- }
- addListener("chatTabs") {
- ChatTabs.initialize()
- if (!chatTabs) {
- val dummy = ChatTab(
- true,
- "ALL",
- unformatted = false,
- lowercase = false,
- startsWith = null,
- contains = null,
- endsWith = null,
- equals = null,
- uncompiledRegex = null,
- ignoreStartsWith = null,
- ignoreContains = null,
- ignoreEndsWith = null,
- ignoreEquals = null,
- uncompiledIgnoreRegex = null,
- color = TabButton.color,
- hoveredColor = TabButton.hoveredColor,
- selectedColor = TabButton.selectedColor,
- prefix = ""
- )
- dummy.initialize()
- ChatTabs.currentTabs.clear()
- ChatTabs.currentTabs.add(dummy)
- } else {
- ChatTabs.currentTabs.clear()
- ChatTabs.currentTabs.add(ChatTabs.tabs[0])
- }
- }
- addListener("chatShortcuts") {
- ChatShortcuts.initialize()
- }
- // addDependency("showTimestampHover", "showTimestamp")
- }
-}
diff --git a/src/main/kotlin/cc/woverflow/chatting/gui/components/CleanButton.kt b/src/main/kotlin/cc/woverflow/chatting/gui/components/CleanButton.kt
deleted file mode 100644
index de590e6..0000000
--- a/src/main/kotlin/cc/woverflow/chatting/gui/components/CleanButton.kt
+++ /dev/null
@@ -1,103 +0,0 @@
-package cc.woverflow.chatting.gui.components
-
-import cc.polyfrost.oneconfig.renderer.TextRenderer
-import cc.woverflow.chatting.Chatting
-import cc.woverflow.chatting.config.ChattingConfig
-import cc.woverflow.chatting.hook.GuiNewChatHook
-import club.sk1er.patcher.config.PatcherConfig
-import net.minecraft.client.Minecraft
-import net.minecraft.client.gui.GuiButton
-import net.minecraft.client.renderer.GlStateManager
-
-/**
- * Taken from ChatShortcuts under MIT License
- * https://github.com/P0keDev/ChatShortcuts/blob/master/LICENSE
- * @author P0keDev
- */
-open class CleanButton(
- buttonId: Int,
- private val x: () -> Int,
- private val y: () -> Int,
- widthIn: Int,
- heightIn: Int,
- name: String,
- private val renderType: () -> RenderType,
- private val textColor: (packedFGColour: Int, enabled: Boolean, hovered: Boolean) -> Int = { packedFGColour: Int, enabled: Boolean, hovered: Boolean ->
- var j = 14737632
- if (packedFGColour != 0) {
- j = packedFGColour
- } else if (!enabled) {
- j = 10526880
- } else if (hovered) {
- j = 16777120
- }
- j
- },
-) :
- GuiButton(buttonId, x.invoke(), 0, widthIn, heightIn, name) {
-
- open fun isEnabled(): Boolean {
- return false
- }
-
- open fun onMousePress() {
-
- }
-
- override fun mousePressed(mc: Minecraft, mouseX: Int, mouseY: Int): Boolean {
- val isPressed =
- visible && mouseX >= xPosition && mouseY >= yPosition && mouseX < xPosition + width && mouseY < yPosition + height
- if (isPressed) {
- onMousePress()
- }
- return isPressed
- }
-
- override fun drawButton(mc: Minecraft, mouseX: Int, mouseY: Int) {
- enabled = isEnabled()
- xPosition = x()
- yPosition = y()
- if (visible) {
- val fontrenderer = mc.fontRendererObj
- GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f)
- hovered =
- mouseX >= xPosition && mouseY >= yPosition && mouseX < xPosition + width && mouseY < yPosition + height
- if (!Chatting.isPatcher || !PatcherConfig.transparentChatInputField) {
- drawRect(
- xPosition,
- yPosition,
- xPosition + width,
- yPosition + height,
- getBackgroundColor(hovered)
- )
- }
- mouseDragged(mc, mouseX, mouseY)
- val j = textColor(packedFGColour, enabled, hovered)
- when (renderType()) {
- RenderType.NONE, RenderType.SHADOW -> {
- drawCenteredString(
- fontrenderer,
- displayString,
- xPosition + width / 2,
- yPosition + (height - 8) / 2,
- j
- )
- }
-
- RenderType.FULL -> {
- TextRenderer.drawBorderedText(
- displayString,
- ((xPosition + width / 2) - (fontrenderer.getStringWidth(displayString) / 2)).toFloat(),
- (yPosition + (height - 8) / 2).toFloat(),
- j,
- (Minecraft.getMinecraft().ingameGUI.chatGUI as GuiNewChatHook).textOpacity
- )
- }
- }
- }
- }
-
- private fun getBackgroundColor(hovered: Boolean) =
- if (hovered) ChattingConfig.chatButtonHoveredBackgroundColor.rgb
- else ChattingConfig.chatButtonBackgroundColor.rgb
-} \ No newline at end of file
diff --git a/src/main/kotlin/cc/woverflow/chatting/gui/components/ClearButton.kt b/src/main/kotlin/cc/woverflow/chatting/gui/components/ClearButton.kt
deleted file mode 100644
index 6ac3d34..0000000
--- a/src/main/kotlin/cc/woverflow/chatting/gui/components/ClearButton.kt
+++ /dev/null
@@ -1,42 +0,0 @@
-package cc.woverflow.chatting.gui.components
-
-import cc.polyfrost.oneconfig.libs.universal.ChatColor
-import cc.polyfrost.oneconfig.libs.universal.UChat
-import cc.polyfrost.oneconfig.libs.universal.UResolution
-import cc.polyfrost.oneconfig.utils.Multithreading
-import cc.woverflow.chatting.Chatting
-import net.minecraft.client.Minecraft
-import net.minecraft.client.gui.Gui
-import net.minecraft.client.renderer.GlStateManager
-import net.minecraft.util.ResourceLocation
-
-class ClearButton :
- CleanButton(13379014, { UResolution.scaledWidth - 28 }, { UResolution.scaledHeight - 27 }, 12, 12, "",
- { RenderType.NONE }) {
-
- var times = 0
-
- override fun onMousePress() {
- ++times
- if (times > 1) {
- times = 0
- Minecraft.getMinecraft().ingameGUI.chatGUI.clearChatMessages()
- } else {
- UChat.chat(ChatColor.RED + ChatColor.BOLD.toString() + "Click again to clear the chat!")
- Multithreading.runAsync {
- Thread.sleep(3000)
- times = 0
- }
- }
- }
-
- override fun drawButton(mc: Minecraft, mouseX: Int, mouseY: Int) {
- super.drawButton(mc, mouseX, mouseY)
- if (visible) {
- if (hovered) GlStateManager.color(1f, 1f, 160f / 255f)
- else GlStateManager.color(1f, 1f, 1f)
- mc.textureManager.bindTexture(ResourceLocation(Chatting.ID, "delete.png"))
- Gui.drawModalRectWithCustomSizedTexture(xPosition + 1, yPosition + 1, 0f, 0f, 10, 10, 10f, 10f)
- }
- }
-} \ No newline at end of file
diff --git a/src/main/kotlin/cc/woverflow/chatting/gui/components/RenderType.kt b/src/main/kotlin/cc/woverflow/chatting/gui/components/RenderType.kt
deleted file mode 100644
index 8a56d5b..0000000
--- a/src/main/kotlin/cc/woverflow/chatting/gui/components/RenderType.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-package cc.woverflow.chatting.gui.components
-
-enum class RenderType {
- NONE,
- SHADOW,
- FULL
-} \ No newline at end of file
diff --git a/src/main/kotlin/cc/woverflow/chatting/gui/components/ScreenshotButton.kt b/src/main/kotlin/cc/woverflow/chatting/gui/components/ScreenshotButton.kt
deleted file mode 100644
index 4f65427..0000000
--- a/src/main/kotlin/cc/woverflow/chatting/gui/components/ScreenshotButton.kt
+++ /dev/null
@@ -1,36 +0,0 @@
-package cc.woverflow.chatting.gui.components
-
-import cc.polyfrost.oneconfig.libs.universal.UResolution
-import cc.polyfrost.oneconfig.libs.universal.UScreen
-import cc.woverflow.chatting.Chatting
-import cc.woverflow.chatting.mixin.GuiNewChatAccessor
-import net.minecraft.client.Minecraft
-import net.minecraft.client.gui.Gui
-import net.minecraft.client.gui.GuiChat
-import net.minecraft.client.renderer.GlStateManager
-import net.minecraft.util.ResourceLocation
-
-class ScreenshotButton :
- CleanButton(448318, { UResolution.scaledWidth - 42 }, { UResolution.scaledHeight - 27 }, 12, 12, "",
- { RenderType.NONE }) {
-
- override fun onMousePress() {
- val chat = Minecraft.getMinecraft().ingameGUI.chatGUI
- if (UScreen.currentScreen is GuiChat) {
- Chatting.screenshotChat((chat as GuiNewChatAccessor).scrollPos)
- }
- }
-
- override fun drawButton(mc: Minecraft, mouseX: Int, mouseY: Int) {
- super.drawButton(mc, mouseX, mouseY)
- if (visible) {
- if (hovered) {
- GlStateManager.color(1f, 1f, 160f / 255f)
- } else {
- GlStateManager.color(1f, 1f, 1f)
- }
- mc.textureManager.bindTexture(ResourceLocation(Chatting.ID, "screenshot.png"))
- Gui.drawModalRectWithCustomSizedTexture(xPosition + 1, yPosition + 1, 0f, 0f, 10, 10, 10f, 10f)
- }
- }
-} \ No newline at end of file
diff --git a/src/main/kotlin/cc/woverflow/chatting/gui/components/SearchButton.kt b/src/main/kotlin/cc/woverflow/chatting/gui/components/SearchButton.kt
deleted file mode 100644
index 54e9041..0000000
--- a/src/main/kotlin/cc/woverflow/chatting/gui/components/SearchButton.kt
+++ /dev/null
@@ -1,70 +0,0 @@
-package cc.woverflow.chatting.gui.components
-
-import cc.polyfrost.oneconfig.libs.universal.UResolution
-import cc.woverflow.chatting.Chatting
-import cc.woverflow.chatting.chat.ChatSearchingManager
-import net.minecraft.client.Minecraft
-import net.minecraft.client.gui.Gui
-import net.minecraft.client.gui.GuiTextField
-import net.minecraft.client.renderer.GlStateManager
-import net.minecraft.util.ResourceLocation
-
-class SearchButton :
- CleanButton(3993935, { UResolution.scaledWidth - 14 }, { UResolution.scaledHeight - 27 }, 12, 12, "",
- { RenderType.NONE }) {
- val inputField = SearchTextField()
- private var chatBox = false
-
- override fun isEnabled(): Boolean {
- return chatBox
- }
-
- override fun onMousePress() {
- chatBox = !chatBox
- inputField.setEnabled(chatBox)
- inputField.isFocused = chatBox
- ChatSearchingManager.lastSearch = ""
- inputField.text = ""
- }
-
- override fun drawButton(mc: Minecraft, mouseX: Int, mouseY: Int) {
- inputField.drawTextBox()
- super.drawButton(mc, mouseX, mouseY)
- if (visible) {
- mc.textureManager.bindTexture(ResourceLocation(Chatting.ID, "search.png"))
- if (isEnabled()) {
- GlStateManager.color(224f / 255f, 224f / 255f, 224f / 255f)
- } else if (mouseX >= xPosition && mouseX <= xPosition + 10 && mouseY >= yPosition && mouseY <= yPosition + 10) {
- GlStateManager.color(1f, 1f, 160f / 255f)
- } else {
- GlStateManager.color(1f, 1f, 1f)
- }
- Gui.drawModalRectWithCustomSizedTexture(xPosition + 1, yPosition + 1, 0f, 0f, 10, 10, 10f, 10f)
- }
- }
-
- inner class SearchTextField : GuiTextField(
- 69420,
- Minecraft.getMinecraft().fontRendererObj,
- UResolution.scaledWidth * 4 / 5 - 60,
- UResolution.scaledHeight - 26,
- UResolution.scaledWidth / 5,
- 12
- ) {
-
- init {
- maxStringLength = 100
- enableBackgroundDrawing = true
- isFocused = false
- text = ""
- setCanLoseFocus(true)
- }
-
- override fun drawTextBox() {
- if (isEnabled()) {
- if (!isFocused) isFocused = true
- super.drawTextBox()
- }
- }
- }
-}
diff --git a/src/main/kotlin/cc/woverflow/chatting/gui/components/TabButton.kt b/src/main/kotlin/cc/woverflow/chatting/gui/components/TabButton.kt
deleted file mode 100644
index e3b96f1..0000000
--- a/src/main/kotlin/cc/woverflow/chatting/gui/components/TabButton.kt
+++ /dev/null
@@ -1,46 +0,0 @@
-package cc.woverflow.chatting.gui.components
-
-import cc.polyfrost.oneconfig.libs.universal.UKeyboard
-import cc.polyfrost.oneconfig.libs.universal.UResolution
-import cc.woverflow.chatting.chat.ChatTab
-import cc.woverflow.chatting.chat.ChatTabs
-import cc.woverflow.chatting.config.ChattingConfig
-
-class TabButton(buttonId: Int, x: Int, widthIn: Int, heightIn: Int, private val chatTab: ChatTab) :
- CleanButton(buttonId, { x }, {
- UResolution.scaledHeight - 26
- }, widthIn, heightIn, chatTab.name, { RenderType.values()[ChattingConfig.textRenderType] }, { packedFGColour: Int, enabled: Boolean, hovered: Boolean ->
- var j = chatTab.color ?: color
- if (packedFGColour != 0) {
- j = packedFGColour
- } else if (!enabled) {
- j = chatTab.selectedColor ?: selectedColor
- } else if (hovered) {
- j = chatTab.hoveredColor ?: hoveredColor
- }
- j
- }) {
-
- override fun onMousePress() {
- if (UKeyboard.isShiftKeyDown()) {
- if (ChatTabs.currentTabs.contains(chatTab)) {
- ChatTabs.currentTabs.remove(chatTab)
- } else {
- ChatTabs.currentTabs.add(chatTab)
- }
- } else {
- ChatTabs.currentTabs.clear()
- ChatTabs.currentTabs.add(chatTab)
- }
- }
-
- override fun isEnabled(): Boolean {
- return ChatTabs.currentTabs.contains(chatTab)
- }
-
- companion object {
- const val color: Int = 14737632
- const val hoveredColor: Int = 16777120
- const val selectedColor: Int = 10526880
- }
-} \ No newline at end of file
diff --git a/src/main/kotlin/cc/woverflow/chatting/utils/EaseOutQuart.kt b/src/main/kotlin/cc/woverflow/chatting/utils/EaseOutQuart.kt
deleted file mode 100644
index 7943b4d..0000000
--- a/src/main/kotlin/cc/woverflow/chatting/utils/EaseOutQuart.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-package cc.woverflow.chatting.utils
-
-import cc.polyfrost.oneconfig.gui.animations.Animation
-
-class EaseOutQuart(duration: Float, start: Float, end: Float, reverse: Boolean) : Animation(duration, start, end, reverse) {
- override fun animate(x: Float) = -1 * (x - 1) * (x - 1) * (x - 1) * (x - 1) + 1
-} \ No newline at end of file
diff --git a/src/main/kotlin/cc/woverflow/chatting/utils/ModCompatHooks.kt b/src/main/kotlin/cc/woverflow/chatting/utils/ModCompatHooks.kt
deleted file mode 100644
index 3c60c72..0000000
--- a/src/main/kotlin/cc/woverflow/chatting/utils/ModCompatHooks.kt
+++ /dev/null
@@ -1,100 +0,0 @@
-package cc.woverflow.chatting.utils
-
-import cc.polyfrost.oneconfig.renderer.TextRenderer
-import cc.polyfrost.oneconfig.utils.dsl.getAlpha
-import cc.polyfrost.oneconfig.utils.dsl.mc
-import cc.woverflow.chatting.Chatting.isBetterChat
-import cc.woverflow.chatting.Chatting.isPatcher
-import cc.woverflow.chatting.config.ChattingConfig.offsetNonPlayerMessages
-import cc.woverflow.chatting.config.ChattingConfig.showChatHeads
-import cc.woverflow.chatting.config.ChattingConfig.textRenderType
-import cc.woverflow.chatting.hook.ChatLineHook
-import cc.woverflow.chatting.hook.GuiNewChatHook
-import club.sk1er.patcher.config.PatcherConfig
-import com.llamalad7.betterchat.BetterChat
-import net.minecraft.client.Minecraft
-import net.minecraft.client.gui.ChatLine
-import net.minecraft.client.gui.FontRenderer
-import net.minecraft.client.gui.Gui
-import net.minecraft.client.renderer.GlStateManager
-
-// This exists because mixin doesn't like dummy classes
-object ModCompatHooks {
- @JvmStatic
- val xOffset
- get() = if (isBetterChat) BetterChat.getSettings().xOffset else 0
-
- @JvmStatic
- val yOffset
- get() = if (isBetterChat) BetterChat.getSettings().yOffset else 0
-
- @JvmStatic
- val chatPosition
- get() = if (isPatcher && PatcherConfig.chatPosition) 12 else 0
-
- @JvmStatic
- val betterChatSmoothMessages
- get() = if (isBetterChat) BetterChat.getSettings().smooth else false
-
- @JvmStatic
- val extendedChatLength
- get() = if (isPatcher) 32667 else 0
-
- @JvmStatic
- val fontRenderer: FontRenderer
- get() = Minecraft.getMinecraft().fontRendererObj
-
- @JvmStatic
- fun redirectDrawString(text: String, x: Float, y: Float, color: Int, chatLine: ChatLine, screenshot: Boolean): Int {
- var actualX = x
- if (showChatHeads && !screenshot) {
- val hook = chatLine as ChatLineHook
- if (hook.hasDetected() || offsetNonPlayerMessages) {
- actualX += 10f
- }
- val networkPlayerInfo = hook.playerInfo
- if (networkPlayerInfo != null) {
- GlStateManager.enableBlend()
- GlStateManager.enableAlpha()
- GlStateManager.enableTexture2D()
- mc.textureManager.bindTexture(networkPlayerInfo.locationSkin)
- GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0)
- GlStateManager.color(1.0f, 1.0f, 1.0f, color.getAlpha() / 255f)
- Gui.drawScaledCustomSizeModalRect(
- (x).toInt(),
- (y - 1f).toInt(),
- 8.0f,
- 8.0f,
- 8,
- 8,
- 8,
- 8,
- 64.0f,
- 64.0f
- )
- Gui.drawScaledCustomSizeModalRect(
- (x).toInt(),
- (y - 1f).toInt(),
- 40.0f,
- 8.0f,
- 8,
- 8,
- 8,
- 8,
- 64.0f,
- 64.0f
- )
- GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f)
- }
- }
- return when (textRenderType) {
- 0 -> fontRenderer.drawString(text, actualX, y, color, false)
- 2 -> TextRenderer.drawBorderedText(text,
- actualX,
- y,
- color,
- (Minecraft.getMinecraft().ingameGUI.chatGUI as GuiNewChatHook).textOpacity)
- else -> fontRenderer.drawString(text, actualX, y, color, true)
- }
- }
-}
diff --git a/src/main/kotlin/cc/woverflow/chatting/utils/RenderUtils.kt b/src/main/kotlin/cc/woverflow/chatting/utils/RenderUtils.kt
deleted file mode 100644
index 12051cf..0000000
--- a/src/main/kotlin/cc/woverflow/chatting/utils/RenderUtils.kt
+++ /dev/null
@@ -1,259 +0,0 @@
-@file:JvmName("RenderUtils")
-
-package cc.woverflow.chatting.utils
-
-import cc.polyfrost.oneconfig.utils.IOUtils
-import cc.woverflow.chatting.config.ChattingConfig
-import net.minecraft.client.renderer.GlStateManager
-import net.minecraft.client.renderer.texture.TextureUtil
-import net.minecraft.client.shader.Framebuffer
-import org.apache.commons.lang3.SystemUtils
-import org.lwjgl.BufferUtils
-import org.lwjgl.opengl.GL11
-import org.lwjgl.opengl.GL12
-import sun.awt.datatransfer.DataTransferer
-import sun.awt.datatransfer.SunClipboard
-import java.awt.Toolkit
-import java.awt.image.BufferedImage
-import java.io.File
-import java.lang.reflect.Field
-import java.lang.reflect.Method
-import java.nio.ByteBuffer
-import java.nio.ByteOrder
-import javax.imageio.ImageIO
-
-/**
- * Taken from https://github.com/Moulberry/HyChat
- */
-fun createBindFramebuffer(w: Int, h: Int): Framebuffer {
- val framebuffer = Framebuffer(w, h, false)
- framebuffer.framebufferColor[0] = 0x36 / 255f
- framebuffer.framebufferColor[1] = 0x39 / 255f
- framebuffer.framebufferColor[2] = 0x3F / 255f
- framebuffer.framebufferClear()
- GlStateManager.matrixMode(5889)
- GlStateManager.loadIdentity()
- GlStateManager.ortho(0.0, w.toDouble(), h.toDouble(), 0.0, 1000.0, 3000.0)
- GlStateManager.matrixMode(5888)
- GlStateManager.loadIdentity()
- GlStateManager.translate(0.0f, 0.0f, -2000.0f)
- framebuffer.bindFramebuffer(true)
- return framebuffer
-}
-
-/**
- * Taken from https://github.com/Moulberry/HyChat
- * Modified so if not on Windows just in case it will switch it to RGB and remove the transparent background.
- */
-fun BufferedImage.copyToClipboard() {
- if (SystemUtils.IS_OS_WINDOWS) {
- try {
- val width = this.width
- val height = this.height
- val hdrSize = 0x28
- val buffer: ByteBuffer = ByteBuffer.allocate(hdrSize + width * height * 4)
- buffer.order(ByteOrder.LITTLE_ENDIAN)
- //Header size
- buffer.putInt(hdrSize)
- //Width
- buffer.putInt(width)
- //Int32 biHeight;
- buffer.putInt(height)
- //Int16 biPlanes;
- buffer.put(1.toByte())
- buffer.put(0.toByte())
- //Int16 biBitCount;
- buffer.put(32.toByte())
- buffer.put(0.toByte())
- //Compression
- buffer.putInt(0)
- //Int32 biSizeImage;
- buffer.putInt(width * height * 4)
- buffer.putInt(0)
- buffer.putInt(0)
- buffer.putInt(0)
- buffer.putInt(0)
-
- //Image data
- for (y in 0 until height) {
- for (x in 0 until width) {
- val argb: Int = this.getRGB(x, height - y - 1)
- if (argb shr 24 and 0xFF == 0) {
- buffer.putInt(0x00000000)
- } else {
- buffer.putInt(argb)
- }
- }
- }
- buffer.flip()
- val hdrSizev5 = 0x7C
- val bufferv5: ByteBuffer = ByteBuffer.allocate(hdrSizev5 + width * height * 4)
- bufferv5.order(ByteOrder.LITTLE_ENDIAN)
- //Header size
- bufferv5.putInt(hdrSizev5)
- //Width
- bufferv5.putInt(width)
- //Int32 biHeight;
- bufferv5.putInt(height)
- //Int16 biPlanes;
- bufferv5.put(1.toByte())
- bufferv5.put(0.toByte())
- //Int16 biBitCount;
- bufferv5.put(32.toByte())
- bufferv5.put(0.toByte())
- //Compression
- bufferv5.putInt(0)
- //Int32 biSizeImage;
- bufferv5.putInt(width * height * 4)
- bufferv5.putInt(0)
- bufferv5.putInt(0)
- bufferv5.putInt(0)
- bufferv5.putInt(0)
- bufferv5.order(ByteOrder.BIG_ENDIAN)
- bufferv5.putInt(-0x1000000)
- bufferv5.putInt(0x00FF0000)
- bufferv5.putInt(0x0000FF00)
- bufferv5.putInt(0x000000FF)
- bufferv5.order(ByteOrder.LITTLE_ENDIAN)
-
- //BGRs
- bufferv5.put(0x42.toByte())
- bufferv5.put(0x47.toByte())
- bufferv5.put(0x52.toByte())
- bufferv5.put(0x73.toByte())
- for (i in bufferv5.position() until hdrSizev5) {
- bufferv5.put(0.toByte())
- }
-
- //Image data
- for (y in 0 until height) {
- for (x in 0 until width) {
- val argb: Int = this.getRGB(x, height - y - 1)
- val a = argb shr 24 and 0xFF
- var r = argb shr 16 and 0xFF
- var g = argb shr 8 and 0xFF
- var b = argb and 0xFF
- r = r * a / 0xFF
- g = g * a / 0xFF
- b = b * a / 0xFF
- bufferv5.putInt(a shl 24 or (r shl 16) or (g shl 8) or b)
- }
- }
- bufferv5.flip()
- val clip = Toolkit.getDefaultToolkit().systemClipboard
- val dt = DataTransferer.getInstance()
- val f: Field = dt.javaClass.getDeclaredField("CF_DIB")
- f.isAccessible = true
- val format: Long = f.getLong(null)
- val openClipboard: Method = clip.javaClass.getDeclaredMethod("openClipboard", SunClipboard::class.java)
- openClipboard.isAccessible = true
- openClipboard.invoke(clip, clip)
- val publishClipboardData: Method = clip.javaClass.getDeclaredMethod(
- "publishClipboardData",
- Long::class.javaPrimitiveType,
- ByteArray::class.java
- )
- publishClipboardData.isAccessible = true
- val arr: ByteArray = buffer.array()
- publishClipboardData.invoke(clip, format, arr)
- val closeClipboard: Method = clip.javaClass.getDeclaredMethod("closeClipboard")
- closeClipboard.isAccessible = true
- closeClipboard.invoke(clip)
- return
- } catch (e: Exception) {
- e.printStackTrace()
- }
- }
- val pixels: IntArray =
- this.getRGB(0, 0, this.width, this.height, null, 0, this.width)
- val newImage = BufferedImage(this.width, this.height, BufferedImage.TYPE_INT_RGB)
- newImage.setRGB(0, 0, newImage.width, newImage.height, pixels, 0, newImage.width)
-
- try {
- IOUtils.copyImageToClipboard(this)
- } catch (e: Exception) {
- e.printStackTrace()
- }
-}
-
-/**
- * Taken from https://github.com/Moulberry/HyChat
- */
-fun Framebuffer.screenshot(file: File): BufferedImage {
- val w = this.framebufferWidth
- val h = this.framebufferHeight
- val i = w * h
- val pixelBuffer = BufferUtils.createIntBuffer(i)
- val pixelValues = IntArray(i)
- GL11.glPixelStorei(GL11.GL_PACK_ALIGNMENT, 1)
- GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1)
- GlStateManager.bindTexture(this.framebufferTexture)
- GL11.glGetTexImage(GL11.GL_TEXTURE_2D, 0, GL12.GL_BGRA, GL12.GL_UNSIGNED_INT_8_8_8_8_REV, pixelBuffer)
- pixelBuffer[pixelValues] //Load buffer into array
- TextureUtil.processPixelValues(pixelValues, w, h) //Flip vertically
- val bufferedimage = BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB)
- val j = this.framebufferTextureHeight - this.framebufferHeight
- for (k in j until this.framebufferTextureHeight) {
- for (l in 0 until this.framebufferWidth) {
- bufferedimage.setRGB(l, k - j, pixelValues[k * this.framebufferTextureWidth + l])
- }
- }
- if (ChattingConfig.copyMode != 1) {
- try {
- file.parentFile.mkdirs()
- ImageIO.write(bufferedimage, "png", file)
- } catch (e: Exception) {
- e.printStackTrace()
- }
- }
- return bufferedimage
-}
-/*/
-private val timePattern = Regex("\\[\\d+:\\d+:\\d+]")
-private var lastLines = mutableListOf<ChatLine>()
-fun timestampPre() {
- if (!ChattingConfig.showTimestampHover) return
- val drawnChatLines = (Minecraft.getMinecraft().ingameGUI.chatGUI as GuiNewChatAccessor).drawnChatLines
- val chatLine = getChatLineOverMouse(UMouse.getTrueX().roundToInt(), UMouse.getTrueY().roundToInt())
-
- lastLines.clear()
- for (line in drawnChatLines) {
- val chatComponent = line.chatComponent.createCopy()
- val newline = ChatLine(line.updatedCounter, chatComponent, line.chatLineID)
- lastLines.add(newline)
- }
-
- drawnChatLines.map {
- if (it != chatLine) it.chatComponent.siblings.removeAll { itt ->
- timePattern.find(ChatColor.stripControlCodes(itt.unformattedText)!!) != null
- }
- }
-}
-
-fun timestampPost() {
- if (!ChattingConfig.showTimestampHover) return
- val drawnChatLines = (Minecraft.getMinecraft().ingameGUI.chatGUI as GuiNewChatAccessor).drawnChatLines
- drawnChatLines.clear()
- drawnChatLines.addAll(lastLines)
-}
-
-private fun getChatLineOverMouse(mouseX: Int, mouseY: Int): ChatLine? {
- val chat = Minecraft.getMinecraft().ingameGUI.chatGUI
- if (!chat.chatOpen) return null
- val scaledResolution = ScaledResolution(Minecraft.getMinecraft())
- val i = scaledResolution.scaleFactor
- val f = chat.chatScale
- val j = MathHelper.floor_float((mouseX / i - 3).toFloat() / f)
- val k = MathHelper.floor_float((mouseY / i - 27).toFloat() / f)
- if (j < 0 || k < 0) return null
- val drawnChatLines = (chat as GuiNewChatAccessor).drawnChatLines
- val l = chat.lineCount.coerceAtMost(drawnChatLines.size)
- if (j <= MathHelper.floor_float(chat.chatWidth.toFloat() / f) && k < fontRenderer.FONT_HEIGHT * l + l) {
- val m = k / Minecraft.getMinecraft().fontRendererObj.FONT_HEIGHT + chat.scrollPos
- if (m >= 0 && m < drawnChatLines.size)
- return drawnChatLines[m]
- }
- return null
-}
-
- */ \ No newline at end of file