diff --git a/changelog.md b/changelog.md index eaf1142..19633ee 100644 --- a/changelog.md +++ b/changelog.md @@ -1 +1,2 @@ - Add Ukrainian translation (Tarteroycc) +- Improve GUI mixin diff --git a/common/src/main/java/dev/terminalmc/effecttimerplus/gui/screen/YaclScreenProvider.java b/common/src/main/java/dev/terminalmc/effecttimerplus/gui/screen/YaclScreenProvider.java index 8c59748..bc29a41 100644 --- a/common/src/main/java/dev/terminalmc/effecttimerplus/gui/screen/YaclScreenProvider.java +++ b/common/src/main/java/dev/terminalmc/effecttimerplus/gui/screen/YaclScreenProvider.java @@ -341,20 +341,23 @@ public int render(GuiGraphics graphics, int x, int y, int width, float delta) { int targetHeight = space; int maxX = (int)(x + width / scale); + int spriteSize = 24; + int iconSize = 18; + for (MobEffectInstance effect : DEMO_EFFECTS) { if (effect.isAmbient()) { - graphics.blitSprite(GuiAccessor.getEffectBackgroundAmbientSprite(), movingX, movingY, 24, 24); + graphics.blitSprite(GuiAccessor.getEffectBackgroundAmbientSprite(), movingX, movingY, spriteSize, spriteSize); } else { - graphics.blitSprite(GuiAccessor.getEffectBackgroundSprite(), movingX, movingY, 24, 24); + graphics.blitSprite(GuiAccessor.getEffectBackgroundSprite(), movingX, movingY, spriteSize, spriteSize); } - graphics.blit(movingX + 3, movingY + 3, 0, 18, 18, mc.getMobEffectTextures().get(effect.getEffect())); + graphics.blit(movingX + 3, movingY + 3, 0, iconSize, iconSize, mc.getMobEffectTextures().get(effect.getEffect())); // Render potency overlay if (potencyEnabled && effect.getAmplifier() > 0) { String label = IndicatorUtil.getAmplifierAsString(effect.getAmplifier()); int labelWidth = mc.font.width(label); - int pX = movingX + IndicatorUtil.getTextOffsetX(potencyLocation, labelWidth); - int pY = movingY + IndicatorUtil.getTextOffsetY(potencyLocation, mc.font.lineHeight); + int pX = movingX + IndicatorUtil.getTextOffsetX(potencyLocation, labelWidth, spriteSize); + int pY = movingY + IndicatorUtil.getTextOffsetY(potencyLocation, mc.font.lineHeight, spriteSize); graphics.pose().pushPose(); graphics.pose().translate(pX * (1 - potencyScale), pY * (1 - potencyScale), 0.0F); @@ -371,8 +374,8 @@ public int render(GuiGraphics graphics, int x, int y, int width, float delta) { if (timerEnabled && (timerEnabledAmbient || !effect.isAmbient())) { String label = IndicatorUtil.getDurationAsString(effect.getDuration()); int labelWidth = mc.font.width(label); - int pX = movingX + IndicatorUtil.getTextOffsetX(timerLocation, labelWidth); - int pY = movingY + IndicatorUtil.getTextOffsetY(timerLocation, mc.font.lineHeight); + int pX = movingX + IndicatorUtil.getTextOffsetX(timerLocation, labelWidth, spriteSize); + int pY = movingY + IndicatorUtil.getTextOffsetY(timerLocation, mc.font.lineHeight, spriteSize); graphics.pose().pushPose(); graphics.pose().translate(pX * (1 - timerScale), pY * (1 - timerScale), 0.0F); diff --git a/common/src/main/java/dev/terminalmc/effecttimerplus/mixin/MixinGui.java b/common/src/main/java/dev/terminalmc/effecttimerplus/mixin/MixinGui.java index 7db0315..4471531 100644 --- a/common/src/main/java/dev/terminalmc/effecttimerplus/mixin/MixinGui.java +++ b/common/src/main/java/dev/terminalmc/effecttimerplus/mixin/MixinGui.java @@ -1,30 +1,26 @@ package dev.terminalmc.effecttimerplus.mixin; -import com.google.common.collect.Ordering; +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; import dev.terminalmc.effecttimerplus.config.Config; import net.minecraft.client.DeltaTracker; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Gui; import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.client.gui.screens.inventory.EffectRenderingInventoryScreen; -import net.minecraft.core.Holder; -import net.minecraft.world.effect.MobEffect; +import net.minecraft.resources.ResourceLocation; import net.minecraft.world.effect.MobEffectInstance; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.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.util.Collection; +import java.util.List; import static dev.terminalmc.effecttimerplus.util.IndicatorUtil.*; -/** - * Includes derivative work of code used by - * Status Effect Timer - */ @Mixin(value = Gui.class, priority = 500) public class MixinGui { @@ -32,91 +28,101 @@ public class MixinGui { @Shadow private Minecraft minecraft; - @Inject(method = "renderEffects", at = @At("HEAD")) - private void scaleGraphics(GuiGraphics graphics, DeltaTracker delta, CallbackInfo ci) { + @Unique + @Nullable + private Runnable effectTimerPlus$runnable; + + @Inject( + method = "renderEffects", + at = @At("HEAD") + ) + private void scale(GuiGraphics graphics, DeltaTracker delta, CallbackInfo ci) { float scale = (float) Config.get().scale; graphics.pose().pushPose(); graphics.pose().translate(graphics.guiWidth() * (1 - scale), 0.0F, 0.0F); graphics.pose().scale(scale, scale, 0.0F); } - @Inject(method = "renderEffects", at = @At("RETURN")) - private void descaleGraphicsAndOverlay(GuiGraphics graphics, DeltaTracker delta, CallbackInfo ci) { - // Replicate vanilla placement algorithm to place labels correctly - Collection effects = this.minecraft.player.getActiveEffects(); - - if (effects.isEmpty() || this.minecraft.screen instanceof EffectRenderingInventoryScreen) { - graphics.pose().popPose(); - return; - } - - int beneficialCount = 0; - int nonBeneficialCount = 0; - - for (MobEffectInstance effectInstance : Ordering.natural().reverse().sortedCopy(effects)) { - Holder effect = effectInstance.getEffect(); - if (effectInstance.showIcon()) { - int x = graphics.guiWidth(); - int y = 1; - if (this.minecraft.isDemo()) { - y += 15; - } + @Inject( + method = "renderEffects", + at = @At("RETURN") + ) + private void descale(GuiGraphics graphics, DeltaTracker delta, CallbackInfo ci) { + graphics.pose().popPose(); + } - if (effect.value().isBeneficial()) { - ++beneficialCount; - x -= 25 * beneficialCount; - } else { - ++nonBeneficialCount; - x -= 25 * nonBeneficialCount; - y += 26; - } + @WrapOperation( + method = "renderEffects", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/client/gui/GuiGraphics;blitSprite(Lnet/minecraft/resources/ResourceLocation;IIII)V" + ) + ) + private void CreateOverlayRunnable(GuiGraphics graphics, ResourceLocation sprite, int x, int y, + int width, int height, Operation original, + @Local MobEffectInstance effectInstance) { + original.call(graphics, sprite, x, y, width, height); - Config options = Config.get(); - // Render potency overlay - if (options.potencyEnabled && effectInstance.getAmplifier() > 0) { - String label = getAmplifierAsString(effectInstance.getAmplifier()); - int labelWidth = minecraft.font.width(label); - int posX = x + getTextOffsetX(options.potencyLocation, labelWidth); - int posY = y + getTextOffsetY(options.potencyLocation, minecraft.font.lineHeight); + Config options = Config.get(); + effectTimerPlus$runnable = () -> { + // Render potency overlay + if (options.potencyEnabled && effectInstance.getAmplifier() > 0) { + String label = getAmplifierAsString(effectInstance.getAmplifier()); + int labelWidth = minecraft.font.width(label); + int posX = x + getTextOffsetX(options.potencyLocation, labelWidth, width); + int posY = y + getTextOffsetY(options.potencyLocation, minecraft.font.lineHeight, height); - float scale = (float)Config.get().potencyScale; - graphics.pose().pushPose(); - graphics.pose().translate(posX * (1 - scale), posY * (1 - scale), 0.0F); - graphics.pose().translate(getScaleTranslateX(options.potencyLocation, labelWidth, scale), - getScaleTranslateY(options.potencyLocation, minecraft.font.lineHeight, scale), 0.0F); - graphics.pose().scale(scale, scale, 0.0F); - if (options.potencyBack) { - graphics.fill(posX - 1, posY - 1, posX + labelWidth, - posY + minecraft.font.lineHeight - 1, options.potencyBackColor); - } - graphics.drawString(minecraft.font, label, posX, posY, options.potencyColor, options.potencyShadow); - graphics.pose().popPose(); + float scale = (float)Config.get().potencyScale; + graphics.pose().pushPose(); + graphics.pose().translate(posX * (1 - scale), posY * (1 - scale), 0.0F); + graphics.pose().translate(getScaleTranslateX(options.potencyLocation, labelWidth, scale), + getScaleTranslateY(options.potencyLocation, minecraft.font.lineHeight, scale), 0.0F); + graphics.pose().scale(scale, scale, 0.0F); + if (options.potencyBack) { + graphics.fill(posX - 1, posY - 1, posX + labelWidth, + posY + minecraft.font.lineHeight - 1, options.potencyBackColor); } - // Render timer overlay - if (options.timerEnabled && (options.timerEnabledAmbient || !effectInstance.isAmbient())) { - String label = getDurationAsString(effectInstance.getDuration()); - int labelWidth = minecraft.font.width(label); - int posX = x + getTextOffsetX(options.timerLocation, labelWidth); - int posY = y + getTextOffsetY(options.timerLocation, minecraft.font.lineHeight); + graphics.drawString(minecraft.font, label, posX, posY, options.potencyColor, options.potencyShadow); + graphics.pose().popPose(); + } + // Render timer overlay + if (options.timerEnabled && (options.timerEnabledAmbient || !effectInstance.isAmbient())) { + String label = getDurationAsString(effectInstance.getDuration()); + int labelWidth = minecraft.font.width(label); + int posX = x + getTextOffsetX(options.timerLocation, labelWidth, width); + int posY = y + getTextOffsetY(options.timerLocation, minecraft.font.lineHeight, height); - int color = getTimerColor(effectInstance, options.timerColor, - options.timerWarnEnabled, options.timerWarnTime, - options.timerWarnColor, options.timerFlashEnabled); - float scale = (float)Config.get().timerScale; - graphics.pose().pushPose(); - graphics.pose().translate(posX * (1 - scale), posY * (1 - scale), 0.0F); - graphics.pose().translate(getScaleTranslateX(options.timerLocation, labelWidth, scale), - getScaleTranslateY(options.timerLocation, minecraft.font.lineHeight, scale), 0.0F); - graphics.pose().scale(scale, scale, 0.0F); - if (options.timerBack) { - graphics.fill(posX - 1, posY - 1, posX + labelWidth, - posY + minecraft.font.lineHeight - 1, options.timerBackColor); - } - graphics.drawString(minecraft.font, label, posX, posY, color, options.timerShadow); - graphics.pose().popPose(); + int color = getTimerColor(effectInstance, options.timerColor, + options.timerWarnEnabled, options.timerWarnTime, + options.timerWarnColor, options.timerFlashEnabled); + float scale = (float)Config.get().timerScale; + graphics.pose().pushPose(); + graphics.pose().translate(posX * (1 - scale), posY * (1 - scale), 0.0F); + graphics.pose().translate(getScaleTranslateX(options.timerLocation, labelWidth, scale), + getScaleTranslateY(options.timerLocation, minecraft.font.lineHeight, scale), 0.0F); + graphics.pose().scale(scale, scale, 0.0F); + if (options.timerBack) { + graphics.fill(posX - 1, posY - 1, posX + labelWidth, + posY + minecraft.font.lineHeight - 1, options.timerBackColor); } + graphics.drawString(minecraft.font, label, posX, posY, color, options.timerShadow); + graphics.pose().popPose(); } + }; + } + + @ModifyExpressionValue( + method = "renderEffects", + at = @At( + value = "INVOKE", + target = "Ljava/util/List;add(Ljava/lang/Object;)Z" + ) + ) + private boolean AddOverlayRunnable(boolean original, @Local List runnables) { + if (effectTimerPlus$runnable != null) { + runnables.add(effectTimerPlus$runnable); + effectTimerPlus$runnable = null; } - graphics.pose().popPose(); + return original; } } diff --git a/common/src/main/java/dev/terminalmc/effecttimerplus/util/IndicatorUtil.java b/common/src/main/java/dev/terminalmc/effecttimerplus/util/IndicatorUtil.java index 277b362..4c3fc9b 100644 --- a/common/src/main/java/dev/terminalmc/effecttimerplus/util/IndicatorUtil.java +++ b/common/src/main/java/dev/terminalmc/effecttimerplus/util/IndicatorUtil.java @@ -4,7 +4,6 @@ import net.minecraft.world.effect.MobEffectInstance; public class IndicatorUtil { - public static final int SPRITE_SIZE = 24; public static final int SPRITE_BORDER = 3; /** @@ -78,11 +77,11 @@ else if (seconds >= 60) { * @return the X-axis offset. * @throws IllegalStateException if the given index is invalid. */ - public static int getTextOffsetX(int locIndex, int labelWidth) { + public static int getTextOffsetX(int locIndex, int labelWidth, int spriteWidth) { return switch (locIndex) { case 0, 6, 7 -> SPRITE_BORDER; // Left - case 1, 5 -> (SPRITE_SIZE / 2) - (labelWidth / 2); // Center - case 2, 3, 4 -> SPRITE_SIZE - SPRITE_BORDER - (labelWidth - 1); // Right + case 1, 5 -> (spriteWidth / 2) - (labelWidth / 2); // Center + case 2, 3, 4 -> spriteWidth - SPRITE_BORDER - (labelWidth - 1); // Right default -> throw new IllegalStateException( "Unexpected positional index outside of allowed range (0-7): " + locIndex); }; @@ -95,11 +94,11 @@ public static int getTextOffsetX(int locIndex, int labelWidth) { * @return the Y-axis offset. * @throws IllegalStateException if the given index is invalid. */ - public static int getTextOffsetY(int locIndex, int labelHeight) { + public static int getTextOffsetY(int locIndex, int labelHeight, int spriteHeight) { return switch (locIndex) { case 0, 1, 2 -> SPRITE_BORDER; // Top - case 3, 7 -> (SPRITE_SIZE / 2) - (labelHeight / 2); // Center - case 4, 5, 6 -> SPRITE_SIZE - SPRITE_BORDER - (labelHeight - 2); // Bottom + case 3, 7 -> (spriteHeight / 2) - (labelHeight / 2); // Center + case 4, 5, 6 -> spriteHeight - SPRITE_BORDER - (labelHeight - 2); // Bottom default -> throw new IllegalStateException( "Unexpected positional index outside of allowed range (0-7): " + locIndex); };