From eb4b815095666bd9d13074a052c4329ba9ac7da7 Mon Sep 17 00:00:00 2001 From: Linnea Gräf Date: Wed, 14 Feb 2024 20:46:25 +0100 Subject: Add mod identification for outgoing mod calls and show this data in /shchathistory. #987 --- .../java/at/hannibal2/skyhanni/data/ChatManager.kt | 28 ++++++++++++++++++---- .../at/hannibal2/skyhanni/events/PacketEvent.kt | 12 ++++++++++ .../skyhanni/features/chat/ChatFilterGui.kt | 22 ++++++++++++----- .../skyhanni/mixins/hooks/EntityPlayerSPHook.kt | 7 ------ .../mixins/transformers/MixinEntityPlayerSP.java | 17 ------------- .../skyhanni/test/CommandsSendToServerLogger.kt | 21 ---------------- .../at/hannibal2/skyhanni/utils/ReflectionUtils.kt | 21 ++++++++++++++++ 7 files changed, 73 insertions(+), 55 deletions(-) delete mode 100644 src/main/java/at/hannibal2/skyhanni/mixins/hooks/EntityPlayerSPHook.kt delete mode 100644 src/main/java/at/hannibal2/skyhanni/mixins/transformers/MixinEntityPlayerSP.java (limited to 'src/main/java') diff --git a/src/main/java/at/hannibal2/skyhanni/data/ChatManager.kt b/src/main/java/at/hannibal2/skyhanni/data/ChatManager.kt index d631e8e26..7d0bb6728 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/ChatManager.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/ChatManager.kt @@ -9,6 +9,8 @@ import at.hannibal2.skyhanni.features.chat.ChatFilterGui import at.hannibal2.skyhanni.utils.IdentityCharacteristics import at.hannibal2.skyhanni.utils.LorenzLogger import at.hannibal2.skyhanni.utils.LorenzUtils +import at.hannibal2.skyhanni.utils.ReflectionUtils.getClassInstance +import at.hannibal2.skyhanni.utils.ReflectionUtils.getModContainer import at.hannibal2.skyhanni.utils.ReflectionUtils.makeAccessible import net.minecraft.client.Minecraft import net.minecraft.client.gui.ChatLine @@ -65,6 +67,8 @@ object ChatManager { var actionKind: ActionKind, var actionReason: String?, val modified: IChatComponent?, + val hoverInfo: List = listOf(), + val hoverExtraInfo: List = listOf(), ) @SubscribeEvent(priority = EventPriority.LOW, receiveCanceled = true) @@ -85,12 +89,28 @@ object ChatManager { val message = packet.message val component = ChatComponentText(message) - messageHistory[IdentityCharacteristics(component)] = - MessageFilteringResult(component, ActionKind.OUTGOING, null, null) + val originatingModCall = event.findOriginatingModCall() + val originatingModContainer = originatingModCall?.getClassInstance()?.getModContainer() + val hoverInfo = listOf( + "§7Message created by §a${originatingModCall?.toString() ?: "§cprobably minecraft"}", + "§7Mod id: §a${originatingModContainer?.modId}", + "§7Mod name: §a${originatingModContainer?.name}" + ) + val stackTrace = + Thread.currentThread().stackTrace.map { + "§7 §2${it.className}§7.§a${it.methodName}§7" + + if (it.fileName == null) "" else "(§b${it.fileName}§7:§3${it.lineNumber}§7)" + } + val result = MessageFilteringResult( + component, ActionKind.OUTGOING, null, null, + hoverInfo = hoverInfo, + hoverExtraInfo = hoverInfo + listOf("") + stackTrace + ) + + messageHistory[IdentityCharacteristics(component)] = result if (MessageSendToServerEvent(message).postAndCatch()) { event.isCanceled = true - messageHistory[IdentityCharacteristics(component)] = - MessageFilteringResult(component, ActionKind.OUTGOING_BLOCKED, null, null) + messageHistory[IdentityCharacteristics(component)] = result.copy(actionKind = ActionKind.OUTGOING_BLOCKED) } } diff --git a/src/main/java/at/hannibal2/skyhanni/events/PacketEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/PacketEvent.kt index 7d356707e..1c9905ce6 100644 --- a/src/main/java/at/hannibal2/skyhanni/events/PacketEvent.kt +++ b/src/main/java/at/hannibal2/skyhanni/events/PacketEvent.kt @@ -26,6 +26,18 @@ abstract class PacketEvent : LorenzEvent() { data class SendEvent(override val packet: Packet<*>) : PacketEvent() { override val direction = Direction.OUTBOUND + + fun findOriginatingModCall(skipSkyhanni: Boolean = false): StackTraceElement? { + val nonMinecraftOriginatingStack = Thread.currentThread().stackTrace + // Skip calls before the event is being called + .dropWhile { it.className != "net.minecraft.client.network.NetHandlerPlayClient" } + // Limit the remaining callstack until only the main entrypoint to hide the relauncher + .takeWhile { !it.className.endsWith(".Main") } + // Drop minecraft or skyhanni call frames + .dropWhile { it.className.startsWith("net.minecraft.") || (skipSkyhanni && it.className.startsWith("at.hannibal2.skyhanni.")) } + .firstOrNull() + return nonMinecraftOriginatingStack + } } enum class Direction { 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 e40854c9d..0e9392ea0 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/chat/ChatFilterGui.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/chat/ChatFilterGui.kt @@ -7,6 +7,7 @@ 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 io.github.moulberry.notenoughupdates.util.Utils import net.minecraft.client.Minecraft import net.minecraft.client.gui.GuiScreen import net.minecraft.client.gui.GuiUtilRenderComponents @@ -27,18 +28,19 @@ class ChatFilterGui(private val history: List? = null GlStateManager.pushMatrix() val l = (width / 2.0 - w / 2.0).toInt() val t = (height / 2.0 - h / 2.0).toInt() 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 = mouseX in 0..w && mouseY in t..(t + h) && Mouse.isButtonDown(0) - var mouseY = mouseY - (t - scroll).toInt() + var mouseX = originalMouseX - l + val isMouseButtonDown = mouseX in 0..w && originalMouseY in t..(t + h) && Mouse.isButtonDown(0) + var mouseY = originalMouseY - (t - scroll).toInt() val sr = ScaledResolution(mc) GlScissorStack.push(l + 5, t + 5, w + l - 5, h + t - 5, sr) @@ -60,7 +62,12 @@ class ChatFilterGui(private val history: List { + return Class.forName(this.className) + } + + private val packageLookup by lazy { + Loader.instance().modList + .flatMap { mod -> mod.ownedPackages.map { it to mod } } + .toMap() + } + + val Class<*>.shPackageName + get() = + canonicalName.substringBeforeLast('.') + + fun Class<*>.getModContainer(): ModContainer? { + return packageLookup[shPackageName] + } + } -- cgit