Skip to content

Commit

Permalink
Improve GUI mixin
Browse files Browse the repository at this point in the history
  • Loading branch information
NotRyken committed Aug 19, 2024
1 parent bec9aa0 commit cbe6311
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 98 deletions.
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
- Add Ukrainian translation (Tarteroycc)
- Improve GUI mixin
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,122 +1,128 @@
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
* <a href="https://github.com/magicus/statuseffecttimer/">Status Effect Timer</a>
*/
@Mixin(value = Gui.class, priority = 500)
public class MixinGui {

@Final
@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<MobEffectInstance> 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<MobEffect> 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<Void> 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<Runnable> runnables) {
if (effectTimerPlus$runnable != null) {
runnables.add(effectTimerPlus$runnable);
effectTimerPlus$runnable = null;
}
graphics.pose().popPose();
return original;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/**
Expand Down Expand Up @@ -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);
};
Expand All @@ -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);
};
Expand Down

0 comments on commit cbe6311

Please sign in to comment.