Update to 1.21.4

This commit is contained in:
Bruno Rybársky 2024-12-05 13:40:59 +01:00
parent 4796b2b78f
commit d0465eeed6
Signed by: BRNSystems
GPG Key ID: 6C9206A821C70598
5 changed files with 270 additions and 117 deletions

@ -1,5 +1,5 @@
plugins {
id 'fabric-loom' version '1.7-SNAPSHOT'
id 'fabric-loom' version '1.8-SNAPSHOT'
id 'maven-publish'
}
@ -88,3 +88,7 @@ publishing {
// retrieving dependencies.
}
}
loom {
accessWidenerPath = file("src/main/resources/hudbars.accesswidener")
}

@ -2,13 +2,13 @@
org.gradle.jvmargs=-Xmx1G
# Fabric Properties
# check these on https://modmuss50.me/fabric.html
minecraft_version=1.21.1
yarn_mappings=1.21.1+build.3
loader_version=0.16.2
minecraft_version=1.21.4
yarn_mappings=1.21.4+build.1
loader_version=0.16.9
# Mod Properties
mod_version=1.0
mod_version=1.1.3
maven_group=systems.brn
archives_base_name=hudbars
# Dependencies
# check this on https://modmuss50.me/fabric.html
fabric_version=0.102.1+1.21.1
fabric_version=0.110.5+1.21.4

@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME

