Init
This commit is contained in:
242
src/main/java/systems/brn/hudbars/mixin/InGameHudMixin.java
Normal file
242
src/main/java/systems/brn/hudbars/mixin/InGameHudMixin.java
Normal 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);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user