diff options
Diffstat (limited to 'src/main/java/cc/woverflow/chattils')
8 files changed, 551 insertions, 0 deletions
diff --git a/src/main/java/cc/woverflow/chattils/hook/GuiNewChatHook.java b/src/main/java/cc/woverflow/chattils/hook/GuiNewChatHook.java new file mode 100644 index 0000000..f84fd43 --- /dev/null +++ b/src/main/java/cc/woverflow/chattils/hook/GuiNewChatHook.java @@ -0,0 +1,23 @@ +package cc.woverflow.chattils.hook; + +import net.minecraft.client.gui.ChatLine; + +import java.awt.datatransfer.Transferable; + +public interface GuiNewChatHook { + int getRight(); + + boolean shouldCopy(); + + Transferable getChattilsChatComponent(int mouseY); + + default ChatLine getFullMessage(ChatLine line) { + throw new AssertionError("getFullMessage not overridden on GuiNewChat"); + } + + String getPrevText(); + + void setPrevText(String prevText); + + int getTextOpacity(); +} diff --git a/src/main/java/cc/woverflow/chattils/mixin/ClientCommandHandlerMixin.java b/src/main/java/cc/woverflow/chattils/mixin/ClientCommandHandlerMixin.java new file mode 100644 index 0000000..0692342 --- /dev/null +++ b/src/main/java/cc/woverflow/chattils/mixin/ClientCommandHandlerMixin.java @@ -0,0 +1,34 @@ +package cc.woverflow.chattils.mixin; + +import cc.woverflow.chattils.chat.ChatShortcuts; +import cc.woverflow.chattils.config.ChattilsConfig; +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.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +import java.util.Iterator; +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 (ChattilsConfig.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/cc/woverflow/chattils/mixin/EntityPlayerSPMixin.java b/src/main/java/cc/woverflow/chattils/mixin/EntityPlayerSPMixin.java new file mode 100644 index 0000000..48dfc10 --- /dev/null +++ b/src/main/java/cc/woverflow/chattils/mixin/EntityPlayerSPMixin.java @@ -0,0 +1,21 @@ +package cc.woverflow.chattils.mixin; + +import cc.woverflow.chattils.chat.ChatTabs; +import cc.woverflow.chattils.config.ChattilsConfig; +import net.minecraft.client.entity.EntityPlayerSP; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyVariable; + +@Mixin(EntityPlayerSP.class) +public class EntityPlayerSPMixin { + @ModifyVariable(method = "sendChatMessage", at = @At("HEAD"), ordinal = 0, argsOnly = true) + private String handleSentMessages(String value) { + if (value.startsWith("/")) return value; + if (ChattilsConfig.INSTANCE.getChatTabs() && ChatTabs.INSTANCE.getCurrentTab() != null && !ChatTabs.INSTANCE.getCurrentTab().getPrefix().isEmpty()) { + return ChatTabs.INSTANCE.getCurrentTab().getPrefix() + value; + } else { + return value; + } + } +}
\ No newline at end of file diff --git a/src/main/java/cc/woverflow/chattils/mixin/GuiChatMixin.java b/src/main/java/cc/woverflow/chattils/mixin/GuiChatMixin.java new file mode 100644 index 0000000..9af0204 --- /dev/null +++ b/src/main/java/cc/woverflow/chattils/mixin/GuiChatMixin.java @@ -0,0 +1,117 @@ +package cc.woverflow.chattils.mixin; + +import cc.woverflow.chattils.chat.ChatSearchingManager; +import cc.woverflow.chattils.chat.ChatShortcuts; +import cc.woverflow.chattils.chat.ChatTab; +import cc.woverflow.chattils.chat.ChatTabs; +import cc.woverflow.chattils.config.ChattilsConfig; +import cc.woverflow.chattils.gui.components.ScreenshotButton; +import cc.woverflow.chattils.gui.components.SearchButton; +import cc.woverflow.chattils.hook.GuiNewChatHook; +import cc.woverflow.chattils.utils.ModCompatHooks; +import com.google.common.collect.Lists; +import net.minecraft.client.Minecraft; +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.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( + "\u00A73\u00A7l\u00A7nCopy To Clipboard", + "\u00A7lNORMAL CLICK\u00A7r - Full Message", + "\u00A7lCTRL CLICK\u00A7r - Single Line", + "\u00A7lSHIFT CLICK\u00A7r - Screenshot Line", + "", + "\u00A73\u00A7l\u00A7nModifiers", + "\u00A7lALT\u00A7r - Formatting Codes"); + + private SearchButton searchButton; + + @Inject(method = "initGui", at = @At("TAIL")) + private void init(CallbackInfo ci) { + if (ChattilsConfig.INSTANCE.getChatSearch()) { + searchButton = new SearchButton(); + buttonList.add(searchButton); + } + buttonList.add(new ScreenshotButton()); + if (ChattilsConfig.INSTANCE.getChatTabs()) { + for (ChatTab chatTab : ChatTabs.INSTANCE.getTabs()) { + buttonList.add(chatTab.getButton()); + } + } + } + + @Inject(method = "updateScreen", at = @At("HEAD")) + private void updateScreen(CallbackInfo ci) { + if (ChattilsConfig.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 (ChattilsConfig.INSTANCE.getChatSearch() && searchButton.isEnabled()) { + ci.cancel(); + if (keyCode == 1) { + searchButton.onMousePress(); + return; + } + searchButton.getInputField().textboxKeyTyped(typedChar, keyCode); + ChatSearchingManager.setPrevText(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.shouldCopy() && (hook.getRight() + ModCompatHooks.getXOffset()) <= x && (hook.getRight() + ModCompatHooks.getXOffset()) + 9 > x) { + GuiUtils.drawHoveringText(COPY_TOOLTIP, mouseX, mouseY, width, height, -1, fontRendererObj); + GlStateManager.disableLighting(); + } + } + + @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.shouldCopy() && (hook.getRight() + ModCompatHooks.getXOffset()) <= x && (hook.getRight() + ModCompatHooks.getXOffset()) + 9 > x) { + Transferable message = hook.getChattilsChatComponent(Mouse.getY()); + if (message == null) return; + try { + Toolkit.getDefaultToolkit().getSystemClipboard().setContents(message, null); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + @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 (ChattilsConfig.INSTANCE.getChatShortcuts()) { + if (original.startsWith("/")) { + return "/" + ChatShortcuts.INSTANCE.handleSentCommand(StringUtils.substringAfter(original, "/")); + } + } + return original; + } +} diff --git a/src/main/java/cc/woverflow/chattils/mixin/GuiNewChatAccessor.java b/src/main/java/cc/woverflow/chattils/mixin/GuiNewChatAccessor.java new file mode 100644 index 0000000..1bce77a --- /dev/null +++ b/src/main/java/cc/woverflow/chattils/mixin/GuiNewChatAccessor.java @@ -0,0 +1,17 @@ +package cc.woverflow.chattils.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 + int getScrollPos(); +} diff --git a/src/main/java/cc/woverflow/chattils/mixin/GuiNewChatMapMixin.java b/src/main/java/cc/woverflow/chattils/mixin/GuiNewChatMapMixin.java new file mode 100644 index 0000000..97d39c5 --- /dev/null +++ b/src/main/java/cc/woverflow/chattils/mixin/GuiNewChatMapMixin.java @@ -0,0 +1,78 @@ +package cc.woverflow.chattils.mixin; + +import cc.woverflow.chattils.hook.GuiNewChatHook; +import net.minecraft.client.gui.ChatLine; +import net.minecraft.client.gui.GuiNewChat; +import net.minecraft.util.IChatComponent; +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/cc/woverflow/chattils/mixin/GuiNewChatMixin.java b/src/main/java/cc/woverflow/chattils/mixin/GuiNewChatMixin.java new file mode 100644 index 0000000..eea68c8 --- /dev/null +++ b/src/main/java/cc/woverflow/chattils/mixin/GuiNewChatMixin.java @@ -0,0 +1,240 @@ +package cc.woverflow.chattils.mixin; + +import cc.woverflow.chattils.Chattils; +import cc.woverflow.chattils.chat.ChatSearchingManager; +import cc.woverflow.chattils.chat.ChatTabs; +import cc.woverflow.chattils.config.ChattilsConfig; +import cc.woverflow.chattils.hook.GuiNewChatHook; +import cc.woverflow.chattils.utils.ModCompatHooks; +import cc.woverflow.chattils.utils.RenderHelper; +import gg.essential.universal.UMouse; +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.IChatComponent; +import net.minecraft.util.MathHelper; +import net.minecraft.util.ResourceLocation; +import org.objectweb.asm.Opcodes; +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.callback.CallbackInfoReturnable; +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; +import java.util.Locale; + +@Mixin(value = GuiNewChat.class, priority = Integer.MIN_VALUE) +public abstract class GuiNewChatMixin extends Gui implements GuiNewChatHook { + @Unique private int chattils$right = 0; + @Unique private boolean chattils$shouldCopy; + @Unique private boolean chattils$chatCheck; + @Unique private int chattils$textOpacity; + @Shadow @Final private Minecraft mc; + @Shadow @Final private List<ChatLine> drawnChatLines; + @SuppressWarnings({"FieldCanBeLocal", "unused"}) + private float percentComplete; + private String chattils$previousText = ""; + + @Shadow public abstract boolean getChatOpen(); + + @Shadow public abstract float getChatScale(); + + @Shadow public abstract int getLineCount(); + + @Shadow private int scrollPos; + @Shadow @Final private List<ChatLine> chatLines; + + @Shadow public abstract void deleteChatLine(int id); + + @Unique private static final ResourceLocation COPY = new ResourceLocation("chattils:copy.png"); + + @Inject(method = "printChatMessageWithOptionalDeletion", at = @At("HEAD"), cancellable = true) + private void handlePrintChatMessage(IChatComponent chatComponent, int chatLineId, CallbackInfo ci) { + handleChatTabMessage(chatComponent, chatLineId, mc.ingameGUI.getUpdateCounter(), false, ci); + if (!EnumChatFormatting.getTextWithoutFormattingCodes(chatComponent.getUnformattedText()).toLowerCase(Locale.ENGLISH).contains(chattils$previousText.toLowerCase(Locale.ENGLISH))) { + percentComplete = 1.0F; + } + } + + @Inject(method = "setChatLine", at = @At("HEAD"), cancellable = true) + private void handleSetChatLine(IChatComponent chatComponent, int chatLineId, int updateCounter, boolean displayOnly, CallbackInfo ci) { + ChatSearchingManager.getCache().invalidateAll(); + handleChatTabMessage(chatComponent, chatLineId, updateCounter, displayOnly, ci); + } + + @Inject(method = "drawChat", at = @At("HEAD")) + private void checkScreenshotKeybind(int j2, CallbackInfo ci) { + if (Chattils.INSTANCE.getKeybind().isPressed()) { + Chattils.INSTANCE.setDoTheThing(true); + } + chattils$chatCheck = false; + } + + @ModifyVariable(method = "drawChat", at = @At("HEAD"), argsOnly = true) + private int setUpdateCounterWhjenYes(int updateCounter) { + return Chattils.INSTANCE.getDoTheThing() ? 0 : updateCounter; + } + + @ModifyVariable(method = "drawChat", at = @At("STORE"), index = 2) + private int setChatLimitWhenYes(int linesToDraw) { + return Chattils.INSTANCE.getDoTheThing() + ? GuiNewChat.calculateChatboxHeight(mc.gameSettings.chatHeightFocused) / 9 + : linesToDraw; + } + + @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) { + int left = args.get(0); + int top = args.get(1); + int right = args.get(2); + int bottom = args.get(3); + if (mc.currentScreen instanceof GuiChat) { + float f = this.getChatScale(); + 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 / f); + mouseY = -(MathHelper.floor_float((float)mouseY / f)); //WHY DO I NEED TO DO THIS + if (mouseX >= (left + ModCompatHooks.getXOffset()) && mouseY < bottom && mouseX < (right + 9 + ModCompatHooks.getXOffset()) && mouseY >= top) { + chattils$shouldCopy = true; + drawCopyChatBox(right, top); + } + } + } + + @Redirect(method = "drawChat", at = @At(value = "FIELD", target = "Lnet/minecraft/client/gui/GuiNewChat;drawnChatLines:Ljava/util/List;", opcode = Opcodes.GETFIELD)) + private List<ChatLine> injected(GuiNewChat instance) { + return ChatSearchingManager.filterMessages(chattils$previousText, drawnChatLines); + } + + @ModifyVariable(method = "drawChat", at = @At("STORE"), ordinal = 7) + private int modifyYeah(int value) { + return chattils$textOpacity = (int) (((float) (getChatOpen() ? 255 : value)) * (mc.gameSettings.chatOpacity * 0.9F + 0.1F)); + } + + @Redirect(method = "drawChat", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/FontRenderer;drawStringWithShadow(Ljava/lang/String;FFI)I")) + private int redirectDrawString(FontRenderer instance, String text, float x, float y, int color) { + return ModCompatHooks.redirectDrawString(text, x, y, color); + } + + @Inject(method = "drawChat", at = @At("RETURN")) + private void checkStuff(int j2, CallbackInfo ci) { + if (!chattils$chatCheck && chattils$shouldCopy) { + chattils$shouldCopy = false; + } + } + + @Inject(method = "getChatHeight", at = @At("HEAD"), cancellable = true) + private void customHeight_getChatHeight(CallbackInfoReturnable<Integer> cir) { + if (ChattilsConfig.INSTANCE.getCustomChatHeight()) cir.setReturnValue(Chattils.INSTANCE.getChatHeight(this.getChatOpen())); + } + + @Override + public int getRight() { + return chattils$right; + } + + @Override + public boolean shouldCopy() { + return chattils$shouldCopy; + } + + private void handleChatTabMessage(IChatComponent chatComponent, int chatLineId, int updateCounter, boolean displayOnly, CallbackInfo ci) { + if (ChattilsConfig.INSTANCE.getChatTabs()) { + if (!ChatTabs.INSTANCE.shouldRender(chatComponent)) { + percentComplete = 1.0F; + if (chatLineId != 0) { + deleteChatLine(chatLineId); + } + if (!displayOnly) { + chatLines.add(0, new ChatLine(updateCounter, chatComponent, chatLineId)); + while (this.chatLines.size() > (100 + ModCompatHooks.getExtendedChatLength())) + { + this.chatLines.remove(this.chatLines.size() - 1); + } + } + ci.cancel(); + } + } + } + + private void drawCopyChatBox(int right, int top) { + chattils$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); + chattils$right = right; + Gui.drawModalRectWithCustomSizedTexture(right, top, 0f, 0f, 9, 9, 9, 9); + GlStateManager.disableAlpha(); + GlStateManager.disableRescaleNormal(); + GlStateManager.disableLighting(); + GlStateManager.popMatrix(); + } + + @Override + public Transferable getChattilsChatComponent(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()) { + ChatLine subLine = this.drawnChatLines.get(i1); + ChatLine fullLine = this.getFullMessage(subLine); + if (GuiScreen.isShiftKeyDown()) { + if (fullLine != null) { + BufferedImage image = Chattils.INSTANCE.screenshotLine(fullLine); + if (image != null) RenderHelper.INSTANCE.copyBufferedImageToClipboard(image); + } + return null; + } + ChatLine line = GuiScreen.isCtrlKeyDown() ? subLine : fullLine; + String message = line == null ? "Could not find chat message." : line.getChatComponent().getFormattedText(); + return new StringSelection(GuiScreen.isAltKeyDown() ? message : EnumChatFormatting.getTextWithoutFormattingCodes(message)); + } + + } + } + } + return null; + } + + @Override + public String getPrevText() { + return chattils$previousText; + } + + @Override + public void setPrevText(String prevText) { + chattils$previousText = prevText; + } + + @Override + public int getTextOpacity() { + return chattils$textOpacity; + } +} diff --git a/src/main/java/cc/woverflow/chattils/mixin/WyvtilsListenerMixin.java b/src/main/java/cc/woverflow/chattils/mixin/WyvtilsListenerMixin.java new file mode 100644 index 0000000..13a4167 --- /dev/null +++ b/src/main/java/cc/woverflow/chattils/mixin/WyvtilsListenerMixin.java @@ -0,0 +1,21 @@ +package cc.woverflow.chattils.mixin; + +import cc.woverflow.chattils.utils.RenderHelper; +import org.spongepowered.asm.mixin.Dynamic; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Pseudo; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Coerce; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Pseudo +@Mixin(targets = "net.wyvest.wyvtils.core.listener.Listener") +public class WyvtilsListenerMixin { + + @Dynamic("Wyvtils") + @Inject(method = "onStringRendered", at = @At("HEAD"), cancellable = true, remap = false) + private void cancelStringRender(@Coerce Object a, CallbackInfo ci) { + if (RenderHelper.INSTANCE.getBypassWyvtils()) ci.cancel(); + } +} |