From 5198a5eca8257ee05e4846dc7ef46c983f7752d0 Mon Sep 17 00:00:00 2001 From: nea Date: Thu, 3 Aug 2023 20:12:53 +0200 Subject: Add chat filter gui --- .../skyhanni/features/chat/ChatFilterGui.kt | 119 +++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 src/main/java/at/hannibal2/skyhanni/features/chat/ChatFilterGui.kt (limited to 'src/main/java/at/hannibal2/skyhanni/features') diff --git a/src/main/java/at/hannibal2/skyhanni/features/chat/ChatFilterGui.kt b/src/main/java/at/hannibal2/skyhanni/features/chat/ChatFilterGui.kt new file mode 100644 index 000000000..f9566cdf1 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/chat/ChatFilterGui.kt @@ -0,0 +1,119 @@ +package at.hannibal2.skyhanni.features.chat + +import at.hannibal2.skyhanni.data.ChatManager +import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.OSUtils +import io.github.moulberry.moulconfig.internal.GlScissorStack +import io.github.moulberry.moulconfig.internal.RenderUtils +import net.minecraft.client.Minecraft +import net.minecraft.client.gui.GuiScreen +import net.minecraft.client.gui.GuiUtilRenderComponents +import net.minecraft.client.gui.ScaledResolution +import net.minecraft.client.renderer.GlStateManager +import net.minecraft.util.IChatComponent +import org.lwjgl.input.Mouse + +class ChatFilterGui(private val history: List) : GuiScreen() { + private var scroll = -1.0 + private val w = 500 + private var wasMouseButtonDown = false + private val h = 300 + private val reasonMaxLength = + history.maxOf { it.actionReason?.let { Minecraft.getMinecraft().fontRendererObj.getStringWidth(it) } ?: 0 } + private val historySize by lazy { + history.sumOf { splitLine(it.message).size * 10 + if (it.modified != null) splitLine(it.modified).size * 10 else 0 } + } + + override fun drawScreen(mouseX: Int, mouseY: Int, partialTicks: Float) { + super.drawScreen(mouseX, mouseY, partialTicks) + drawDefaultBackground() + GlStateManager.pushMatrix() + val l = (width / 2.0 - w / 2.0).toInt() + val t = (height / 2.0 - h / 2.0).toInt() + val sr = ScaledResolution(mc) + GlStateManager.translate(l + 0.0, t + 0.0, 0.0) + RenderUtils.drawFloatingRectDark(0, 0, w, h) + GlStateManager.translate(5.0, 5.0 - scroll, 0.0) + var mouseX = mouseX - (l) + val isMouseButtonDown = if (mouseX in 0..w && mouseY in t..(t + h)) + Mouse.isButtonDown(0) + else false + var mouseY = mouseY - (t - scroll).toInt() + GlStateManager.color(1f, 1f, 1f, 1f) + GlScissorStack.push(l + 5, t + 5, w + l - 5, h + t - 5, sr) + + for (msg in history) { + drawString(mc.fontRendererObj, msg.actionKind.renderedString, 0, 0, -1) + GlStateManager.color(1f, 1f, 1f, 1f) + drawString(mc.fontRendererObj, msg.actionReason, ChatManager.ActionKind.maxLength + 5, 0, -1) + GlStateManager.color(1f, 1f, 1f, 1f) + var size = drawMultiLineText( + msg.message, + ChatManager.ActionKind.maxLength + reasonMaxLength + 10, + ) + if (msg.modified != null) { + drawString( + mc.fontRendererObj, + "§e§lNEW TEXT", + 0, 0, -1 + ) + size += drawMultiLineText( + msg.modified, + ChatManager.ActionKind.maxLength + reasonMaxLength + 10, + ) + } + if (mouseX in 0..w && mouseY in 0..(size * 10) && (isMouseButtonDown && !wasMouseButtonDown)) { + OSUtils.copyToClipboard(msg.message.formattedText) + LorenzUtils.chat("Copied to clipboard") + } + mouseY -= size * 10 + } + GlScissorStack.pop(sr) + wasMouseButtonDown = isMouseButtonDown + GlStateManager.popMatrix() + } + + fun splitLine(comp: IChatComponent): MutableList { + return GuiUtilRenderComponents.splitText( + comp, + w - (ChatManager.ActionKind.maxLength + reasonMaxLength + 10 + 10), + mc.fontRendererObj, + false, + true + ) + } + + override fun initGui() { + super.initGui() + if (this.scroll < 0) { + setScroll(1000000000.0) + } + } + + fun setScroll(newScroll: Double) { + this.scroll = newScroll.coerceAtMost(historySize - h + 10.0).coerceAtLeast(0.0) + } + + fun drawMultiLineText(comp: IChatComponent, xPos: Int): Int { + val modifiedSplitText = splitLine(comp) + for (line in modifiedSplitText) { + drawString( + mc.fontRendererObj, + line.formattedText, + xPos, + 0, + -1 + ) + GlStateManager.color(1f, 1f, 1f, 1f) + GlStateManager.translate(0F, 10F, 0F) + } + return modifiedSplitText.size + } + + + override fun handleMouseInput() { + super.handleMouseInput() + setScroll(scroll - Mouse.getEventDWheel()) + } + +} \ No newline at end of file -- cgit From 67a47c003c76cebc7d57e789c114b62313a543fe Mon Sep 17 00:00:00 2001 From: nea Date: Thu, 3 Aug 2023 21:31:57 +0200 Subject: Add structured chat component support to chat filter --- .../java/at/hannibal2/skyhanni/config/commands/Commands.kt | 1 + .../java/at/hannibal2/skyhanni/features/chat/ChatFilterGui.kt | 10 ++++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'src/main/java/at/hannibal2/skyhanni/features') diff --git a/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt b/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt index 4c73c6113..e83a14c5c 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt +++ b/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt @@ -50,6 +50,7 @@ object Commands { ConfigGuiManager.openConfigGui(it.joinToString(" ")) } } else { + val arr = mutableListOf() ConfigGuiManager.openConfigGui() } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/chat/ChatFilterGui.kt b/src/main/java/at/hannibal2/skyhanni/features/chat/ChatFilterGui.kt index f9566cdf1..8f346ddea 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/chat/ChatFilterGui.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/chat/ChatFilterGui.kt @@ -11,6 +11,7 @@ import net.minecraft.client.gui.GuiUtilRenderComponents import net.minecraft.client.gui.ScaledResolution import net.minecraft.client.renderer.GlStateManager import net.minecraft.util.IChatComponent +import org.lwjgl.input.Keyboard import org.lwjgl.input.Mouse class ChatFilterGui(private val history: List) : GuiScreen() { @@ -63,8 +64,13 @@ class ChatFilterGui(private val history: List Date: Thu, 3 Aug 2023 22:17:47 +0200 Subject: Add support for retracted messages --- .../java/at/hannibal2/skyhanni/data/ChatManager.kt | 47 +++++++++++++++++----- .../features/chat/CompactBestiaryChatMessage.kt | 10 ++--- .../skyhanni/utils/IdentityCharacteristics.kt | 12 ++++++ 3 files changed, 52 insertions(+), 17 deletions(-) create mode 100644 src/main/java/at/hannibal2/skyhanni/utils/IdentityCharacteristics.kt (limited to 'src/main/java/at/hannibal2/skyhanni/features') diff --git a/src/main/java/at/hannibal2/skyhanni/data/ChatManager.kt b/src/main/java/at/hannibal2/skyhanni/data/ChatManager.kt index 399517d2a..167efdb3b 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/ChatManager.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/ChatManager.kt @@ -7,9 +7,13 @@ import at.hannibal2.skyhanni.events.PacketEvent import at.hannibal2.skyhanni.events.SeaCreatureFishEvent import at.hannibal2.skyhanni.features.chat.ChatFilterGui import at.hannibal2.skyhanni.features.fishing.SeaCreatureManager +import at.hannibal2.skyhanni.utils.IdentityCharacteristics import at.hannibal2.skyhanni.utils.LorenzLogger import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.LorenzUtils.makeAccessible import net.minecraft.client.Minecraft +import net.minecraft.client.gui.ChatLine +import net.minecraft.client.gui.GuiNewChat import net.minecraft.event.HoverEvent import net.minecraft.network.play.server.S02PacketChat import net.minecraft.util.EnumChatFormatting @@ -17,6 +21,8 @@ import net.minecraft.util.IChatComponent import net.minecraftforge.client.event.ClientChatReceivedEvent import net.minecraftforge.fml.common.eventhandler.EventPriority import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import net.minecraftforge.fml.relauncher.ReflectionHelper +import java.lang.invoke.MethodHandles import java.util.LinkedHashMap object ChatManager { @@ -26,11 +32,12 @@ object ChatManager { private val loggerAllowed = LorenzLogger("chat/allowed") private val loggerModified = LorenzLogger("chat/modified") private val loggerFilteredTypes = mutableMapOf() - private val messageHistory = object : LinkedHashMap() { - override fun removeEldestEntry(eldest: MutableMap.MutableEntry?): Boolean { - return size > 100 + private val messageHistory = + object : LinkedHashMap, MessageFilteringResult>() { + override fun removeEldestEntry(eldest: MutableMap.MutableEntry, MessageFilteringResult>?): Boolean { + return size > 100 + } } - } fun getRecentMessageHistory(): List { return messageHistory.toList().map { it.second } @@ -38,6 +45,7 @@ object ChatManager { enum class ActionKind(format: Any) { BLOCKED(EnumChatFormatting.RED.toString() + EnumChatFormatting.BOLD), + RETRACTED(EnumChatFormatting.DARK_PURPLE.toString() + EnumChatFormatting.BOLD), MODIFIED(EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD), ALLOWED(EnumChatFormatting.GREEN), ; @@ -53,8 +61,8 @@ object ChatManager { data class MessageFilteringResult( val message: IChatComponent, - val actionKind: ActionKind, - val actionReason: String?, + var actionKind: ActionKind, + var actionReason: String?, val modified: IChatComponent? ) @@ -79,7 +87,7 @@ object ChatManager { val message = LorenzUtils.stripVanillaMessage(original.formattedText) if (message.startsWith("§f{\"server\":\"")) return - + val key = IdentityCharacteristics(original) val chatEvent = LorenzChatEvent(message, original) if (!isSoopyMessage(event.message)) { chatEvent.postAndCatch() @@ -92,7 +100,7 @@ object ChatManager { loggerAll.log("[$blockReason] $message") loggerFilteredTypes.getOrPut(blockReason) { LorenzLogger("chat/filter_blocked/$blockReason") } .log(message) - messageHistory.put(Object(), MessageFilteringResult(original, ActionKind.BLOCKED, blockReason, null)) + messageHistory.put(key, MessageFilteringResult(original, ActionKind.BLOCKED, blockReason, null)) return } @@ -104,9 +112,9 @@ object ChatManager { loggerModified.log(" ") loggerModified.log("[original] " + original.formattedText) loggerModified.log("[modified] " + modified.formattedText) - messageHistory.put(Object(), MessageFilteringResult(original, ActionKind.MODIFIED, null, modified)) + messageHistory.put(key, MessageFilteringResult(original, ActionKind.MODIFIED, null, modified)) } else { - messageHistory.put(Object(), MessageFilteringResult(original, ActionKind.ALLOWED, null, null)) + messageHistory.put(key, MessageFilteringResult(original, ActionKind.ALLOWED, null, null)) } } @@ -148,4 +156,23 @@ object ChatManager { fun openChatFilterGUI() { SkyHanniMod.screenToOpen = (ChatFilterGui(getRecentMessageHistory())) } + + val chatLinesField by lazy { + MethodHandles.publicLookup().unreflectGetter( + ReflectionHelper.findField(GuiNewChat::class.java, "chatLines", "field_146252_h", "h") + .makeAccessible() + ) + } + + fun retractMessage(message: IChatComponent?, reason: String) { + if (message == null) return + val chatGUI = Minecraft.getMinecraft().ingameGUI.chatGUI + val chatLines = chatLinesField.invokeExact(chatGUI) as MutableList + if (chatLines.removeIf { it.chatComponent === message }) { + val history = messageHistory[IdentityCharacteristics(message)] + history?.actionKind = ActionKind.RETRACTED + history?.actionReason = reason.uppercase() + } + chatGUI.refreshChat() + } } \ No newline at end of file diff --git a/src/main/java/at/hannibal2/skyhanni/features/chat/CompactBestiaryChatMessage.kt b/src/main/java/at/hannibal2/skyhanni/features/chat/CompactBestiaryChatMessage.kt index 7b893afcf..67c76617b 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/chat/CompactBestiaryChatMessage.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/chat/CompactBestiaryChatMessage.kt @@ -1,6 +1,7 @@ package at.hannibal2.skyhanni.features.chat import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.data.ChatManager import at.hannibal2.skyhanni.events.LorenzChatEvent import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.LorenzUtils.makeAccessible @@ -41,13 +42,8 @@ class CompactBestiaryChatMessage { if (message == titleMessage) { event.blockedReason = "bestiary" - val chatGUI = Minecraft.getMinecraft().ingameGUI.chatGUI - val chatLinesField = ReflectionHelper.findField(chatGUI.javaClass, "chatLines") - val chatLines = chatLinesField.makeAccessible().get(chatGUI) as MutableList - - lastBorder?.let { chat -> chatLines.removeIf { it.chatComponent === chat } } - lastEmpty?.let { chat -> chatLines.removeIf { it.chatComponent === chat } } - chatGUI.refreshChat() + ChatManager.retractMessage(lastBorder, "bestiary") + ChatManager.retractMessage(lastEmpty, "bestiary") lastBorder = null lastEmpty = null diff --git a/src/main/java/at/hannibal2/skyhanni/utils/IdentityCharacteristics.kt b/src/main/java/at/hannibal2/skyhanni/utils/IdentityCharacteristics.kt new file mode 100644 index 000000000..5b1399f73 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/utils/IdentityCharacteristics.kt @@ -0,0 +1,12 @@ +package at.hannibal2.skyhanni.utils + +class IdentityCharacteristics(val value: T) { + override fun equals(other: Any?): Boolean { + if (other !is IdentityCharacteristics<*>) return false + return this.value === other.value + } + + override fun hashCode(): Int { + return System.identityHashCode(value) + } +} -- cgit From a4c61672d93aaf7418568ca6b3704289d890f48b Mon Sep 17 00:00:00 2001 From: hannibal2 <24389977+hannibal00212@users.noreply.github.com> Date: Thu, 3 Aug 2023 23:36:44 +0200 Subject: code cleanup --- .../java/at/hannibal2/skyhanni/data/ChatManager.kt | 18 ++++++++---------- .../hannibal2/skyhanni/features/chat/ChatFilterGui.kt | 16 +++++----------- 2 files changed, 13 insertions(+), 21 deletions(-) (limited to 'src/main/java/at/hannibal2/skyhanni/features') diff --git a/src/main/java/at/hannibal2/skyhanni/data/ChatManager.kt b/src/main/java/at/hannibal2/skyhanni/data/ChatManager.kt index 167efdb3b..8b6330f6d 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/ChatManager.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/ChatManager.kt @@ -23,7 +23,6 @@ import net.minecraftforge.fml.common.eventhandler.EventPriority import net.minecraftforge.fml.common.eventhandler.SubscribeEvent import net.minecraftforge.fml.relauncher.ReflectionHelper import java.lang.invoke.MethodHandles -import java.util.LinkedHashMap object ChatManager { @@ -39,9 +38,7 @@ object ChatManager { } } - fun getRecentMessageHistory(): List { - return messageHistory.toList().map { it.second } - } + fun getRecentMessageHistory(): List = messageHistory.toList().map { it.second } enum class ActionKind(format: Any) { BLOCKED(EnumChatFormatting.RED.toString() + EnumChatFormatting.BOLD), @@ -154,7 +151,7 @@ object ChatManager { } fun openChatFilterGUI() { - SkyHanniMod.screenToOpen = (ChatFilterGui(getRecentMessageHistory())) + SkyHanniMod.screenToOpen = ChatFilterGui(getRecentMessageHistory()) } val chatLinesField by lazy { @@ -167,12 +164,13 @@ object ChatManager { fun retractMessage(message: IChatComponent?, reason: String) { if (message == null) return val chatGUI = Minecraft.getMinecraft().ingameGUI.chatGUI + @Suppress("UNCHECKED_CAST") val chatLines = chatLinesField.invokeExact(chatGUI) as MutableList - if (chatLines.removeIf { it.chatComponent === message }) { - val history = messageHistory[IdentityCharacteristics(message)] - history?.actionKind = ActionKind.RETRACTED - history?.actionReason = reason.uppercase() - } + if (!chatLines.removeIf { it.chatComponent === message }) return chatGUI.refreshChat() + + val history = messageHistory[IdentityCharacteristics(message)] ?: return + history.actionKind = ActionKind.RETRACTED + history.actionReason = reason.uppercase() } } \ No newline at end of file diff --git a/src/main/java/at/hannibal2/skyhanni/features/chat/ChatFilterGui.kt b/src/main/java/at/hannibal2/skyhanni/features/chat/ChatFilterGui.kt index 8f346ddea..971878306 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/chat/ChatFilterGui.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/chat/ChatFilterGui.kt @@ -11,7 +11,6 @@ import net.minecraft.client.gui.GuiUtilRenderComponents import net.minecraft.client.gui.ScaledResolution import net.minecraft.client.renderer.GlStateManager import net.minecraft.util.IChatComponent -import org.lwjgl.input.Keyboard import org.lwjgl.input.Mouse class ChatFilterGui(private val history: List) : GuiScreen() { @@ -31,23 +30,18 @@ class ChatFilterGui(private val history: List { + fun splitLine(comp: IChatComponent): List { return GuiUtilRenderComponents.splitText( comp, w - (ChatManager.ActionKind.maxLength + reasonMaxLength + 10 + 10), @@ -110,7 +105,6 @@ class ChatFilterGui(private val history: List