aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/org/polyfrost
diff options
context:
space:
mode:
authorWyvest <wyvestbusiness@gmail.com>2023-11-22 08:18:19 +0900
committerWyvest <wyvestbusiness@gmail.com>2023-11-22 08:18:19 +0900
commit8b373f577d9c6dde26357ef3fc86691f1efef9b4 (patch)
treea5328e995d8f4df21a9fe94ac8e384be08833c70 /src/main/java/org/polyfrost
parent64230799777473246b5f98efbc596206c5bbf42d (diff)
downloadChatting-8b373f577d9c6dde26357ef3fc86691f1efef9b4.tar.gz
Chatting-8b373f577d9c6dde26357ef3fc86691f1efef9b4.tar.bz2
Chatting-8b373f577d9c6dde26357ef3fc86691f1efef9b4.zip
update PGT and relocate to org.polyfrost
Diffstat (limited to 'src/main/java/org/polyfrost')
-rw-r--r--src/main/java/org/polyfrost/chatting/hook/ChatLineHook.java17
-rw-r--r--src/main/java/org/polyfrost/chatting/hook/GuiNewChatHook.java21
-rw-r--r--src/main/java/org/polyfrost/chatting/mixin/ChatLineMixin.java114
-rw-r--r--src/main/java/org/polyfrost/chatting/mixin/ClientCommandHandlerMixin.java33
-rw-r--r--src/main/java/org/polyfrost/chatting/mixin/EntityPlayerSPMixin.java41
-rw-r--r--src/main/java/org/polyfrost/chatting/mixin/GuiChatMixin.java143
-rw-r--r--src/main/java/org/polyfrost/chatting/mixin/GuiNewChatAccessor.java20
-rw-r--r--src/main/java/org/polyfrost/chatting/mixin/GuiNewChatMapMixin.java78
-rw-r--r--src/main/java/org/polyfrost/chatting/mixin/GuiNewChatMixin.java257
-rw-r--r--src/main/java/org/polyfrost/chatting/mixin/GuiNewChatMixin_ChatHeight.java21
-rw-r--r--src/main/java/org/polyfrost/chatting/mixin/GuiNewChatMixin_ChatSearching.java31
-rw-r--r--src/main/java/org/polyfrost/chatting/mixin/GuiNewChatMixin_ChatTabs.java54
-rw-r--r--src/main/java/org/polyfrost/chatting/mixin/GuiNewChatMixin_Scrolling.java71
-rw-r--r--src/main/java/org/polyfrost/chatting/mixin/GuiNewChatMixin_SmoothMessages.java103
-rw-r--r--src/main/java/org/polyfrost/chatting/mixin/GuiNewChatMixin_TextRendering.java29
-rw-r--r--src/main/java/org/polyfrost/chatting/mixin/GuiUtilsMixin.java36
16 files changed, 1069 insertions, 0 deletions
diff --git a/src/main/java/org/polyfrost/chatting/hook/ChatLineHook.java b/src/main/java/org/polyfrost/chatting/hook/ChatLineHook.java
new file mode 100644
index 0000000..50b9ce3
--- /dev/null
+++ b/src/main/java/org/polyfrost/chatting/hook/ChatLineHook.java
@@ -0,0 +1,17 @@
+package org.polyfrost.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();
+
+ long getUniqueId();
+}
diff --git a/src/main/java/org/polyfrost/chatting/hook/GuiNewChatHook.java b/src/main/java/org/polyfrost/chatting/hook/GuiNewChatHook.java
new file mode 100644
index 0000000..84097bd
--- /dev/null
+++ b/src/main/java/org/polyfrost/chatting/hook/GuiNewChatHook.java
@@ -0,0 +1,21 @@
+package org.polyfrost.chatting.hook;
+
+import net.minecraft.client.gui.ChatLine;
+
+import java.awt.datatransfer.Transferable;
+
+public interface GuiNewChatHook {
+ int getRight();
+
+ boolean isHovering();
+
+ ChatLine getHoveredLine(int mouseY);
+
+ Transferable getChattingChatComponent(int mouseY);
+
+ default ChatLine getFullMessage(ChatLine line) {
+ throw new AssertionError("getFullMessage not overridden on GuiNewChat");
+ }
+
+ int getTextOpacity();
+}
diff --git a/src/main/java/org/polyfrost/chatting/mixin/ChatLineMixin.java b/src/main/java/org/polyfrost/chatting/mixin/ChatLineMixin.java
new file mode 100644
index 0000000..2e5f21c
--- /dev/null
+++ b/src/main/java/org/polyfrost/chatting/mixin/ChatLineMixin.java
@@ -0,0 +1,114 @@
+/*
+ * 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 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.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;
+ private static long lastUniqueId = 0;
+ private long uniqueId = 0;
+
+ @Inject(method = "<init>", at = @At("RETURN"))
+ private void onInit(int i, IChatComponent iChatComponent, int j, CallbackInfo ci) {
+ 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) {
+ }
+ }
+
+ @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;
+ }
+ }
+
+ @Override
+ public long getUniqueId() {
+ return uniqueId;
+ }
+}
diff --git a/src/main/java/org/polyfrost/chatting/mixin/ClientCommandHandlerMixin.java b/src/main/java/org/polyfrost/chatting/mixin/ClientCommandHandlerMixin.java
new file mode 100644
index 0000000..ee63ed3
--- /dev/null
+++ b/src/main/java/org/polyfrost/chatting/mixin/ClientCommandHandlerMixin.java
@@ -0,0 +1,33 @@
+package org.polyfrost.chatting.mixin;
+
+import kotlin.Pair;
+import net.minecraft.client.Minecraft;
+import net.minecraft.command.CommandHandler;
+import net.minecraft.command.ICommandSender;
+import net.minecraft.util.BlockPos;
+import net.minecraftforge.client.ClientCommandHandler;
+import net.minecraftforge.fml.client.FMLClientHandler;
+import org.polyfrost.chatting.chat.ChatShortcuts;
+import org.polyfrost.chatting.config.ChattingConfig;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Redirect;
+
+import java.util.List;
+
+@Mixin(value = ClientCommandHandler.class, remap = false)
+public class ClientCommandHandlerMixin extends CommandHandler {
+ @Redirect(method = "autoComplete", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/client/ClientCommandHandler;getTabCompletionOptions(Lnet/minecraft/command/ICommandSender;Ljava/lang/String;Lnet/minecraft/util/BlockPos;)Ljava/util/List;"))
+ private List<String> addChatShortcuts(ClientCommandHandler instance, ICommandSender iCommandSender, String leftOfCursor, BlockPos blockPos) {
+ Minecraft mc = FMLClientHandler.instance().getClient();
+ List<String> autocompleteList = instance.getTabCompletionOptions(mc.thePlayer, leftOfCursor, mc.thePlayer.getPosition());
+ if (ChattingConfig.INSTANCE.getChatShortcuts()) {
+ for (Pair<String, String> pair : ChatShortcuts.INSTANCE.getShortcuts()) {
+ if (pair.getFirst().startsWith(leftOfCursor)) {
+ autocompleteList.add(pair.getFirst());
+ }
+ }
+ }
+ return autocompleteList;
+ }
+}
diff --git a/src/main/java/org/polyfrost/chatting/mixin/EntityPlayerSPMixin.java b/src/main/java/org/polyfrost/chatting/mixin/EntityPlayerSPMixin.java
new file mode 100644
index 0000000..d59d7f2
--- /dev/null
+++ b/src/main/java/org/polyfrost/chatting/mixin/EntityPlayerSPMixin.java
@@ -0,0 +1,41 @@
+package org.polyfrost.chatting.mixin;
+
+import net.minecraft.client.entity.EntityPlayerSP;
+import net.minecraft.client.network.NetHandlerPlayClient;
+import net.minecraft.network.Packet;
+import net.minecraft.network.play.client.C01PacketChatMessage;
+import org.polyfrost.chatting.chat.ChatTab;
+import org.polyfrost.chatting.chat.ChatTabs;
+import org.polyfrost.chatting.config.ChattingConfig;
+import org.spongepowered.asm.mixin.Final;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Shadow;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Redirect;
+
+@Mixin(value = EntityPlayerSP.class, priority = 0)
+public class EntityPlayerSPMixin {
+ @Shadow @Final public NetHandlerPlayClient sendQueue;
+
+ @Redirect(method = "sendChatMessage", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/NetHandlerPlayClient;addToSendQueue(Lnet/minecraft/network/Packet;)V"))
+ private void handleSentMessages(NetHandlerPlayClient instance, Packet<?> packet, String value) {
+ if (value.startsWith("/")) {
+ sendQueue.addToSendQueue(packet);
+ return;
+ }
+ if (ChattingConfig.INSTANCE.getChatTabs() && !ChatTabs.INSTANCE.getCurrentTabs().isEmpty()) {
+ boolean sent = false;
+ for (ChatTab tab : ChatTabs.INSTANCE.getCurrentTabs()) {
+ if (tab.getPrefix() != null && !tab.getPrefix().isEmpty()) {
+ sendQueue.addToSendQueue(new C01PacketChatMessage(tab.getPrefix() + value));
+ sent = true;
+ }
+ }
+ if (!sent) {
+ sendQueue.addToSendQueue(packet);
+ }
+ } else {
+ sendQueue.addToSendQueue(packet);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/main/java/org/polyfrost/chatting/mixin/GuiChatMixin.java b/src/main/java/org/polyfrost/chatting/mixin/GuiChatMixin.java
new file mode 100644
index 0000000..303326f
--- /dev/null
+++ b/src/main/java/org/polyfrost/chatting/mixin/GuiChatMixin.java
@@ -0,0 +1,143 @@
+package org.polyfrost.chatting.mixin;
+
+import org.polyfrost.chatting.chat.*;
+import org.polyfrost.chatting.config.ChattingConfig;
+import org.polyfrost.chatting.gui.components.ClearButton;
+import org.polyfrost.chatting.gui.components.ScreenshotButton;
+import org.polyfrost.chatting.gui.components.SearchButton;
+import org.polyfrost.chatting.hook.ChatLineHook;
+import org.polyfrost.chatting.hook.GuiNewChatHook;
+import com.google.common.collect.Lists;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.ChatLine;
+import net.minecraft.client.gui.GuiChat;
+import net.minecraft.client.gui.GuiScreen;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.util.MathHelper;
+import net.minecraftforge.fml.client.config.GuiUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.lwjgl.input.Mouse;
+import org.polyfrost.chatting.chat.ChatSearchingManager;
+import org.polyfrost.chatting.chat.ChatShortcuts;
+import org.polyfrost.chatting.utils.ModCompatHooks;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Unique;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.ModifyArg;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+import java.awt.*;
+import java.awt.datatransfer.Transferable;
+import java.util.List;
+
+@Mixin(GuiChat.class)
+public abstract class GuiChatMixin extends GuiScreen {
+
+ @Unique
+ private static final List<String> COPY_TOOLTIP = Lists.newArrayList(
+ "\u00A7e\u00A7lCopy To Clipboard",
+ "\u00A7b\u00A7lNORMAL CLICK\u00A7r \u00A78- \u00A77Full Message",
+ "\u00A7b\u00A7lCTRL CLICK\u00A7r \u00A78- \u00A77Single Line",
+ "\u00A7b\u00A7lSHIFT CLICK\u00A7r \u00A78- \u00A77Screenshot Line",
+ "",
+ "\u00A7e\u00A7lModifiers",
+ "\u00A7b\u00A7lALT\u00A7r \u00A78- \u00A77Formatting Codes");
+
+ private SearchButton searchButton;
+
+ @Inject(method = "initGui", at = @At("TAIL"))
+ private void init(CallbackInfo ci) {
+ if (ChattingConfig.INSTANCE.getChatSearch()) {
+ searchButton = new SearchButton();
+ buttonList.add(searchButton);
+ }
+ buttonList.add(new ScreenshotButton());
+ buttonList.add(new ClearButton());
+ if (ChattingConfig.INSTANCE.getChatTabs()) {
+ for (ChatTab chatTab : ChatTabs.INSTANCE.getTabs()) {
+ buttonList.add(chatTab.getButton());
+ }
+ }
+ }
+
+ @Inject(method = "updateScreen", at = @At("HEAD"))
+ private void updateScreen(CallbackInfo ci) {
+ if (ChattingConfig.INSTANCE.getChatSearch() && searchButton.isEnabled()) {
+ searchButton.getInputField().updateCursorCounter();
+ }
+ }
+
+ @Inject(method = "keyTyped", at = @At("HEAD"), cancellable = true)
+ private void keyTyped(char typedChar, int keyCode, CallbackInfo ci) {
+ if (ChattingConfig.INSTANCE.getChatSearch() && searchButton.isEnabled()) {
+ ci.cancel();
+ if (keyCode == 1) {
+ searchButton.onMousePress();
+ return;
+ }
+ searchButton.getInputField().textboxKeyTyped(typedChar, keyCode);
+ ChatSearchingManager.INSTANCE.setLastSearch(searchButton.getInputField().getText());
+ }
+ }
+
+ @Inject(method = "drawScreen", at = @At("HEAD"))
+ private void onDrawScreen(int mouseX, int mouseY, float partialTicks, CallbackInfo ci) {
+ GuiNewChatHook hook = ((GuiNewChatHook) Minecraft.getMinecraft().ingameGUI.getChatGUI());
+ float f = mc.ingameGUI.getChatGUI().getChatScale();
+ int x = MathHelper.floor_float((float) mouseX / f);
+ if (hook.isHovering() && (hook.getRight() + ModCompatHooks.getXOffset() + 3) <= x && (hook.getRight() + ModCompatHooks.getXOffset()) + 13 > x) {
+ GuiUtils.drawHoveringText(COPY_TOOLTIP, mouseX, mouseY, width, height, -1, fontRendererObj);
+ GlStateManager.disableLighting();
+ }
+ }
+
+ @ModifyArg(method = "drawScreen", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiChat;drawRect(IIIII)V"), index = 2)
+ private int modifyRight(int right) {
+ return ChattingConfig.INSTANCE.getCompactInputBox() ? (MathHelper.ceiling_float_int((float) mc.ingameGUI.getChatGUI().getChatWidth() / mc.ingameGUI.getChatGUI().getChatScale()) + 6) : right;
+ }
+
+ @ModifyArg(method = "drawScreen", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiChat;drawRect(IIIII)V"), index = 4)
+ private int modifyInputBoxColor(int color) {
+ return ChattingConfig.INSTANCE.getInputBoxBackgroundColor().getRGB();
+ }
+
+ @Inject(method = "mouseClicked", at = @At("HEAD"))
+ private void mouseClicked(int mouseX, int mouseY, int mouseButton, CallbackInfo ci) {
+ GuiNewChatHook hook = ((GuiNewChatHook) Minecraft.getMinecraft().ingameGUI.getChatGUI());
+ float f = mc.ingameGUI.getChatGUI().getChatScale();
+ int x = MathHelper.floor_float((float) mouseX / f);
+ if (hook.isHovering()) {
+ if (((hook.getRight() + ModCompatHooks.getXOffset() + 3) <= x && (hook.getRight() + ModCompatHooks.getXOffset()) + 13 > x) || (mouseButton == 1 && ChattingConfig.INSTANCE.getRightClickCopy())) {
+ Transferable message = hook.getChattingChatComponent(Mouse.getY());
+ if (message == null) return;
+ try {
+ Toolkit.getDefaultToolkit().getSystemClipboard().setContents(message, null);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ } else if ((hook.getRight() + ModCompatHooks.getXOffset() + 13) <= x && (hook.getRight() + ModCompatHooks.getXOffset()) + 23 > x) {
+ ChatLine chatLine = hook.getHoveredLine(Mouse.getY());
+ if (chatLine == null) return;
+ ((GuiNewChatAccessor) Minecraft.getMinecraft().ingameGUI.getChatGUI()).getDrawnChatLines().removeIf(line -> ((ChatLineHook) line).getUniqueId() == ((ChatLineHook) chatLine).getUniqueId());
+ ((GuiNewChatAccessor) Minecraft.getMinecraft().ingameGUI.getChatGUI()).getChatLines().removeIf(line -> ((ChatLineHook) line).getUniqueId() == ((ChatLineHook) chatLine).getUniqueId());
+ }
+ }
+
+ }
+
+ @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()) {
+ if (original.startsWith("/")) {
+ return "/" + ChatShortcuts.INSTANCE.handleSentCommand(StringUtils.substringAfter(original, "/"));
+ }
+ }
+ return original;
+ }
+
+ @Inject(method = "handleMouseInput", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiNewChat;scroll(I)V"))
+ private void handleMouseInput(CallbackInfo ci) {
+ ChatScrollingHook.INSTANCE.setShouldSmooth(true);
+ }
+}
diff --git a/src/main/java/org/polyfrost/chatting/mixin/GuiNewChatAccessor.java b/src/main/java/org/polyfrost/chatting/mixin/GuiNewChatAccessor.java
new file mode 100644
index 0000000..d0630ca
--- /dev/null
+++ b/src/main/java/org/polyfrost/chatting/mixin/GuiNewChatAccessor.java
@@ -0,0 +1,20 @@
+package org.polyfrost.chatting.mixin;
+
+import net.minecraft.client.gui.ChatLine;
+import net.minecraft.client.gui.GuiNewChat;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.gen.Accessor;
+
+import java.util.List;
+
+@Mixin(GuiNewChat.class)
+public interface GuiNewChatAccessor {
+ @Accessor
+ List<ChatLine> getDrawnChatLines();
+
+ @Accessor
+ List<ChatLine> getChatLines();
+
+ @Accessor
+ int getScrollPos();
+}
diff --git a/src/main/java/org/polyfrost/chatting/mixin/GuiNewChatMapMixin.java b/src/main/java/org/polyfrost/chatting/mixin/GuiNewChatMapMixin.java
new file mode 100644
index 0000000..ca1c0df
--- /dev/null
+++ b/src/main/java/org/polyfrost/chatting/mixin/GuiNewChatMapMixin.java
@@ -0,0 +1,78 @@
+package org.polyfrost.chatting.mixin;
+
+import net.minecraft.client.gui.ChatLine;
+import net.minecraft.client.gui.GuiNewChat;
+import net.minecraft.util.IChatComponent;
+import org.polyfrost.chatting.hook.GuiNewChatHook;
+import org.spongepowered.asm.mixin.Final;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Shadow;
+import org.spongepowered.asm.mixin.Unique;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Mixin(value = GuiNewChat.class, priority = Integer.MIN_VALUE)
+public abstract class GuiNewChatMapMixin implements GuiNewChatHook {
+
+ @Unique private final Map<ChatLine, ChatLine> drawnToFull = new HashMap<>();
+ @Unique private final List<ChatLine> tempDrawnLines = new ArrayList<>();
+ @Unique private ChatLine lastTempLine = null;
+
+ @Shadow @Final private List<ChatLine> drawnChatLines;
+ @Shadow @Final private List<ChatLine> chatLines;
+
+ @Inject(method = "setChatLine", at = @At("HEAD"))
+ private void handleSetChatLine(IChatComponent chatComponent, int chatLineId, int updateCounter, boolean displayOnly, CallbackInfo ci) {
+ tempDrawnLines.clear();
+ }
+
+ @Inject(method = "setChatLine", at = @At(value = "INVOKE", target = "Ljava/util/List;add(ILjava/lang/Object;)V", ordinal = 0, shift = At.Shift.AFTER, remap = false))
+ private void handleDrawnLineAdded(IChatComponent chatComponent, int chatLineId, int updateCounter, boolean displayOnly, CallbackInfo ci) {
+ if (!displayOnly) tempDrawnLines.add(drawnChatLines.get(0));
+ else if (lastTempLine != null) {
+ drawnToFull.put(drawnChatLines.get(0), lastTempLine);
+ }
+ }
+
+ @Inject(method = "setChatLine", at = @At(value = "INVOKE", target = "Ljava/util/List;remove(I)Ljava/lang/Object;", ordinal = 0, shift = At.Shift.BEFORE, remap = false))
+ private void handleDrawnLineRemoved(IChatComponent chatComponent, int chatLineId, int updateCounter, boolean displayOnly, CallbackInfo ci) {
+ drawnToFull.remove(drawnChatLines.get(drawnChatLines.size() - 1));
+ }
+
+ @Inject(method = "setChatLine", at = @At("RETURN"))
+ private void handleLineAdded(IChatComponent chatComponent, int chatLineId, int updateCounter, boolean displayOnly, CallbackInfo ci) {
+ if (!displayOnly) {
+ ChatLine masterLine = chatLines.get(0);
+ for (ChatLine tempDrawnLine : tempDrawnLines) drawnToFull.put(tempDrawnLine, masterLine);
+ }else {
+ lastTempLine = null;
+ }
+ }
+
+ @Inject(method = "refreshChat", at = @At("HEAD"))
+ private void handleRefreshedChat(CallbackInfo ci) {
+ drawnToFull.clear();
+ }
+
+ @Inject(method = "refreshChat", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiNewChat;setChatLine(Lnet/minecraft/util/IChatComponent;IIZ)V", ordinal = 0, shift = At.Shift.BEFORE))
+ private void handleLineRefresh(CallbackInfo ci, int i, ChatLine chatline) {
+ lastTempLine = chatline;
+ }
+
+ @Inject(method = "clearChatMessages", at = @At("HEAD"))
+ private void handleChatCleared(CallbackInfo ci) {
+ drawnToFull.clear();
+ }
+
+ @Override
+ public ChatLine getFullMessage(ChatLine line) {
+ return drawnToFull.getOrDefault(line, null);
+ }
+}
diff --git a/src/main/java/org/polyfrost/chatting/mixin/GuiNewChatMixin.java b/src/main/java/org/polyfrost/chatting/mixin/GuiNewChatMixin.java
new file mode 100644
index 0000000..bc90730
--- /dev/null
+++ b/src/main/java/org/polyfrost/chatting/mixin/GuiNewChatMixin.java
@@ -0,0 +1,257 @@
+package org.polyfrost.chatting.mixin;
+
+import cc.polyfrost.oneconfig.libs.universal.UMouse;
+import cc.polyfrost.oneconfig.utils.Notifications;
+import org.polyfrost.chatting.Chatting;
+import org.polyfrost.chatting.chat.ChatSearchingManager;
+import org.polyfrost.chatting.config.ChattingConfig;
+import org.polyfrost.chatting.hook.GuiNewChatHook;
+import org.polyfrost.chatting.utils.ModCompatHooks;
+import org.polyfrost.chatting.utils.RenderUtils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.*;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.MathHelper;
+import net.minecraft.util.ResourceLocation;
+import org.spongepowered.asm.mixin.Final;
+import org.spongepowered.asm.mixin.Mixin;
+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.invoke.arg.Args;
+
+import java.awt.datatransfer.StringSelection;
+import java.awt.datatransfer.Transferable;
+import java.awt.image.BufferedImage;
+import java.util.List;
+
+@Mixin(value = GuiNewChat.class, priority = 990)
+public abstract class GuiNewChatMixin extends Gui implements GuiNewChatHook {
+ @Unique
+ private int chatting$right = 0;
+ @Unique
+ private boolean chatting$isHovering;
+ @Unique
+ private boolean chatting$chatCheck;
+ @Unique
+ private int chatting$textOpacity;
+ @Shadow
+ @Final
+ private Minecraft mc;
+ @Shadow
+ @Final
+ private List<ChatLine> drawnChatLines;
+ @Shadow
+ public abstract boolean getChatOpen();
+
+ @Shadow
+ public abstract float getChatScale();
+
+ @Shadow
+ public abstract int getLineCount();
+
+ @Shadow
+ private int scrollPos;
+
+ @Shadow public abstract int getChatWidth();
+
+ @Unique
+ private static final ResourceLocation COPY = new ResourceLocation("chatting:copy.png");
+ @Unique
+ private static final ResourceLocation DELETE = new ResourceLocation("chatting:delete.png");
+
+ /*?
+ @Unique
+ private final SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
+ @ModifyArg(method = "setChatLine", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/ChatLine;<init>(ILnet/minecraft/util/IChatComponent;I)V"))
+ private IChatComponent handleAddDrawnLine(IChatComponent iChatComponent) {
+ if (!ChattingConfig.INSTANCE.getShowTimestamp()) return iChatComponent;
+ String time = " §7["+ sdf.format(new Date(System.currentTimeMillis())) + "]§r";
+ iChatComponent.appendSibling(new ChatComponentText(time));
+ return iChatComponent;
+ }
+
+ */
+
+ @Inject(method = "drawChat", at = @At("HEAD"))
+ private void checkScreenshotKeybind(int j2, CallbackInfo ci) {
+ if (Chatting.INSTANCE.getKeybind().isPressed()) {
+ Chatting.INSTANCE.setDoTheThing(true);
+ }
+ chatting$chatCheck = false;
+ }
+
+ @ModifyVariable(method = "drawChat", at = @At("HEAD"), argsOnly = true)
+ private int setUpdateCounterWhenYes(int updateCounter) {
+ return Chatting.INSTANCE.getDoTheThing() ? 0 : updateCounter;
+ }
+
+ @ModifyVariable(method = "drawChat", at = @At("STORE"), index = 2)
+ private int setChatLimitWhenYes(int linesToDraw) {
+ return Chatting.INSTANCE.getDoTheThing()
+ ? GuiNewChat.calculateChatboxHeight(mc.gameSettings.chatHeightFocused) / 9
+ : linesToDraw;
+ }
+
+ private boolean lineInBounds = false;
+
+ @ModifyArgs(method = "drawChat", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiNewChat;drawRect(IIIII)V"), slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/util/MathHelper;clamp_double(DDD)D"), to = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/GlStateManager;enableBlend()V")))
+ private void captureDrawRect(Args args) {
+ args.set(4, ChattingConfig.INSTANCE.getChatBackgroundColor().getRGB());
+ if (mc.currentScreen instanceof GuiChat) {
+ int left = args.get(0);
+ int top = args.get(1);
+ int right = args.get(2);
+ int bottom = args.get(3);
+ if (isInBounds(left, top, right, bottom, getChatScale())) {
+ chatting$isHovering = true;
+ lineInBounds = true;
+ args.set(4, ChattingConfig.INSTANCE.getHoveredChatBackgroundColor().getRGB());
+ }
+ }
+ }
+
+ @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) {
+ float f = this.getChatScale();
+ int left = 0;
+ int top = (int) ((float) args.get(2) - 1);
+ int right = MathHelper.ceiling_float_int((float)getChatWidth() / f) + 4;
+ int bottom = (int) ((float) args.get(2) + 8);
+ if ((chatting$isHovering && lineInBounds) || isInBounds(left, top, right, bottom, f)) {
+ chatting$isHovering = true;
+ drawCopyChatBox(right, top);
+ }
+ }
+ lineInBounds = false;
+ }
+
+ private boolean isInBounds(int left, int top, int right, int bottom, float chatScale) {
+ int mouseX = MathHelper.floor_double(UMouse.getScaledX()) - 3;
+ int mouseY = MathHelper.floor_double(UMouse.getScaledY()) - 27 + ModCompatHooks.getYOffset() - ModCompatHooks.getChatPosition();
+ mouseX = MathHelper.floor_float((float) mouseX / chatScale);
+ mouseY = -(MathHelper.floor_float((float) mouseY / chatScale)); //WHY DO I NEED TO DO THIS
+ return mouseX >= (left + ModCompatHooks.getXOffset()) && mouseY < bottom && mouseX < (right + 23 + ModCompatHooks.getXOffset()) && mouseY >= top;
+ }
+
+ @ModifyVariable(method = "drawChat", at = @At("STORE"), ordinal = 7)
+ private int modifyYeah(int value) {
+ return chatting$textOpacity = (int) (((float) (getChatOpen() ? 255 : value)) * (mc.gameSettings.chatOpacity * 0.9F + 0.1F));
+ }
+ /*/
+ @Inject(method = "drawChat", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/GlStateManager;scale(FFF)V"))
+ private void drawPre(int updateCounter, CallbackInfo ci) {
+ RenderUtils.timestampPre();
+ }
+
+ @Inject(method = "drawChat", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/GlStateManager;popMatrix()V"))
+ private void drawPost(int updateCounter, CallbackInfo ci) {
+ RenderUtils.timestampPost();
+ }
+
+ */
+
+ @Inject(method = "drawChat", at = @At("RETURN"))
+ private void checkStuff(int j2, CallbackInfo ci) {
+ if (!chatting$chatCheck && chatting$isHovering) {
+ chatting$isHovering = false;
+ }
+ }
+
+ @Override
+ public int getRight() {
+ return chatting$right;
+ }
+
+ @Override
+ public boolean isHovering() {
+ return chatting$isHovering;
+ }
+
+ private void drawCopyChatBox(int right, int top) {
+ chatting$chatCheck = true;
+ GlStateManager.enableRescaleNormal();
+ GlStateManager.enableBlend();
+ GlStateManager.enableDepth();
+ GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0);
+ GlStateManager.pushMatrix();
+ mc.getTextureManager().bindTexture(COPY);
+ GlStateManager.enableRescaleNormal();
+ GlStateManager.enableAlpha();
+ GlStateManager.alphaFunc(516, 0.1f);
+ GlStateManager.enableBlend();
+ GlStateManager.blendFunc(770, 771);
+ GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f);
+ chatting$right = right;
+ drawModalRectWithCustomSizedTexture(right + 1, top, 0f, 0f, 9, 9, 9, 9);
+ drawRect(right + 1, top, right + 10, top + 9, (((right + ModCompatHooks.getXOffset() + 3) <= (UMouse.getScaledX() / mc.ingameGUI.getChatGUI().getChatScale()) && (right + ModCompatHooks.getXOffset()) + 13 > (UMouse.getScaledX() / mc.ingameGUI.getChatGUI().getChatScale())) ? ChattingConfig.INSTANCE.getChatButtonHoveredBackgroundColor().getRGB() : ChattingConfig.INSTANCE.getChatButtonBackgroundColor().getRGB()));
+ GlStateManager.disableAlpha();
+ GlStateManager.disableRescaleNormal();
+ mc.getTextureManager().bindTexture(DELETE);
+ GlStateManager.enableRescaleNormal();
+ GlStateManager.enableAlpha();
+ GlStateManager.alphaFunc(516, 0.1f);
+ GlStateManager.enableBlend();
+ GlStateManager.blendFunc(770, 771);
+ GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f);
+ drawModalRectWithCustomSizedTexture(right + 11, top, 0f, 0f, 9, 9, 9, 9);
+ drawRect(right + 11, top, right + 20, top + 9, (((right + ModCompatHooks.getXOffset() + 13) <= (UMouse.getScaledX() / mc.ingameGUI.getChatGUI().getChatScale()) && (right + ModCompatHooks.getXOffset()) + 23 > (UMouse.getScaledX() / mc.ingameGUI.getChatGUI().getChatScale())) ? ChattingConfig.INSTANCE.getChatButtonHoveredBackgroundColor().getRGB() : ChattingConfig.INSTANCE.getChatButtonBackgroundColor().getRGB()));
+ GlStateManager.disableLighting();
+ GlStateManager.popMatrix();
+ }
+
+ @Override
+ public ChatLine getHoveredLine(int mouseY) {
+ if (this.getChatOpen()) {
+ ScaledResolution scaledresolution = new ScaledResolution(this.mc);
+ int i = scaledresolution.getScaleFactor();
+ float f = this.getChatScale();
+ int k = mouseY / i - 27 + ModCompatHooks.getYOffset() - ModCompatHooks.getChatPosition();
+ k = MathHelper.floor_float((float) k / f);
+
+ if (k >= 0) {
+ int l = Math.min(this.getLineCount(), this.drawnChatLines.size());
+
+ if (k < this.mc.fontRendererObj.FONT_HEIGHT * l + l) {
+ int i1 = k / this.mc.fontRendererObj.FONT_HEIGHT + this.scrollPos;
+
+ if (i1 >= 0 && i1 < this.drawnChatLines.size()) {
+ List<ChatLine> m = ChatSearchingManager.filterMessages(ChatSearchingManager.INSTANCE.getLastSearch(), this.drawnChatLines