Как сделать отдельные рамки сердечек для эффектов

Версия Minecraft
1.21.1
API
Fabric
25
2
2
Вот о каких рамках идёт речь:

1727466762000.png1727466903545.png

Отдельные сердечки у эффекта реализованы следующими двумя файлами:
GameHudMixin:

GameHudMixin:
package net.yaksolo.ambulance.mixin.client;



import com.mojang.blaze3d.systems.RenderSystem;

import net.minecraft.client.MinecraftClient;

import net.minecraft.client.gui.DrawContext;

import net.minecraft.client.gui.hud.InGameHud;

import net.minecraft.client.option.AttackIndicator;

import net.minecraft.client.render.RenderTickCounter;

import net.minecraft.entity.Entity;

import net.minecraft.entity.effect.StatusEffectInstance;

import net.minecraft.entity.player.PlayerEntity;

import net.minecraft.entity.player.PlayerInventory;

import net.minecraft.item.ItemStack;

import net.minecraft.item.Items;

import net.minecraft.item.RangedWeaponItem;

import net.minecraft.registry.entry.RegistryEntry;

import net.minecraft.util.Arm;

import net.minecraft.util.Identifier;

import net.minecraft.util.math.MathHelper;

import net.minecraft.util.math.random.Random;

import net.yaksolo.ambulance.effects.ModEffects;

import net.yaksolo.ambulance.misc.ModHeartType;

import org.spongepowered.asm.mixin.Mixin;

import org.spongepowered.asm.mixin.Shadow;

import org.spongepowered.asm.mixin.injection.At;

import org.spongepowered.asm.mixin.injection.Inject;

import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;



@Mixin(InGameHud.class)

