Отрисовка изображения поверх всего интерфейса

Версия Minecraft
1.21.4
API
Forge
Не понимаю как в новых версиях Forge отрисовывать изображение поверх всего интерфейса если в старых версиях был RenderGuiOverlayEvent то в 1.21.x я так понял его выпилили и нормального аналога я так и не нашёл. Пробывал через GuiGraphics но там отрисовка исключительно внутри интерфейса.

Java:
package com.example.eternaljesus;

import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.world.entity.player.Player;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.ScreenEvent;
import net.minecraftforge.event.TickEvent;
import net.minecraftforge.event.entity.living.LivingUseTotemEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryObject;

import java.util.Random;

@Mod(eternaljesus.MOD_ID)
public class eternaljesus {

    public static final String MOD_ID = "eternaljesus";

    // Регистрация звуков через DeferredRegister
    public static final DeferredRegister<SoundEvent> SOUND_EVENTS =
            DeferredRegister.create(ForgeRegistries.SOUND_EVENTS, MOD_ID);

    // Регистрируем звук "jesus_sound" (файл: assets/eternaljesus/sounds/jesus_bell.ogg)
    public static final RegistryObject<SoundEvent> JESUS_SOUND =
            SOUND_EVENTS.register("jesus_sound",
                    () -> SoundEvent.createVariableRangeEvent(ResourceLocation.fromNamespaceAndPath(MOD_ID, "jesus_bell")));

    public eternaljesus(FMLJavaModLoadingContext context) {
        // Регистрируем звуки в шине событий мода
        SOUND_EVENTS.register(context.getModEventBus());
        System.out.println("EternalJesus mod initialized");
    }

    @Mod.EventBusSubscriber(modid = MOD_ID, bus = Mod.EventBusSubscriber.Bus.FORGE, value = Dist.CLIENT)
    public static class ClientEventHandler {

        // Таймеры для изображения и звука
        private static int displayTicks = 0;
        private static int soundTicks = 0;
        // Флаг активного эффекта
        private static boolean effectActive = false;
        // Флаг, позволяющий повторный запуск эффекта
        private static boolean canTriggerEffect = true;
        // Случайно выбранное изображение (для логики эффекта)
        private static ResourceLocation currentImage = null;
        // Генератор случайных чисел
        private static final Random RANDOM = new Random();
        // Массив изображений (для логики эффекта)
        private static final ResourceLocation[] JESUS_IMAGES = {
                ResourceLocation.fromNamespaceAndPath(MOD_ID, "textures/gui/jesus0.png"),
                ResourceLocation.fromNamespaceAndPath(MOD_ID, "textures/gui/jesus1.png"),
                ResourceLocation.fromNamespaceAndPath(MOD_ID, "textures/gui/jesus2.png"),
                ResourceLocation.fromNamespaceAndPath(MOD_ID, "textures/gui/jesus3.png"),
                ResourceLocation.fromNamespaceAndPath(MOD_ID, "textures/gui/jesus4.png")
        };

        @SubscribeEvent
        public static void onPlayerTick(TickEvent.PlayerTickEvent event) {
            if (event.phase != TickEvent.Phase.END) return;
            if (event.player.level().isClientSide()) {
                Player player = event.player;
                float health = player.getHealth();

                // Если здоровье низкое и эффект не активен, запускаем его
                if (health <= 2.0f && health > 0.0f && !effectActive && canTriggerEffect) {
                    triggerEffect(player);
                }

                // Обновляем таймеры эффекта
                if (effectActive) {
                    if (displayTicks > 0) {
                        displayTicks--;
                    }
                    if (soundTicks > 0) {
                        soundTicks--;
                    }
                    // Останавливаем эффект, когда таймеры исчерпаны
                    if (displayTicks <= 0 && soundTicks <= 0) {
                        effectActive = false;
                        currentImage = null;
                    }
                }

                // Разрешаем повторный запуск эффекта при восстановлении здоровья
                if (health > 2.0f) {
                    canTriggerEffect = true;
                }
            }
        }

        @SubscribeEvent
        public static void onTotemUse(LivingUseTotemEvent event) {
            if (event.getEntity() instanceof Player player && player.level().isClientSide()) {
                System.out.println("Totem used, triggering effect");
                triggerEffect(player);
            }
        }

        private static void triggerEffect(Player player) {
            System.out.println("Triggering effect for player: " + player.getName().getString());
            effectActive = true;
            canTriggerEffect = false;
            // Выбираем случайное изображение
            currentImage = JESUS_IMAGES[RANDOM.nextInt(JESUS_IMAGES.length)];
            System.out.println("Selected image: " + currentImage);
            // Проигрываем звук
            try {
                player.playSound(eternaljesus.JESUS_SOUND.get(), 4.0f, 1.0f);
                System.out.println("Sound played: jesus_bell");
            } catch (Exception e) {
                System.err.println("Failed to play sound: " + e.getMessage());
            }
            // Устанавливаем таймеры эффекта (примерно 10 секунд для изображения и 1 секунда для звука)
            displayTicks = 200;
            soundTicks = 20;
        }

        // Отрисовка оверлея поверх всех экранов происходит в событии ScreenEvent.Render.Post
        @SubscribeEvent
        public static void onScreenRender(ScreenEvent.Render.Post event) {
            if (effectActive && currentImage != null && displayTicks > 0) {
                Screen screen = event.getScreen();

                GuiGraphics guiGraphics = event.getGuiGraphics();
                int width = screen.width;
                int height = screen.height;

                RenderSystem.enableBlend();
                RenderSystem.defaultBlendFunc();
                RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
                // Отрисовываем текстуру (она будет отрисована поверх всех экранов)

                guiGraphics.blit(
                        rl -> RenderType.cutout(),
                        currentImage, // ресурс текстуры
                        0, 0,         // координаты на экране
                        0.0F, 0.0F,   // смещение текстуры (u, v)
                        width, height, // ширина и высота отрисовки
                        width, height  // реальные размеры текстуры
                );
                RenderSystem.disableBlend();
            }
        }
    }
}
 
Назад
Сверху