diff options
Diffstat (limited to 'src/main/java/cc/woverflow')
3 files changed, 145 insertions, 0 deletions
diff --git a/src/main/java/cc/woverflow/chatting/hook/ChatLineHook.java b/src/main/java/cc/woverflow/chatting/hook/ChatLineHook.java new file mode 100644 index 0000000..fb10225 --- /dev/null +++ b/src/main/java/cc/woverflow/chatting/hook/ChatLineHook.java @@ -0,0 +1,15 @@ +package cc.woverflow.chatting.hook; + +import net.minecraft.client.gui.ChatLine; +import net.minecraft.client.network.NetworkPlayerInfo; + +import java.lang.ref.WeakReference; +import java.util.HashSet; + +public interface ChatLineHook { + HashSet<WeakReference<ChatLine>> chatLines = new HashSet<>(); + boolean hasDetected(); + NetworkPlayerInfo getPlayerInfo(); + + void updatePlayerInfo(); +} diff --git a/src/main/java/cc/woverflow/chatting/mixin/ChatLineMixin.java b/src/main/java/cc/woverflow/chatting/mixin/ChatLineMixin.java new file mode 100644 index 0000000..b739284 --- /dev/null +++ b/src/main/java/cc/woverflow/chatting/mixin/ChatLineMixin.java @@ -0,0 +1,101 @@ +/* + * This file is from chat_heads is licensed under MPL-2.0, which can be found at https://www.mozilla.org/en-US/MPL/2.0/ + * See: https://github.com/dzwdz/chat_heads/blob/fabric-1.16.x/LICENSE + */ + +package cc.woverflow.chatting.mixin; + +import cc.woverflow.chatting.config.ChattingConfig; +import cc.woverflow.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.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 NetworkPlayerInfo playerInfo; + private NetworkPlayerInfo detectedPlayerInfo; + private static NetworkPlayerInfo lastPlayerInfo; + + @Inject(method = "<init>", at = @At("RETURN")) + private void onInit(int i, IChatComponent iChatComponent, int j, CallbackInfo ci) { + chatLines.add(new WeakReference<>((ChatLine) (Object) this)); + NetHandlerPlayClient netHandler = Minecraft.getMinecraft().getNetHandler(); + Map<String, NetworkPlayerInfo> nicknameCache = new HashMap<>(); + 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; + } + } + } + + @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 hasDetected() { + return detected; + } + + @Override + public NetworkPlayerInfo getPlayerInfo() { + return playerInfo; + } + + @Override + public void updatePlayerInfo() { + if (ChattingConfig.INSTANCE.getHideChatHeadOnConsecutiveMessages() && !first) { + playerInfo = null; + } else { + playerInfo = detectedPlayerInfo; + } + } +} diff --git a/src/main/java/cc/woverflow/chatting/mixin/GuiNewChatMixin.java b/src/main/java/cc/woverflow/chatting/mixin/GuiNewChatMixin.java index 13c91ef..a430f8e 100644 --- a/src/main/java/cc/woverflow/chatting/mixin/GuiNewChatMixin.java +++ b/src/main/java/cc/woverflow/chatting/mixin/GuiNewChatMixin.java @@ -1,17 +1,20 @@ package cc.woverflow.chatting.mixin; import cc.polyfrost.oneconfig.config.core.OneColor; +import cc.polyfrost.oneconfig.utils.color.ColorUtils; import cc.woverflow.chatting.Chatting; import cc.woverflow.chatting.chat.ChatSearchingManager; import cc.woverflow.chatting.chat.ChatTabs; import cc.woverflow.chatting.config.ChattingConfig; import cc.woverflow.chatting.gui.components.CleanButton; +import cc.woverflow.chatting.hook.ChatLineHook; import cc.woverflow.chatting.hook.GuiNewChatHook; import cc.woverflow.chatting.utils.ModCompatHooks; import cc.woverflow.chatting.utils.RenderUtils; import cc.polyfrost.oneconfig.libs.universal.UMouse; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.*; +import net.minecraft.client.network.NetworkPlayerInfo; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.IChatComponent; @@ -25,6 +28,7 @@ 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.callback.LocalCapture; import org.spongepowered.asm.mixin.injection.invoke.arg.Args; import java.awt.datatransfer.StringSelection; @@ -141,6 +145,14 @@ public abstract class GuiNewChatMixin extends Gui implements GuiNewChatHook { } } + @Unique + private ChatLine chatting$drawingLine = null; + + @Inject(method = "drawChat", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/ChatLine;getChatComponent()Lnet/minecraft/util/IChatComponent;"), locals = LocalCapture.CAPTURE_FAILSOFT) + private void captureChatLine(int updateCounter, CallbackInfo ci, int i, boolean bl, int j, int k, float f, float g, int l, int m, ChatLine chatLine, int n, double d, int o, int p, int q) { + chatting$drawingLine = chatLine; + } + @ModifyArgs(method = "drawChat", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/FontRenderer;drawStringWithShadow(Ljava/lang/String;FFI)I")) private void drawChatBox(Args args) { if (mc.currentScreen instanceof GuiChat) { @@ -155,6 +167,23 @@ public abstract class GuiNewChatMixin extends Gui implements GuiNewChatHook { } } lineInBounds = false; + if (ChattingConfig.INSTANCE.getShowChatHeads()) { + ChatLineHook hook = ((ChatLineHook) chatting$drawingLine); + if (hook.hasDetected() || ChattingConfig.INSTANCE.getOffsetNonPlayerMessages()) { + args.set(1, ((float) args.get(1)) + 10f); + } + NetworkPlayerInfo networkPlayerInfo = hook.getPlayerInfo(); + if (networkPlayerInfo != null) { + GlStateManager.enableBlend(); + GlStateManager.enableAlpha(); + mc.getTextureManager().bindTexture(networkPlayerInfo.getLocationSkin()); + GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0); + GlStateManager.color(1.0F, 1.0F, 1.0F, ColorUtils.getAlpha(args.get(3)) / 255f); + Gui.drawScaledCustomSizeModalRect((int) ((float) args.get(1) - 10f), (int) ((float) args.get(2) - 1f), 8.0F, 8.0F, 8, 8, 8, 8, 64.0F, 64.0F); + Gui.drawScaledCustomSizeModalRect((int) ((float) args.get(1) - 10f), (int) ((float) args.get(2) - 1f), 40.0F, 8.0F, 8, 8, 8, 8, 64.0F, 64.0F); + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + } + } } private boolean isInBounds(int left, int top, int right, int bottom, float chatScale) { |