public class GameHudMixin {



private static final Identifier HOTBAR_TEXTURE = Identifier.ofVanilla("hud/hotbar");

private static final Identifier HOTBAR_SELECTION_TEXTURE = Identifier.ofVanilla("hud/hotbar_selection");

private static final Identifier HOTBAR_OFFHAND_LEFT_TEXTURE = Identifier.ofVanilla("hud/hotbar_offhand_left");

private static final Identifier HOTBAR_OFFHAND_RIGHT_TEXTURE = Identifier.ofVanilla("hud/hotbar_offhand_right");

private static final Identifier HOTBAR_ATTACK_INDICATOR_BACKGROUND_TEXTURE = Identifier.ofVanilla("hud/hotbar_attack_indicator_background");

private static final Identifier HOTBAR_ATTACK_INDICATOR_PROGRESS_TEXTURE = Identifier.ofVanilla("hud/hotbar_attack_indicator_progress");



[USER=8500]@Shadow[/USER] MinecraftClient client;



@Inject(method = {"renderHealthBar"}, at = @At("INVOKE"), cancellable = true)

private void renderHealthBar(DrawContext context, PlayerEntity player, int x, int y, int lines, int regeneratingHeartIndex, float maxHealth, int lastHealth, int health, int absorption, boolean blinking, CallbackInfo info) {

        info.cancel();



        Random random = player.getRandom();

ModHeartType heartType = ModHeartType.fromPlayerState(player);

 boolean bl = player.getWorld().getLevelProperties().isHardcore();

int i = MathHelper.ceil((double)maxHealth / 2.0);

int j = MathHelper.ceil((double)absorption / 2.0);

int k = i * 2;



for(int l = i + j - 1; l >= 0; --l) {

int m = l / 10;

int n = l % 10;

int o = x + n * 8;

 int p = y - m * lines;

if (lastHealth + absorption <= 4) {

p += random.nextInt(2);

            }



 if (l < i && l == regeneratingHeartIndex) {

p -= 2;

            }



drawHeart(context, ModHeartType.CONTAINER, o, p, bl, blinking, false);

int q = l * 2;

 boolean bl2 = l >= i;

 if (bl2) {

 int r = q - k;

 if (r < absorption) {

boolean bl3 = r + 1 == absorption;

drawHeart(context, heartType == ModHeartType.WITHERED ? heartType : ModHeartType.ABSORBING, o, p, bl, false, bl3);

                }

            }



 boolean bl4;

 if (blinking && q < health) {

bl4 = q + 1 == health;

drawHeart(context, (player.hasStatusEffect(ModEffects.FRUIT_EXTENSION) && (l > 9 && l <= getMaxFruitExpansionHearts(player))) ? ModHeartType.FRUIT_EXTENSION : heartType, o, p, bl, true, bl4);

            }



 if (q < lastHealth) {

bl4 = q + 1 == lastHealth;

drawHeart(context, (player.hasStatusEffect(ModEffects.FRUIT_EXTENSION) && (l > 9 && l <= getMaxFruitExpansionHearts(player))) ? ModHeartType.FRUIT_EXTENSION : heartType, o, p, bl, false, bl4);

            }

        }



    }



@Inject(method = {"renderHotbar"}, at = @At("INVOKE"), cancellable = true)

private void renderHotbar(DrawContext context, RenderTickCounter tickCounter, CallbackInfo info) {

        info.cancel();



        PlayerEntity playerEntity = getCameraPlayer();

if (playerEntity != null) {

            ItemStack itemStack = playerEntity.getOffHandStack();

            Arm arm = playerEntity.getMainArm().getOpposite();

int i = context.getScaledWindowWidth() / 2;

RenderSystem.enableBlend();

            context.getMatrices().push();

context.getMatrices().translate(0.0F, 0.0F, -90.0F);

context.drawGuiTexture(HOTBAR_TEXTURE, i - 91, context.getScaledWindowHeight() - 22, 182, 22);

context.drawGuiTexture(HOTBAR_SELECTION_TEXTURE, i - 91 - 1 + playerEntity.getInventory().selectedSlot * 20, context.getScaledWindowHeight() - 22 - 1, 24, 23);

 if (!itemStack.isEmpty()) {

if (arm == Arm.LEFT) {

context.drawGuiTexture(HOTBAR_OFFHAND_LEFT_TEXTURE, i - 91 - 29, context.getScaledWindowHeight() - 23, 29, 24);

} else {

context.drawGuiTexture(HOTBAR_OFFHAND_RIGHT_TEXTURE, i + 91, context.getScaledWindowHeight() - 23, 29, 24);

                }

            }



            context.getMatrices().pop();

RenderSystem.disableBlend();

int l = 1;



 int m;

 int n;

 int o;

for(m = 0; m < 9; ++m) {

n = i - 90 + m * 20 + 2;

o = context.getScaledWindowHeight() - 16 - 3;

renderHotbarItem(context, n, o, tickCounter, playerEntity, (ItemStack)playerEntity.getInventory().main.get(m), l++);

            }



 if (!itemStack.isEmpty()) {

m = context.getScaledWindowHeight() - 16 - 3;

if (arm == Arm.LEFT) {

renderHotbarItem(context, i - 91 - 26, m, tickCounter, playerEntity, itemStack, l++);

} else {

renderHotbarItem(context, i + 91 + 10, m, tickCounter, playerEntity, itemStack, l++);

                }

            }



if (client.options.getAttackIndicator().getValue() == AttackIndicator.HOTBAR) {

RenderSystem.enableBlend();

float f = client.player.getAttackCooldownProgress(0.0F);

if (f < 1.0F) {

n = context.getScaledWindowHeight() - 20;

o = i + 91 + 6;

if (arm == Arm.RIGHT) {

o = i - 91 - 22;

                    }



int p = (int)(f * 19.0F);

context.drawGuiTexture(HOTBAR_ATTACK_INDICATOR_BACKGROUND_TEXTURE, o, n, 18, 18);

context.drawGuiTexture(HOTBAR_ATTACK_INDICATOR_PROGRESS_TEXTURE, 18, 18, 0, 18 - p, o, n + 18 - p, 18, p);

                }



RenderSystem.disableBlend();

            }



        }

    }



private void renderHotbarItem(DrawContext context, int x, int y, RenderTickCounter tickCounter, PlayerEntity player, ItemStack stack, int seed) {

 if (!stack.isEmpty()) {

float f = (float)stack.getBobbingAnimationTime() - tickCounter.getTickDelta(false);

if (f > 0.0F) {

float g = 1.0F + f / 5.0F;

                context.getMatrices().push();

context.getMatrices().translate((float)(x + 8), (float)(y + 12), 0.0F);

context.getMatrices().scale(1.0F / g, (g + 1.0F) / 2.0F, 1.0F);

context.getMatrices().translate((float)(-(x + 8)), (float)(-(y + 12)), 0.0F);

            }



            context.drawItem(player, stack, x, y, seed);

if (f > 0.0F) {

                context.getMatrices().pop();

            }



context.drawItemInSlot(client.textRenderer, stack, x, y);

        }

    }



private PlayerEntity getCameraPlayer() {

Entity var2 = MinecraftClient.getInstance().getCameraEntity();

        PlayerEntity var10000;

if (var2 instanceof PlayerEntity playerEntity) {

            var10000 = playerEntity;

} else {

var10000 = null;

        }



 return var10000;

    }



private void drawHeart(DrawContext context, ModHeartType type, int x, int y, boolean hardcore, boolean blinking, boolean half) {

RenderSystem.enableBlend();

context.drawGuiTexture(type.getTexture(hardcore, half, blinking), x, y, 9, 9);

RenderSystem.disableBlend();

    }



public int getMaxFruitExpansionHearts(PlayerEntity p){

StatusEffectInstance effect = p.getStatusEffect(ModEffects.FRUIT_EXTENSION);

 int a = effect.getAmplifier();

return a == 0 ? 13 : (10 + ((a + 1) * 7) / 2) - 1;

    }



}

