This commit is contained in:
2024-08-24 20:44:08 +02:00
commit 4796b2b78f
14 changed files with 898 additions and 0 deletions

View File

@@ -0,0 +1,242 @@
package systems.brn.hudbars.mixin;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.hud.InGameHud;
import net.minecraft.client.render.RenderTickCounter;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.attribute.EntityAttributes;
import net.minecraft.entity.effect.StatusEffects;
import net.minecraft.entity.player.HungerManager;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.math.MathHelper;
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.callback.CallbackInfo;
import static net.minecraft.entity.effect.StatusEffects.POISON;
import static net.minecraft.entity.effect.StatusEffects.WITHER;
@Mixin(InGameHud.class)
public class InGameHudMixin {
@Inject(method = "renderHealthBar", at = @At("HEAD"), cancellable = true)
private void renderHealthBar(DrawContext context, PlayerEntity player, int x, int y, int lines, int regeneratingHeartIndex, float maxHealthFloat, int lastHealth, int health, int absorption, boolean blinking, CallbackInfo ci) {
int barWidth = 80;
int barHeight = 10;
int maxHealth = (int) maxHealthFloat;
y -= 12;
int color;
int borderColor;
if (blinking && lastHealth != health) {
borderColor = 0xFFFFFFFF;
} else if (blinking) {
borderColor = 0xFFFF0000;
} else if (lastHealth != health) {
borderColor = 0xFFFF80FF;
} else {
borderColor = 0xFF000000;
}
if (player.hasStatusEffect(POISON)) {
color = 0xFF004400;
} else if (player.hasStatusEffect(WITHER)) {
color = 0xFF000000;
} else if (player.isFrozen()) {
color = 0xFF00FFFF;
} else if (absorption > 0) {
color = 0xFFAAAA00;
} else {
color = 0xFF55AA00;
}
float healthPercentage = (float) lastHealth / maxHealth;
String healthText = "%d/%d".formatted(lastHealth + absorption, maxHealth);
drawBar(context, x, y, barWidth, barHeight, healthPercentage, color, borderColor, healthText, 0, 0);
ci.cancel();
}
@Unique
private static int generateSubBarColor(int color) {
// Mask the alpha channel (first byte)
int alpha = color & 0xFF000000;
// Extract RGB channels
int red = (color & 0x00FF0000) >> 16;
int green = (color & 0x0000FF00) >> 8;
int blue = color & 0x000000FF;
// Halve each RGB channel
red = Math.max(red / 2, 0);
green = Math.max(green / 2, 0);
blue = Math.max(blue / 2, 0);
// Combine the halved RGB channels back into the color
int RGB = (red << 16) | (green << 8) | blue;
// Combine the alpha channel with the modified RGB channels
return alpha | RGB;
}
@Inject(method = "renderFood", at = @At("HEAD"), cancellable = true)
private void renderFood(DrawContext context, PlayerEntity player, int top, int right, CallbackInfo ci) {
HungerManager hungerManager = player.getHungerManager();
int foodLevel = hungerManager.getFoodLevel();
float saturationLevel = hungerManager.getSaturationLevel();
int barWidth = 80;
int barHeight = 10;
int x = right - barWidth + 1;
int y = top - 12;
int color;
if (player.hasStatusEffect(StatusEffects.HUNGER)) {
color = 0xFFAA55AA;
} else if (player.hasStatusEffect(StatusEffects.SATURATION)) {
color = 0xFF00FF00;
} else if (foodLevel >= 20) {
color = 0xFF00FF00;
} else if (foodLevel >= 18) {
color = 0xFF33FF00;
} else if (foodLevel > 6) {
color = 0xFF66FF00;
} else if (foodLevel > 0) {
color = 0xFFFFFF00;
} else {
color = 0xFFFF0000;
}
float foodPercentage = (float) foodLevel / 20.0f;
String foodText = "%d(%d)/%d".formatted(foodLevel, (int) saturationLevel, 20);
// Calculate the saturation percentage relative to the current food level
float saturationPercentage = saturationLevel > 0 ? (saturationLevel / (float) foodLevel) : 0;
// Use the drawBar method with the innerPercentage and innerColor for saturation
drawBar(context, x, y, barWidth, barHeight, foodPercentage, color, 0xFF000000, foodText, saturationPercentage, generateSubBarColor(color));
ci.cancel();
}
@Unique
private static int getArmorToughness(LivingEntity livingEntity) {
return MathHelper.floor(livingEntity.getAttributeValue(EntityAttributes.GENERIC_ARMOR_TOUGHNESS));
}
@Unique
private static int computeArmorColor(float armorPercentage) {
// Gradually interpolate between grey (low armor) and green (high armor)
int red = (int) (0xAA * (1.0f - armorPercentage)); // Red decreases as armor increases
int green = (int) (0xFF * armorPercentage); // Green increases as armor increases
int blue = (int) (0x55 + (0xAA * armorPercentage)); // Blue shifts from grey to green
// Combine the RGB values into a single color integer
return (0xFF << 24) | (red << 16) | (green << 8) | blue;
}
@Inject(method = "renderArmor", at = @At("HEAD"), cancellable = true)
private static void renderArmor(DrawContext context, PlayerEntity player, int i, int j, int k, int x, CallbackInfo ci) {
int armorLevel = player.getArmor();
int armorToughness = getArmorToughness(player);
// Skip rendering if armor level is 0
if (armorLevel > 0) {
int barWidth = 80;
int barHeight = 10;
int posY = i - (j - 1) * k - 26;
// Compute the color based on the armor level percentage
float armorPercentage = (float) armorLevel / 20.0f;
float toughnessPercentage = (float) armorToughness / 20.0f;
int color = computeArmorColor(armorPercentage);
// Armor text to display
String armorText = "%d/%d".formatted(armorLevel, 20);
// Use the drawBar method to render the armor bar
drawBar(context, x, posY, barWidth, barHeight, armorPercentage, color, 0xFF000000, armorText, toughnessPercentage, generateSubBarColor(color));
RenderSystem.disableBlend();
}
ci.cancel();
}
@Inject(method = "renderExperienceBar", at = @At("HEAD"), cancellable = true)
private void renderExperienceBar(DrawContext context, int x, CallbackInfo ci) {
MinecraftClient client = MinecraftClient.getInstance();
PlayerEntity player = client.player;
if (player == null) {
ci.cancel();
return;
}
client.getProfiler().push("expBar");
int experienceNeededForNextLevel = player.getNextLevelExperience();
if (experienceNeededForNextLevel > 0) {
int experienceGotForThisLevel = (int) (player.experienceProgress * experienceNeededForNextLevel);
int experienceLevel = player.experienceLevel;
int barWidth = 183;
int barHeight = 10;
int filledWidth = (int) (player.experienceProgress * barWidth);
int y = context.getScaledWindowHeight() - 36;
RenderSystem.enableBlend();
// Display experienceGotForThisLevel/experienceNeededForNextLevel
String experienceText = "%d/%d (%d)".formatted(experienceGotForThisLevel, experienceNeededForNextLevel, experienceLevel);
drawBar(context, x, y, barWidth, barHeight, (float) filledWidth / barWidth, 0xFFAAAA00, 0xFF000000, experienceText, 0, 0);
RenderSystem.disableBlend();
}
client.getProfiler().pop();
ci.cancel();
}
@Inject(method = "renderExperienceLevel", at = @At("HEAD"), cancellable = true)
private void renderExperienceLevel(DrawContext context, RenderTickCounter tickCounter, CallbackInfo ci) {
ci.cancel();
}
// Common helper method for rendering bars
@Unique
private static void drawBar(DrawContext context, int x, int y, int barWidth, int barHeight, float percentage, int color, int borderColor, String text, float innerPercentage, int innerColor) {
// Draw outer border
context.fill(x - 1, y - 1, x + barWidth + 1, y + barHeight + 1, borderColor);
// Draw background
context.fill(x, y, x + barWidth, y + barHeight, 0xFF555555); // Grey background
// Calculate the filled width based on the percentage
int filledWidth = (int) (barWidth * percentage);
// Draw the filled part of the bar
context.fill(x, y, x + filledWidth, y + barHeight, color);
// Draw the inner bar if applicable
if (innerPercentage > 0) {
int innerFilledWidth = (int) (barWidth * innerPercentage);
context.fill(x, y, x + innerFilledWidth, y + barHeight, innerColor);
}
// Render the text
TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer;
context.drawText(textRenderer, text, x + 2, y + 1, 0xFFFFFFFF, false);
}
}