- 1
- 0
Не понимаю как в новых версиях 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();
}
}
}
}