И ModHeartType:

ModHeartType:
package net.yaksolo.ambulance.misc;



import net.minecraft.client.gui.hud.InGameHud;

import net.minecraft.entity.effect.StatusEffects;

import net.minecraft.entity.player.PlayerEntity;

import net.minecraft.util.Identifier;

import net.yaksolo.ambulance.effects.ModEffects;



public enum ModHeartType {

CONTAINER(Identifier.ofVanilla("hud/heart/container"), Identifier.ofVanilla("hud/heart/container_blinking"), Identifier.ofVanilla("hud/heart/container"), Identifier.ofVanilla("hud/heart/container_blinking"), Identifier.ofVanilla("hud/heart/container_hardcore"), Identifier.ofVanilla("hud/heart/container_hardcore_blinking"), Identifier.ofVanilla("hud/heart/container_hardcore"), Identifier.ofVanilla("hud/heart/container_hardcore_blinking")),

NORMAL(Identifier.ofVanilla("hud/heart/full"), Identifier.ofVanilla("hud/heart/full_blinking"), Identifier.ofVanilla("hud/heart/half"), Identifier.ofVanilla("hud/heart/half_blinking"), Identifier.ofVanilla("hud/heart/hardcore_full"), Identifier.ofVanilla("hud/heart/hardcore_full_blinking"), Identifier.ofVanilla("hud/heart/hardcore_half"), Identifier.ofVanilla("hud/heart/hardcore_half_blinking")),

POISONED(Identifier.ofVanilla("hud/heart/poisoned_full"), Identifier.ofVanilla("hud/heart/poisoned_full_blinking"), Identifier.ofVanilla("hud/heart/poisoned_half"), Identifier.ofVanilla("hud/heart/poisoned_half_blinking"), Identifier.ofVanilla("hud/heart/poisoned_hardcore_full"), Identifier.ofVanilla("hud/heart/poisoned_hardcore_full_blinking"), Identifier.ofVanilla("hud/heart/poisoned_hardcore_half"), Identifier.ofVanilla("hud/heart/poisoned_hardcore_half_blinking")),

WITHERED(Identifier.ofVanilla("hud/heart/withered_full"), Identifier.ofVanilla("hud/heart/withered_full_blinking"), Identifier.ofVanilla("hud/heart/withered_half"), Identifier.ofVanilla("hud/heart/withered_half_blinking"), Identifier.ofVanilla("hud/heart/withered_hardcore_full"), Identifier.ofVanilla("hud/heart/withered_hardcore_full_blinking"), Identifier.ofVanilla("hud/heart/withered_hardcore_half"), Identifier.ofVanilla("hud/heart/withered_hardcore_half_blinking")),

ABSORBING(Identifier.ofVanilla("hud/heart/absorbing_full"), Identifier.ofVanilla("hud/heart/absorbing_full_blinking"), Identifier.ofVanilla("hud/heart/absorbing_half"), Identifier.ofVanilla("hud/heart/absorbing_half_blinking"), Identifier.ofVanilla("hud/heart/absorbing_hardcore_full"), Identifier.ofVanilla("hud/heart/absorbing_hardcore_full_blinking"), Identifier.ofVanilla("hud/heart/absorbing_hardcore_half"), Identifier.ofVanilla("hud/heart/absorbing_hardcore_half_blinking")),

FROZEN(Identifier.ofVanilla("hud/heart/frozen_full"), Identifier.ofVanilla("hud/heart/frozen_full_blinking"), Identifier.ofVanilla("hud/heart/frozen_half"), Identifier.ofVanilla("hud/heart/frozen_half_blinking"), Identifier.ofVanilla("hud/heart/frozen_hardcore_full"), Identifier.ofVanilla("hud/heart/frozen_hardcore_full_blinking"), Identifier.ofVanilla("hud/heart/frozen_hardcore_half"), Identifier.ofVanilla("hud/heart/frozen_hardcore_half_blinking")),

FRUIT_EXTENSION(Identifier.ofVanilla("hud/heart/fruit_extension_full"), Identifier.ofVanilla("hud/heart/fruit_extension_full_blinking"), Identifier.ofVanilla("hud/heart/fruit_extension_half"), Identifier.ofVanilla("hud/heart/fruit_extension_half_blinking"), Identifier.ofVanilla("hud/heart/fruit_extension_hardcore_full"), Identifier.ofVanilla("hud/heart/fruit_extension_hardcore_full_blinking"), Identifier.ofVanilla("hud/heart/fruit_extension_hardcore_half"), Identifier.ofVanilla("hud/heart/fruit_extension_hardcore_half_blinking"));



private final Identifier fullTexture;

private final Identifier fullBlinkingTexture;

private final Identifier halfTexture;

private final Identifier halfBlinkingTexture;

private final Identifier hardcoreFullTexture;

private final Identifier hardcoreFullBlinkingTexture;

private final Identifier hardcoreHalfTexture;

private final Identifier hardcoreHalfBlinkingTexture;



private ModHeartType(final Identifier fullTexture, final Identifier fullBlinkingTexture, final Identifier halfTexture, final Identifier halfBlinkingTexture, final Identifier hardcoreFullTexture, final Identifier hardcoreFullBlinkingTexture, final Identifier hardcoreHalfTexture, final Identifier hardcoreHalfBlinkingTexture) {

this.fullTexture = fullTexture;

this.fullBlinkingTexture = fullBlinkingTexture;

this.halfTexture = halfTexture;

this.halfBlinkingTexture = halfBlinkingTexture;

this.hardcoreFullTexture = hardcoreFullTexture;

this.hardcoreFullBlinkingTexture = hardcoreFullBlinkingTexture;

this.hardcoreHalfTexture = hardcoreHalfTexture;

this.hardcoreHalfBlinkingTexture = hardcoreHalfBlinkingTexture;

    }



public Identifier getTexture(boolean hardcore, boolean half, boolean blinking) {

 if (!hardcore) {

 if (half) {

return blinking ? this.halfBlinkingTexture : this.halfTexture;

} else {

return blinking ? this.fullBlinkingTexture : this.fullTexture;

            }

} else if (half) {

return blinking ? this.hardcoreHalfBlinkingTexture : this.hardcoreHalfTexture;

} else {

return blinking ? this.hardcoreFullBlinkingTexture : this.hardcoreFullTexture;

        }

    }



public static ModHeartType fromPlayerState(PlayerEntity player) {

        ModHeartType heartType;

if (player.hasStatusEffect(StatusEffects.POISON)) {

heartType = POISONED;

} else if (player.hasStatusEffect(StatusEffects.WITHER)) {

heartType = WITHERED;

} else if (player.isFrozen()) {

heartType = FROZEN;

} else if (player.hasStatusEffect(ModEffects.FRUIT_EXTENSION)) {

heartType = FRUIT_EXTENSION;

} else {

heartType = NORMAL;

        }



 return heartType;

    }

}

Можно ли здесь же создать отдельные рамки для сердечек, КАК и с какого файла начать?
Часть кода делал не я, поэтому я не разбираюсь в его работе идеально, но по большей части понимаю
 
Последнее редактирование:
25
2
2
Что конкретно, не так?
Мне нужны отдельные Container для эффекта, на картинке выше я просто заменил ванильную текстуру, но оно заменяется и работает на все эффекты/их отсутствие, а мне нужно только на один конкретный
 
Сверху