diff --git a/src/main/java/net/silentclient/client/mixin/mixins/GuiChatMixin.java b/src/main/java/net/silentclient/client/mixin/mixins/GuiChatMixin.java index 8377dd0..15746ca 100644 --- a/src/main/java/net/silentclient/client/mixin/mixins/GuiChatMixin.java +++ b/src/main/java/net/silentclient/client/mixin/mixins/GuiChatMixin.java @@ -2,10 +2,18 @@ package net.silentclient.client.mixin.mixins; import net.minecraft.client.gui.GuiChat; import net.minecraft.client.gui.GuiTextField; +import net.silentclient.client.Client; +import net.silentclient.client.gui.animation.SimpleAnimation; +import net.silentclient.client.gui.clickgui.utils.GlUtils; import net.silentclient.client.mixin.accessors.GuiChatAccessor; import net.silentclient.client.mixin.wrappers.GuiTextFieldWrapper; +import net.silentclient.client.mods.render.ChatMod; 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; @Mixin(GuiChat.class) public class GuiChatMixin implements GuiChatAccessor { @@ -25,4 +33,23 @@ public class GuiChatMixin implements GuiChatAccessor { } this.inputField = a.getGuiTextField(); } + + @Unique + private SimpleAnimation animation = new SimpleAnimation(0.0F); + + @Inject(method = "drawScreen", at = @At("HEAD")) + public void drawScreenPre(int mouseX, int mouseY, float partialTicks, CallbackInfo ci) { + + if(Client.getInstance().getModInstances().getModByClass(ChatMod.class).isToggled() && Client.getInstance().getSettingsManager().getSettingByClass(ChatMod.class, "Bar Animation").getValBoolean()) { + animation.setAnimation(30, 20); + GlUtils.startTranslate(0, 29 - (int) animation.getValue()); + } + } + + @Inject(method = "drawScreen", at = @At("TAIL")) + public void drawScreenPost(int mouseX, int mouseY, float partialTicks, CallbackInfo ci) { + if(Client.getInstance().getModInstances().getModByClass(ChatMod.class).isToggled() && Client.getInstance().getSettingsManager().getSettingByClass(ChatMod.class, "Bar Animation").getValBoolean()) { + GlUtils.stopTranslate(); + } + } } diff --git a/src/main/java/net/silentclient/client/mixin/mixins/GuiNewChatMixin.java b/src/main/java/net/silentclient/client/mixin/mixins/GuiNewChatMixin.java new file mode 100644 index 0000000..81d81da --- /dev/null +++ b/src/main/java/net/silentclient/client/mixin/mixins/GuiNewChatMixin.java @@ -0,0 +1,115 @@ +package net.silentclient.client.mixin.mixins; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.*; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.util.IChatComponent; +import net.silentclient.client.Client; +import net.silentclient.client.mods.render.ChatMod; +import net.silentclient.client.utils.MathUtils; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +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 java.util.List; + +@Mixin(GuiNewChat.class) +public abstract class GuiNewChatMixin extends Gui { + @Shadow public abstract float getChatScale(); + + @Shadow public abstract int getLineCount(); + + @Shadow @Final private Minecraft mc; + @Shadow private boolean isScrolled; + private float percentComplete; + private int newLines; + private long prevMillis = System.currentTimeMillis(); + private float animationPercent; + private int lineBeingDrawn; + + private void updatePercentage(long diff) { + if (percentComplete < 1) { + percentComplete += (Client.getInstance().getSettingsManager().getSettingByClass(ChatMod.class, "Smooth Speed").getValDouble() / 1000) * (float) diff; + } + percentComplete = MathUtils.clamp(percentComplete, 0, 1); + } + + @Inject(method = "drawChat", at = @At("HEAD"), cancellable = true) + private void modifyChatRendering(CallbackInfo ci) { + long current = System.currentTimeMillis(); + long diff = current - prevMillis; + prevMillis = current; + updatePercentage(diff); + float t = percentComplete; + animationPercent = MathUtils.clamp(1 - (--t) * t * t * t, 0, 1); + } + + @Inject(method = "drawChat", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/GlStateManager;pushMatrix()V", ordinal = 0, shift = At.Shift.AFTER)) + private void translate(CallbackInfo ci) { + float y = 0; + if (Client.getInstance().getModInstances().getModByClass(ChatMod.class).isEnabled() && Client.getInstance().getSettingsManager().getSettingByClass(ChatMod.class, "Smooth").getValBoolean() && !this.isScrolled) { + y += (9 - 9 * animationPercent) * this.getChatScale(); + } + GlStateManager.translate(0, y, 0); + } + + @Redirect(method = "drawChat", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiNewChat;drawRect(IIIII)V", ordinal = 0)) + private void transparentBackground(int left, int top, int right, int bottom, int color) { + + boolean transparent = !Client.getInstance().getModInstances().getModByClass(ChatMod.class).isEnabled() || (Client.getInstance().getModInstances().getModByClass(ChatMod.class).isEnabled() && + !Client.getInstance().getSettingsManager().getSettingByClass(ChatMod.class, "Disable Background").getValBoolean()); + + if (transparent) { + drawRect(left, top, right, bottom, color); + } + } + + @ModifyArg(method = "drawChat", at = @At(value = "INVOKE", target = "Ljava/util/List;get(I)Ljava/lang/Object;", ordinal = 0, remap = false), index = 0) + private int getLineBeingDrawn(int line) { + lineBeingDrawn = line; + return line; + } + + @ModifyArg(method = "drawChat", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/FontRenderer;drawStringWithShadow(Ljava/lang/String;FFI)I"), index = 3) + private int modifyTextOpacity(int original) { + if (Client.getInstance().getModInstances().getModByClass(ChatMod.class).isEnabled() && Client.getInstance().getSettingsManager().getSettingByClass(ChatMod.class, "Smooth").getValBoolean() && lineBeingDrawn <= newLines) { + int opacity = (original >> 24) & 0xFF; + opacity *= animationPercent; + return (original & ~(0xFF << 24)) | (opacity << 24); + } else { + return original; + } + } + + @Inject(method = "printChatMessageWithOptionalDeletion", at = @At("HEAD")) + private void printChatMessageWithOptionalDeletion(CallbackInfo ci) { + percentComplete = 0; + } + + @ModifyVariable(method = "setChatLine", at = @At("STORE"), ordinal = 0) + private List setNewLines(List original) { + newLines = original.size() - 1; + return original; + } + + @Inject(method = "getChatComponent", at = @At(value = "FIELD", target = "Lnet/minecraft/client/gui/GuiNewChat;scrollPos:I"), cancellable = true, locals = LocalCapture.CAPTURE_FAILSOFT) + private void getChatComponent(int mouseX, int mouseY, CallbackInfoReturnable cir, ScaledResolution scaledresolution, int i, float f, int j, int k, int l) { + int line = k / mc.fontRendererObj.FONT_HEIGHT; + if (line >= getLineCount()) cir.setReturnValue(null); + } + + @Redirect(method = "deleteChatLine", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/ChatLine;getChatLineID()I")) + private int deleteChatLine(ChatLine instance) { + if (instance == null) return -1; + return instance.getChatLineID(); + } + + @Redirect(method = "drawChat", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/FontRenderer;drawStringWithShadow(Ljava/lang/String;FFI)I")) + public int renderShadow(FontRenderer instance, String text, float x, float y, int color) { + return instance.drawString(text, x, y, color, Client.getInstance().getModInstances().getModByClass(ChatMod.class).isEnabled() && Client.getInstance().getSettingsManager().getSettingByClass(ChatMod.class, "Font Shadow").getValBoolean()); + } +} diff --git a/src/main/java/net/silentclient/client/utils/MathUtils.java b/src/main/java/net/silentclient/client/utils/MathUtils.java new file mode 100644 index 0000000..a99279e --- /dev/null +++ b/src/main/java/net/silentclient/client/utils/MathUtils.java @@ -0,0 +1,50 @@ +package net.silentclient.client.utils; + +import java.math.BigDecimal; +import java.math.RoundingMode; + +public class MathUtils { + + public static float clamp(float value) { + return (double) value < 0.0D ? 0.0F : ((double) value > 1.0D ? 1.0F : value); + } + + public static float clamp(float number, float min, float max) { + return number < min ? min : Math.min(number, max); + } + + public static float lerp(float a, float b, float t) { + return a + (b - a) * clamp(t); + } + + public static float getPercent(float val, float min, float max) { + return (val - min) / (max - min); + } + + public static Double interpolate(double oldValue, double newValue, double interpolationValue){ + return (oldValue + (newValue - oldValue) * interpolationValue); + } + + public static float interpolateFloat(float oldValue, float newValue, double interpolationValue){ + return interpolate(oldValue, newValue, (float) interpolationValue).floatValue(); + } + + public static int interpolateInt(int oldValue, int newValue, double interpolationValue){ + return interpolate(oldValue, newValue, (float) interpolationValue).intValue(); + } + + public static float calculateGaussianValue(float x, float sigma) { + double PI = 3.141592653; + double output = 1.0 / Math.sqrt(2.0 * PI * (sigma * sigma)); + return (float) (output * Math.exp(-(x * x) / (2.0 * (sigma * sigma)))); + } + + public static double roundToPlace(final double value, final int places) { + if (places < 0) { + throw new IllegalArgumentException(); + } + BigDecimal bd = new BigDecimal(value); + bd = bd.setScale(places, RoundingMode.HALF_UP); + return bd.doubleValue(); + } +} \ No newline at end of file diff --git a/src/main/resources/mixins.SilentClient.json b/src/main/resources/mixins.SilentClient.json index 0957ede..869b67a 100644 --- a/src/main/resources/mixins.SilentClient.json +++ b/src/main/resources/mixins.SilentClient.json @@ -49,6 +49,7 @@ "accessors.FontRendererAccessor", "mixins.FontRendererMixin", "mixins.WorldInfoMixin", - "mixins.GuiPlayerTabOverlayMixin" + "mixins.GuiPlayerTabOverlayMixin", + "mixins.GuiNewChatMixin" ] } \ No newline at end of file