@ -6,12 +6,16 @@ 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.JumpingMount;
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.registry.tag.FluidTags;
import net.minecraft.util.Util;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.GameMode;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
@ -23,13 +27,111 @@ 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) {
@Inject(method = "render", at = @At("HEAD"), cancellable = true)
private void renderMainHud(DrawContext context, RenderTickCounter tickCounter, CallbackInfo ci) {
InGameHud hud = (InGameHud) (Object) this;
MinecraftClient client = hud.client;
PlayerEntity player = client.player;
if (client.interactionManager.getCurrentGameMode() == GameMode.SPECTATOR) {
hud.getSpectatorHud().renderSpectatorMenu(context);
} else {
hud.renderHotbar(context, tickCounter);
}
if (player == null) return;
// Calculate HUD bar positions
int centerX = context.getScaledWindowWidth() / 2 - 91;
// Render Jump Bar for Mount
JumpingMount jumpingMount = client.player.getJumpingMount();
if (jumpingMount != null) {
renderMountJumpBar(jumpingMount, context, centerX);
}
// Render Status Bars (Health, Armor, Food, Air)
renderStatusBars(context);
// Render Mount Health (if applicable)
renderMountHealth(context);
// Render Experience Bar
renderExperienceBar(context, centerX);
// Render Held Item Tooltip
if (client.interactionManager.getCurrentGameMode() != GameMode.SPECTATOR) {
hud.renderHeldItemTooltip(context);
} else if (player.isSpectator()) {
hud.getSpectatorHud().render(context);
}
hud.renderCrosshair(context, tickCounter);
ci.cancel();
}
private void renderStatusBars(DrawContext context) {
InGameHud hud = (InGameHud) (Object) this;
MinecraftClient client = hud.client;
PlayerEntity player = hud.getCameraPlayer();
if (player != null) {
int lastHealth = MathHelper.ceil(player.getHealth());
boolean bl = hud.heartJumpEndTick > (long) hud.getTicks() && (hud.heartJumpEndTick - (long) hud.getTicks()) / 3L % 2L == 1L;
int screenWidth = context.getScaledWindowWidth();
int screenHeight = context.getScaledWindowHeight();
int baseY = screenHeight - 39;
long l = Util.getMeasuringTimeMs();
if (lastHealth < hud.lastHealthValue && player.timeUntilRegen > 0) {
hud.lastHealthCheckTime = l;
hud.heartJumpEndTick = (long) (hud.getTicks() + 20);
} else if (lastHealth > hud.lastHealthValue && player.timeUntilRegen > 0) {
hud.lastHealthCheckTime = l;
hud.heartJumpEndTick = (long) (hud.getTicks() + 10);
}
if (l - hud.lastHealthCheckTime > 1000L) {
hud.lastHealthValue = lastHealth;
hud.renderHealthValue = lastHealth;
hud.lastHealthCheckTime = l;
}
hud.lastHealthValue = lastHealth;
int health = hud.renderHealthValue;
int x = context.getScaledWindowWidth() / 2 - 91;
int m = context.getScaledWindowWidth() / 2 + 91;
int y = context.getScaledWindowHeight() - 39;
float maxHealthFloat = Math.max((float) player.getAttributeValue(EntityAttributes.MAX_HEALTH), (float) Math.max(health, lastHealth));
int absorption = MathHelper.ceil(player.getAbsorptionAmount());
int p = MathHelper.ceil((maxHealthFloat + (float) absorption) / 2.0F / 10.0F);
int q = Math.max(10 - (p - 2), 3);
renderArmor(context, player, y, p, q, x);
renderHealthBar(context, player, x, y, maxHealthFloat, lastHealth, health, absorption, bl);
renderFood(context, player, y, m);
renderAir(context, player, baseY, screenWidth / 2 + 91);
}
}
private void renderMountHealth(DrawContext context) {
InGameHud hud = (InGameHud) (Object) this;
LivingEntity mount = hud.getRiddenEntity();
if (mount != null) {
int health = (int) Math.ceil(mount.getHealth());
int screenHeight = context.getScaledWindowHeight();
int screenWidth = context.getScaledWindowWidth();
int baseX = screenWidth / 2 + 12;
int baseY = screenHeight - 52;
renderHealthBar(context, mount, baseX, baseY, mount.getMaxHealth(), health, health, 0, false);
}
}
private void renderHealthBar(DrawContext context, LivingEntity player, int x, int y, float maxHealthFloat, int lastHealth, int health, int absorption, boolean blinking) {
int barWidth = 80;
int barHeight = 10;
int maxHealth = (int) maxHealthFloat;
y -= 12;
y -= 8;
int color;
int borderColor;
@ -60,35 +162,116 @@ public class InGameHudMixin {
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;
private static int getArmorToughness(LivingEntity livingEntity) {
return MathHelper.floor(livingEntity.getAttributeValue(EntityAttributes.ARMOR_TOUGHNESS));
}
// Extract RGB channels
int red = (color & 0x00FF0000) >> 16;
int green = (color & 0x0000FF00) >> 8;
int blue = color & 0x000000FF;
@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
// 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;
// Combine the RGB values into a single color integer
return (0xFF << 24) | (red << 16) | (green << 8) | blue;
}
@Inject(method = "renderFood", at = @At("HEAD"), cancellable = true)
private void renderFood(DrawContext context, PlayerEntity player, int top, int right, CallbackInfo ci) {
@Unique
private static void renderArmor(DrawContext context, PlayerEntity player, int i, int j, int k, int x) {
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 - 21;
// 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();
}
}
private void renderMountJumpBar(JumpingMount mount, DrawContext context, int x) {
InGameHud hud = (InGameHud) (Object) this;
MinecraftClient client = hud.client;
int screenHeight = context.getScaledWindowHeight();
int y = screenHeight - 68;
float jumpStrength = client.player.getMountJumpStrength();
// Background color for the bar
int backgroundColor = 0xFF555555; // Grey background
// Main bar color
int barColor = 0xFF00FF00; // Green color for the jump bar (can be adjusted)
// Border color
int borderColor = 0xFFFFFFFF; // White border
// Text to display
String text = ""; // Assuming no text to be displayed on the jump bar
// Inner bar color, if applicable
int innerBarColor = 0xFFFF0000; // Red color for the inner bar (can be adjusted)
// Calculate fill percentage based on jump strength
float fillPercentage = jumpStrength;
// Check for cooldown
float innerPercentage = (mount.getJumpCooldown() > 0) ? 1.0f : 0.0f;
// Draw the bar using the drawBar function
drawBar(context, x, y, 182, 5, fillPercentage, barColor, borderColor, text, innerPercentage, innerBarColor);
}
private void renderExperienceBar(DrawContext context, int x) {
InGameHud hud = (InGameHud) (Object) this;
MinecraftClient client = hud.client;
PlayerEntity player = client.player;
if (player == null) return;
int screenHeight = context.getScaledWindowHeight();
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 = screenHeight - 34;
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();
}
}
private void renderFood(DrawContext context, PlayerEntity player, int top, int right) {
HungerManager hungerManager = player.getHungerManager();
int foodLevel = hungerManager.getFoodLevel();
float saturationLevel = hungerManager.getSaturationLevel();
@ -97,7 +280,7 @@ public class InGameHudMixin {
int barHeight = 10;
int x = right - barWidth + 1;
int y = top - 12;
int y = top - 8;
int color;
@ -121,99 +304,30 @@ public class InGameHudMixin {
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;
float saturationPercentage = saturationLevel / 20.0f;
// 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) {
private void renderAir(DrawContext context, PlayerEntity player, int top, int right) {
int air = player.getAir();
int maxAir = player.getMaxAir();
int barWidth = 80;
int barHeight = 10;
int posY = i - (j - 1) * k - 26;
int x = right - barWidth + 1;
int y = top - 22;
// 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();
if (air < maxAir || player.isSubmergedIn(FluidTags.WATER)) {
float airPercentage = (float) air / (float) maxAir;
if (airPercentage < 0) {
airPercentage = 0;
}
String airText = "%d/%d".formatted(air, maxAir);
drawBar(context, x, y, barWidth, barHeight, airPercentage, 0xFF00FFFF, 0xFF000000, airText, 0, 0);
}
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) {
@ -239,4 +353,26 @@ public class InGameHudMixin {
TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer;
context.drawText(textRenderer, text, x + 2, y + 1, 0xFFFFFFFF, false);
}
@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;
}
}

@ -0,0 +1,13 @@
accessWidener v2 named
accessible method net/minecraft/client/gui/hud/InGameHud getCameraPlayer ()Lnet/minecraft/entity/player/PlayerEntity;
accessible field net/minecraft/client/gui/hud/InGameHud client Lnet/minecraft/client/MinecraftClient;
accessible field net/minecraft/client/gui/hud/InGameHud heartJumpEndTick J
accessible field net/minecraft/client/gui/hud/InGameHud lastHealthValue I
accessible field net/minecraft/client/gui/hud/InGameHud lastHealthCheckTime J
accessible field net/minecraft/client/gui/hud/InGameHud renderHealthValue I
accessible field net/minecraft/client/gui/hud/InGameHud random Lnet/minecraft/util/math/random/Random;
accessible method net/minecraft/client/gui/hud/InGameHud renderHotbar (Lnet/minecraft/client/gui/DrawContext;Lnet/minecraft/client/render/RenderTickCounter;)V
accessible method net/minecraft/client/gui/hud/InGameHud renderHeldItemTooltip (Lnet/minecraft/client/gui/DrawContext;)V
accessible method net/minecraft/client/gui/hud/InGameHud getRiddenEntity ()Lnet/minecraft/entity/LivingEntity;
accessible method net/minecraft/client/gui/hud/InGameHud getHeartCount (Lnet/minecraft/entity/LivingEntity;)I
accessible method net/minecraft/client/gui/hud/InGameHud renderCrosshair (Lnet/minecraft/client/gui/DrawContext;Lnet/minecraft/client/render/RenderTickCounter;)V