aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main/java/org/polyfrost/chatting/hook/ChatLineHook.java8
-rw-r--r--src/main/java/org/polyfrost/chatting/mixin/ChatLineMixin.java91
-rw-r--r--src/main/java/org/polyfrost/chatting/mixin/GuiChatMixin.java19
-rw-r--r--src/main/java/org/polyfrost/chatting/mixin/GuiNewChatMixin.java42
-rw-r--r--src/main/java/org/polyfrost/chatting/mixin/GuiUtilRenderComponentsMixin.java19
-rw-r--r--src/main/kotlin/org/polyfrost/chatting/Chatting.kt2
-rw-r--r--src/main/kotlin/org/polyfrost/chatting/utils/ChatHeadHooks.kt74
-rw-r--r--src/main/kotlin/org/polyfrost/chatting/utils/ModCompatHooks.kt2
-rw-r--r--src/main/resources/mixins.chatting.json43
9 files changed, 219 insertions, 81 deletions
diff --git a/src/main/java/org/polyfrost/chatting/hook/ChatLineHook.java b/src/main/java/org/polyfrost/chatting/hook/ChatLineHook.java
index 50b9ce3..22f180c 100644
--- a/src/main/java/org/polyfrost/chatting/hook/ChatLineHook.java
+++ b/src/main/java/org/polyfrost/chatting/hook/ChatLineHook.java
@@ -8,8 +8,14 @@ import java.util.HashSet;
public interface ChatLineHook {
HashSet<WeakReference<ChatLine>> chatLines = new HashSet<>();
- boolean hasDetected();
+ boolean isDetected();
+ void setDetected(boolean detected);
NetworkPlayerInfo getPlayerInfo();
+ void setPlayerInfo(NetworkPlayerInfo playerInfo);
+ NetworkPlayerInfo getDetectedPlayerInfo();
+ void setDetectedPlayerInfo(NetworkPlayerInfo detectedPlayerInfo);
+ boolean isFirstDetection();
+ void setFirstDetection(boolean firstDetection);
void updatePlayerInfo();
diff --git a/src/main/java/org/polyfrost/chatting/mixin/ChatLineMixin.java b/src/main/java/org/polyfrost/chatting/mixin/ChatLineMixin.java
index 2e5f21c..cde09ea 100644
--- a/src/main/java/org/polyfrost/chatting/mixin/ChatLineMixin.java
+++ b/src/main/java/org/polyfrost/chatting/mixin/ChatLineMixin.java
@@ -7,28 +7,23 @@ package org.polyfrost.chatting.mixin;
import org.polyfrost.chatting.config.ChattingConfig;
import org.polyfrost.chatting.hook.ChatLineHook;
-import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.ChatLine;
-import net.minecraft.client.network.NetHandlerPlayClient;
import net.minecraft.client.network.NetworkPlayerInfo;
import net.minecraft.util.IChatComponent;
-import org.jetbrains.annotations.Nullable;
+import org.polyfrost.chatting.utils.ChatHeadHooks;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.lang.ref.WeakReference;
-import java.util.HashMap;
-import java.util.Map;
@Mixin(ChatLine.class)
public class ChatLineMixin implements ChatLineHook {
private boolean detected = false;
- private boolean first = true;
+ private boolean firstDetection = true;
private NetworkPlayerInfo playerInfo;
private NetworkPlayerInfo detectedPlayerInfo;
- private static NetworkPlayerInfo lastPlayerInfo;
private static long lastUniqueId = 0;
private long uniqueId = 0;
@@ -37,60 +32,17 @@ public class ChatLineMixin implements ChatLineHook {
lastUniqueId++;
uniqueId = lastUniqueId;
chatLines.add(new WeakReference<>((ChatLine) (Object) this));
- NetHandlerPlayClient netHandler = Minecraft.getMinecraft().getNetHandler();
- if (netHandler == null) return;
- Map<String, NetworkPlayerInfo> nicknameCache = new HashMap<>();
- try {
- for (String word : iChatComponent.getFormattedText().split("(§.)|\\W")) {
- if (word.isEmpty()) continue;
- playerInfo = netHandler.getPlayerInfo(word);
- if (playerInfo == null) {
- playerInfo = getPlayerFromNickname(word, netHandler, nicknameCache);
- }
- if (playerInfo != null) {
- detectedPlayerInfo = playerInfo;
- detected = true;
- if (playerInfo == lastPlayerInfo) {
- first = false;
- if (ChattingConfig.INSTANCE.getHideChatHeadOnConsecutiveMessages()) {
- playerInfo = null;
- }
- } else {
- lastPlayerInfo = playerInfo;
- }
- break;
- }
- }
- } catch (Exception ignored) {
- }
+ ChatHeadHooks.INSTANCE.detect(iChatComponent.getFormattedText(), (ChatLine) (Object) this);
}
- @Nullable
- private static NetworkPlayerInfo getPlayerFromNickname(String word, NetHandlerPlayClient connection, Map<String, NetworkPlayerInfo> nicknameCache) {
- if (nicknameCache.isEmpty()) {
- for (NetworkPlayerInfo p : connection.getPlayerInfoMap()) {
- IChatComponent displayName = p.getDisplayName();
- if (displayName != null) {
- String nickname = displayName.getUnformattedTextForChat();
- if (word.equals(nickname)) {
- nicknameCache.clear();
- return p;
- }
-
- nicknameCache.put(nickname, p);
- }
- }
- } else {
- // use prepared cache
- return nicknameCache.get(word);
- }
-
- return null;
+ @Override
+ public boolean isDetected() {
+ return detected;
}
@Override
- public boolean hasDetected() {
- return detected;
+ public void setDetected(boolean detected) {
+ this.detected = detected;
}
@Override
@@ -99,8 +51,33 @@ public class ChatLineMixin implements ChatLineHook {
}
@Override
+ public void setPlayerInfo(NetworkPlayerInfo playerInfo) {
+ this.playerInfo = playerInfo;
+ }
+
+ @Override
+ public NetworkPlayerInfo getDetectedPlayerInfo() {
+ return detectedPlayerInfo;
+ }
+
+ @Override
+ public void setDetectedPlayerInfo(NetworkPlayerInfo detectedPlayerInfo) {
+ this.detectedPlayerInfo = detectedPlayerInfo;
+ }
+
+ @Override
+ public boolean isFirstDetection() {
+ return firstDetection;
+ }
+
+ @Override
+ public void setFirstDetection(boolean firstDetection) {
+ this.firstDetection = firstDetection;
+ }
+
+ @Override
public void updatePlayerInfo() {
- if (ChattingConfig.INSTANCE.getHideChatHeadOnConsecutiveMessages() && !first) {
+ if (ChattingConfig.INSTANCE.getHideChatHeadOnConsecutiveMessages() && !firstDetection) {
playerInfo = null;
} else {
playerInfo = detectedPlayerInfo;
diff --git a/src/main/java/org/polyfrost/chatting/mixin/GuiChatMixin.java b/src/main/java/org/polyfrost/chatting/mixin/GuiChatMixin.java
index 167bbd4..d434958 100644
--- a/src/main/java/org/polyfrost/chatting/mixin/GuiChatMixin.java
+++ b/src/main/java/org/polyfrost/chatting/mixin/GuiChatMixin.java
@@ -1,5 +1,6 @@
package org.polyfrost.chatting.mixin;
+import cc.polyfrost.oneconfig.libs.universal.UResolution;
import org.polyfrost.chatting.chat.*;
import org.polyfrost.chatting.config.ChattingConfig;
import org.polyfrost.chatting.gui.components.ClearButton;
@@ -102,6 +103,15 @@ public abstract class GuiChatMixin extends GuiScreen {
return ChattingConfig.INSTANCE.getInputBoxBackgroundColor().getRGB();
}
+ @ModifyArg(method = "drawScreen", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiNewChat;getChatComponent(II)Lnet/minecraft/util/IChatComponent;"), index = 0)
+ private int modifyChatComponentX(int x) {
+ if (ChattingConfig.INSTANCE.getShowChatHeads()) {
+ return x - (10 * (int) UResolution.getScaleFactor());
+ } else {
+ return x;
+ }
+ }
+
@Inject(method = "mouseClicked", at = @At("HEAD"))
private void mouseClicked(int mouseX, int mouseY, int mouseButton, CallbackInfo ci) {
GuiNewChatHook hook = ((GuiNewChatHook) Minecraft.getMinecraft().ingameGUI.getChatGUI());
@@ -126,6 +136,15 @@ public abstract class GuiChatMixin extends GuiScreen {
}
+ @ModifyArg(method = "mouseClicked", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiNewChat;getChatComponent(II)Lnet/minecraft/util/IChatComponent;"), index = 0)
+ private int modifyChatComponentX2(int x) {
+ if (ChattingConfig.INSTANCE.getShowChatHeads()) {
+ return x - (10 * (int) UResolution.getScaleFactor());
+ } else {
+ return x;
+ }
+ }
+
@ModifyArg(method = "keyTyped", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiChat;sendChatMessage(Ljava/lang/String;)V"), index = 0)
private String modifySentMessage(String original) {
if (ChattingConfig.INSTANCE.getChatShortcuts()) {
diff --git a/src/main/java/org/polyfrost/chatting/mixin/GuiNewChatMixin.java b/src/main/java/org/polyfrost/chatting/mixin/GuiNewChatMixin.java
index bc90730..4733ab6 100644
--- a/src/main/java/org/polyfrost/chatting/mixin/GuiNewChatMixin.java
+++ b/src/main/java/org/polyfrost/chatting/mixin/GuiNewChatMixin.java
@@ -1,10 +1,13 @@
package org.polyfrost.chatting.mixin;
import cc.polyfrost.oneconfig.libs.universal.UMouse;
+import cc.polyfrost.oneconfig.libs.universal.UResolution;
import cc.polyfrost.oneconfig.utils.Notifications;
+import net.minecraft.util.IChatComponent;
import org.polyfrost.chatting.Chatting;
import org.polyfrost.chatting.chat.ChatSearchingManager;
import org.polyfrost.chatting.config.ChattingConfig;
+import org.polyfrost.chatting.hook.ChatLineHook;
import org.polyfrost.chatting.hook.GuiNewChatHook;
import org.polyfrost.chatting.utils.ModCompatHooks;
import org.polyfrost.chatting.utils.RenderUtils;
@@ -20,6 +23,7 @@ import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.*;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import org.spongepowered.asm.mixin.injection.invoke.arg.Args;
import java.awt.datatransfer.StringSelection;
@@ -161,6 +165,44 @@ public abstract class GuiNewChatMixin extends Gui implements GuiNewChatHook {
}
}
+ @Unique
+ private boolean chatting$cancelChatComponent = false;
+ @Unique
+ private int chatting$lastMouseX = 0;
+ @Unique
+ private int chatting$lastMouseY = 0;
+
+ @Inject(method = "getChatComponent", at = @At(value = "INVOKE", target = "Ljava/util/List;get(I)Ljava/lang/Object;"))
+ private void storeMouseXAndY(int mouseX, int mouseY, CallbackInfoReturnable<IChatComponent> cir) {
+ chatting$lastMouseX = mouseX;
+ chatting$lastMouseY = mouseY;
+ }
+
+ @ModifyVariable(method = "getChatComponent", at = @At("STORE"), ordinal = 0)
+ private ChatLine storeChatLine(ChatLine line) {
+ if (ChattingConfig.INSTANCE.getShowChatHeads() && !((ChatLineHook) line).isDetected() && !ChattingConfig.INSTANCE.getOffsetNonPlayerMessages()) {
+ int i = (int) UResolution.getScaleFactor();
+ float f = this.getChatScale();
+ int j = chatting$lastMouseX / i - 3;
+ int k = chatting$lastMouseY / i - 27;
+ j = MathHelper.floor_float((float)j / f);
+ k = MathHelper.floor_float((float)k / f);
+ int l = Math.min(this.getLineCount(), this.drawnChatLines.size());
+ if (j > MathHelper.floor_float((float)this.getChatWidth() / this.getChatScale()) && k < this.mc.fontRendererObj.FONT_HEIGHT * l + l) {
+ chatting$cancelChatComponent = true;
+ }
+ }
+ return line;
+ }
+
+ @Inject(method = "getChatComponent", at = @At(value = "INVOKE", target = "Ljava/util/List;get(I)Ljava/lang/Object;", shift = At.Shift.AFTER), cancellable = true)
+ private void cancelChatComponent(int mouseX, int mouseY, CallbackInfoReturnable<IChatComponent> cir) {
+ if (chatting$cancelChatComponent) {
+ cir.setReturnValue(null);
+ chatting$cancelChatComponent = false;
+ }
+ }
+
@Override
public int getRight() {
return chatting$right;
diff --git a/src/main/java/org/polyfrost/chatting/mixin/GuiUtilRenderComponentsMixin.java b/src/main/java/org/polyfrost/chatting/mixin/GuiUtilRenderComponentsMixin.java
new file mode 100644
index 0000000..fd497a6
--- /dev/null
+++ b/src/main/java/org/polyfrost/chatting/mixin/GuiUtilRenderComponentsMixin.java
@@ -0,0 +1,19 @@
+package org.polyfrost.chatting.mixin;
+
+import net.minecraft.client.gui.GuiUtilRenderComponents;
+import org.polyfrost.chatting.config.ChattingConfig;
+import org.polyfrost.chatting.utils.ChatHeadHooks;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Redirect;
+
+@Mixin(GuiUtilRenderComponents.class)
+public class GuiUtilRenderComponentsMixin {
+ @Redirect(method = "splitText", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/FontRenderer;getStringWidth(Ljava/lang/String;)I"))
+ private static int modifyChatLineX(net.minecraft.client.gui.FontRenderer fontRenderer, String text) {
+ if (ChattingConfig.INSTANCE.getShowChatHeads() && (ChattingConfig.INSTANCE.getOffsetNonPlayerMessages() || ChatHeadHooks.INSTANCE.detect(text, null))) {
+ return fontRenderer.getStringWidth(text) + 10;
+ }
+ return fontRenderer.getStringWidth(text);
+ }
+}
diff --git a/src/main/kotlin/org/polyfrost/chatting/Chatting.kt b/src/main/kotlin/org/polyfrost/chatting/Chatting.kt
index 0e8745c..cf439ce 100644
--- a/src/main/kotlin/org/polyfrost/chatting/Chatting.kt
+++ b/src/main/kotlin/org/polyfrost/chatting/Chatting.kt
@@ -245,7 +245,7 @@ object Chatting {
}
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 width = messages.maxOf { fr.getStringWidth(it.value) + (if (ChattingConfig.showChatHeads && ((it.key as ChatLineHook).isDetected || 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()))
diff --git a/src/main/kotlin/org/polyfrost/chatting/utils/ChatHeadHooks.kt b/src/main/kotlin/org/polyfrost/chatting/utils/ChatHeadHooks.kt
new file mode 100644
index 0000000..aa777c1
--- /dev/null
+++ b/src/main/kotlin/org/polyfrost/chatting/utils/ChatHeadHooks.kt
@@ -0,0 +1,74 @@
+package org.polyfrost.chatting.utils
+
+import net.minecraft.client.Minecraft
+import net.minecraft.client.gui.ChatLine
+import net.minecraft.client.network.NetHandlerPlayClient
+import net.minecraft.client.network.NetworkPlayerInfo
+import org.polyfrost.chatting.config.ChattingConfig.hideChatHeadOnConsecutiveMessages
+import org.polyfrost.chatting.hook.ChatLineHook
+
+object ChatHeadHooks {
+ private var lastPlayerInfo: NetworkPlayerInfo? = null
+ fun detect(formattedText: String, chatLine: ChatLine?): Boolean {
+ if (chatLine !is ChatLineHook) {
+ return false
+ }
+ val netHandler = Minecraft.getMinecraft().netHandler ?: return false
+ val nicknameCache: MutableMap<String, NetworkPlayerInfo> = HashMap()
+ var detected = false
+ try {
+ formattedText.split("(§.)|\\W".toRegex()).dropLastWhile { it.isEmpty() }
+ .forEach { word ->
+ if (word.isNotEmpty()) {
+ var maybePlayerInfo = netHandler.getPlayerInfo(word)
+ if (maybePlayerInfo == null) {
+ maybePlayerInfo = getPlayerFromNickname(word, netHandler, nicknameCache)
+ }
+ if (maybePlayerInfo != null) {
+ detected = true
+ chatLine.run {
+ playerInfo = maybePlayerInfo
+ detectedPlayerInfo = playerInfo
+ isDetected = true
+ if (playerInfo == lastPlayerInfo) {
+ isFirstDetection = false
+ if (hideChatHeadOnConsecutiveMessages) {
+ playerInfo = null
+ }
+ } else {
+ lastPlayerInfo = playerInfo
+ }
+ return@forEach
+ }
+ }
+ }
+ }
+ } catch (ignored: Exception) {
+ }
+ return detected
+ }
+
+ private fun getPlayerFromNickname(
+ word: String,
+ connection: NetHandlerPlayClient,
+ nicknameCache: MutableMap<String, NetworkPlayerInfo>
+ ): NetworkPlayerInfo? {
+ if (nicknameCache.isEmpty()) {
+ for (p in connection.playerInfoMap) {
+ val displayName = p.displayName
+ if (displayName != null) {
+ val nickname = displayName.unformattedTextForChat
+ if (word == nickname) {
+ nicknameCache.clear()
+ return p
+ }
+ nicknameCache[nickname] = p
+ }
+ }
+ } else {
+ // use prepared cache
+ return nicknameCache[word]
+ }
+ return null
+ }
+} \ No newline at end of file
diff --git a/src/main/kotlin/org/polyfrost/chatting/utils/ModCompatHooks.kt b/src/main/kotlin/org/polyfrost/chatting/utils/ModCompatHooks.kt
index b6198fa..591461d 100644
--- a/src/main/kotlin/org/polyfrost/chatting/utils/ModCompatHooks.kt
+++ b/src/main/kotlin/org/polyfrost/chatting/utils/ModCompatHooks.kt
@@ -58,7 +58,7 @@ object ModCompatHooks {
var actualX = x
if (showChatHeads && !screenshot) {
val hook = chatLine as ChatLineHook
- if (hook.hasDetected() || offsetNonPlayerMessages) {
+ if (hook.isDetected || offsetNonPlayerMessages) {
actualX += 10f
}
val networkPlayerInfo = hook.playerInfo
diff --git a/src/main/resources/mixins.chatting.json b/src/main/resources/mixins.chatting.json
index ce96f59..429b9f5 100644
--- a/src/main/resources/mixins.chatting.json
+++ b/src/main/resources/mixins.chatting.json
@@ -1,23 +1,24 @@
{
- "compatibilityLevel": "JAVA_8",
- "minVersion": "0.7",
- "package": "org.polyfrost.chatting.mixin",
- "refmap": "mixins.${id}.refmap.json",
- "verbose": true,
- "client": [
- "ChatLineMixin",
- "ClientCommandHandlerMixin",
- "EntityPlayerSPMixin",
- "GuiChatMixin",
- "GuiNewChatAccessor",
- "GuiNewChatMapMixin",
- "GuiNewChatMixin",
- "GuiNewChatMixin_ChatHeight",
- "GuiNewChatMixin_ChatSearching",
- "GuiNewChatMixin_ChatTabs",
- "GuiNewChatMixin_Scrolling",
- "GuiNewChatMixin_SmoothMessages",
- "GuiNewChatMixin_TextRendering",
- "GuiUtilsMixin"
- ]
+ "compatibilityLevel": "JAVA_8",
+ "minVersion": "0.7",
+ "package": "org.polyfrost.chatting.mixin",
+ "refmap": "mixins.${id}.refmap.json",
+ "verbose": true,
+ "client": [
+ "ChatLineMixin",
+ "ClientCommandHandlerMixin",
+ "EntityPlayerSPMixin",
+ "GuiChatMixin",
+ "GuiNewChatAccessor",
+ "GuiNewChatMapMixin",
+ "GuiNewChatMixin",
+ "GuiNewChatMixin_ChatHeight",
+ "GuiNewChatMixin_ChatSearching",
+ "GuiNewChatMixin_ChatTabs",
+ "GuiNewChatMixin_Scrolling",
+ "GuiNewChatMixin_SmoothMessages",
+ "GuiNewChatMixin_TextRendering",
+ "GuiUtilRenderComponentsMixin",
+ "GuiUtilsMixin"
+ ]
} \ No newline at end of file