2026-05-04 12:09:37 +02:00
/ *
* Decompiled with CFR 0 . 152 .
* /
package com.vinlanx.explosionoverhaul.client ;
import com.mojang.blaze3d.systems.RenderSystem ;
import com.vinlanx.explosionoverhaul.Config ;
import com.vinlanx.explosionoverhaul.ExplosionOverhaul ;
import com.vinlanx.explosionoverhaul.ModSounds ;
import com.vinlanx.explosionoverhaul.client.BackgroundParticle ;
import com.vinlanx.explosionoverhaul.client.ExplosionTextureManager ;
import com.vinlanx.explosionoverhaul.client.IntroMusicManager ;
import com.vinlanx.explosionoverhaul.client.SpriteSheetAnimator ;
import java.util.ArrayList ;
import java.util.List ;
import net.minecraft.client.Minecraft ;
import net.minecraft.client.gui.GuiGraphics ;
import net.minecraft.client.gui.screens.Screen ;
import net.minecraft.client.gui.screens.TitleScreen ;
import net.minecraft.client.resources.sounds.SimpleSoundInstance ;
import net.minecraft.client.resources.sounds.SoundInstance ;
import net.minecraft.network.chat.Component ;
import net.minecraft.resources.ResourceLocation ;
import net.minecraft.sounds.SoundEvent ;
import net.minecraft.util.Mth ;
import net.minecraft.util.RandomSource ;
public class FirstTimeScreen
extends Screen {
private static final ResourceLocation SPRITE_REALISTIC = ResourceLocation . fromNamespaceAndPath ( ( String ) " explosionoverhaul " , ( String ) " intro_gui/gui_screen_1.png " ) ;
private static final ResourceLocation SPRITE_VANILLA = ResourceLocation . fromNamespaceAndPath ( ( String ) " explosionoverhaul " , ( String ) " intro_gui/gui_screen_2.png " ) ;
private static final ResourceLocation SPRITE_REALISTIC_2 = ResourceLocation . fromNamespaceAndPath ( ( String ) " explosionoverhaul " , ( String ) " intro_gui/gui_screen_3.png " ) ;
private static final ResourceLocation SPRITE_STYLE_256 = ResourceLocation . fromNamespaceAndPath ( ( String ) " explosionoverhaul " , ( String ) " intro_gui/gui_screen_1.png " ) ;
private static final ResourceLocation SPRITE_STYLE_64 = ResourceLocation . fromNamespaceAndPath ( ( String ) " explosionoverhaul " , ( String ) " intro_gui/gui_screen_4.png " ) ;
private static final int FRAME_WIDTH = 854 ;
private static final int FRAME_HEIGHT = 480 ;
private static final int COLUMNS = 10 ;
private static final int ROWS = 10 ;
private static final int TOTAL_FRAMES = 61 ;
private static final int FPS = 15 ;
private static final int COLOR_BG = - 15921907 ;
private static final int COLOR_ACCENT_ORANGE = - 881908 ;
private static final int COLOR_ACCENT_RED = - 4250588 ;
private static final int COLOR_ACCENT_ROSE = - 2529701 ;
private static final int COLOR_ACCENT_DARK_RED = - 10939115 ;
private ScreenState currentState = ScreenState . CHOOSING_MODE ;
private Config . Client . ParticleRenderMode selectedRenderMode = null ;
private SpriteSheetAnimator realisticAnimator ;
private SpriteSheetAnimator vanillaAnimator ;
private SpriteSheetAnimator realistic2Animator ;
private SpriteSheetAnimator style256Animator ;
private SpriteSheetAnimator style64Animator ;
private boolean shouldSwitchState = false ;
private ScreenState nextState = ScreenState . CHOOSING_MODE ;
private int leftBoxX ;
private int leftBoxY ;
private int leftBoxW ;
private int leftBoxH ;
private int rightBoxX ;
private int rightBoxY ;
private int rightBoxW ;
private int rightBoxH ;
private int bottomBoxX ;
private int bottomBoxY ;
private int bottomBoxW ;
private int bottomBoxH ;
private int backButtonX ;
private int backButtonY ;
private int backButtonW ;
private int backButtonH ;
private boolean backButtonHovered = false ;
private float backButtonScale = 1 . 0f ;
private float leftHoverScale = 1 . 0f ;
private float rightHoverScale = 1 . 0f ;
private float bottomHoverScale = 1 . 0f ;
private static final float HOVER_SCALE_TARGET = 1 . 05f ;
private static final float SCALE_SPEED = 0 . 15f ;
private boolean leftHovered = false ;
private boolean rightHovered = false ;
private boolean bottomHovered = false ;
private long lastFrameTime = System . currentTimeMillis ( ) ;
private float transitionAlpha = 1 . 0f ;
private boolean isTransitioning = false ;
private static final float TRANSITION_DURATION = 0 . 8f ;
private float transitionTime = 0 . 0f ;
private List < BackgroundParticle > particles = new ArrayList < BackgroundParticle > ( ) ;
private RandomSource random = RandomSource . m_216327_ ( ) ;
private float backgroundTime = 0 . 0f ;
private IntroMusicManager musicManager ;
private static final float FADE_IN_DURATION = 5 . 0f ;
private static final float FADE_OUT_DURATION = 3 . 0f ;
private float fadeTime = 0 . 0f ;
private boolean fadingIn = true ;
private boolean fadingOut = false ;
private float screenAlpha = 0 . 0f ;
private float fadeOutStartAlpha = 1 . 0f ;
private long fadeOutStartMillis = - 1L ;
private static final long FORCE_CLOSE_BUFFER_MS = 2000L ;
public FirstTimeScreen ( ) {
2026-05-04 13:33:41 +02:00
super ( ( Component ) Component . literal ( ( String ) " First Time Setup " ) ) ;
2026-05-04 12:09:37 +02:00
}
protected void m_7856_ ( ) {
int i ;
int displayHeight ;
int displayWidth ;
super . m_7856_ ( ) ;
this . fadingIn = true ;
this . fadingOut = false ;
this . fadeTime = 0 . 0f ;
this . screenAlpha = 0 . 0f ;
this . lastFrameTime = System . currentTimeMillis ( ) ;
this . leftHovered = false ;
this . rightHovered = false ;
this . bottomHovered = false ;
this . backButtonHovered = false ;
this . backButtonScale = 1 . 0f ;
this . musicManager = IntroMusicManager . getInstance ( ) ;
if ( this . currentState = = ScreenState . CHOOSING_MODE ) {
this . realisticAnimator = new SpriteSheetAnimator ( SPRITE_REALISTIC , 854 , 480 , 10 , 10 , 61 , 15 ) ;
this . vanillaAnimator = new SpriteSheetAnimator ( SPRITE_VANILLA , 854 , 480 , 10 , 10 , 61 , 15 ) ;
this . realistic2Animator = new SpriteSheetAnimator ( SPRITE_REALISTIC_2 , 854 , 480 , 10 , 10 , 61 , 15 ) ;
this . realisticAnimator . load ( ) ;
this . vanillaAnimator . load ( ) ;
this . realistic2Animator . load ( ) ;
} else if ( this . currentState = = ScreenState . CHOOSING_STYLE ) {
this . style256Animator = new SpriteSheetAnimator ( SPRITE_STYLE_256 , 854 , 480 , 10 , 10 , 61 , 15 ) ;
this . style64Animator = new SpriteSheetAnimator ( SPRITE_STYLE_64 , 854 , 480 , 10 , 10 , 61 , 15 ) ;
this . style256Animator . load ( ) ;
this . style64Animator . load ( ) ;
ExplosionOverhaul . LOGGER . warn ( " Style selection screen loaded. Ensure gui_screen_4.png and gui_screen_5.png exist in intro_gui folder for proper animations. " ) ;
}
int maxWidth = ( int ) ( ( float ) this . f_96543_ * 0 . 3f ) ;
int maxHeight = ( int ) ( ( float ) this . f_96544_ * 0 . 44f ) ;
float aspectRatio = 1 . 7777778f ;
if ( ( float ) maxWidth / aspectRatio < = ( float ) maxHeight ) {
displayWidth = maxWidth ;
displayHeight = ( int ) ( ( float ) maxWidth / aspectRatio ) ;
} else {
displayHeight = maxHeight ;
displayWidth = ( int ) ( ( float ) maxHeight * aspectRatio ) ;
}
if ( this . currentState = = ScreenState . CHOOSING_MODE ) {
gap = ( int ) ( ( float ) this . f_96543_ * 0 . 03f ) ;
totalWidth = displayWidth * 2 + gap ;
startX = ( this . f_96543_ - totalWidth ) / 2 ;
startY = ( this . f_96544_ - displayHeight ) / 2 - ( int ) ( ( float ) this . f_96544_ * 0 . 15f ) ;
this . leftBoxX = startX ;
this . leftBoxY = startY ;
this . leftBoxW = displayWidth ;
this . leftBoxH = displayHeight ;
this . rightBoxX = startX + displayWidth + gap ;
this . rightBoxY = startY ;
this . rightBoxW = displayWidth ;
this . rightBoxH = displayHeight ;
this . bottomBoxX = ( this . f_96543_ - displayWidth ) / 2 ;
this . bottomBoxY = startY + displayHeight + ( int ) ( ( float ) this . f_96544_ * 0 . 08f ) ;
this . bottomBoxW = displayWidth ;
this . bottomBoxH = displayHeight ;
} else if ( this . currentState = = ScreenState . CHOOSING_STYLE ) {
gap = ( int ) ( ( float ) this . f_96543_ * 0 . 03f ) ;
totalWidth = displayWidth * 2 + gap ;
startX = ( this . f_96543_ - totalWidth ) / 2 ;
startY = ( this . f_96544_ - displayHeight ) / 2 ;
this . leftBoxX = startX ;
this . leftBoxY = startY ;
this . leftBoxW = displayWidth ;
this . leftBoxH = displayHeight ;
this . rightBoxX = startX + displayWidth + gap ;
this . rightBoxY = startY ;
this . rightBoxW = displayWidth ;
this . rightBoxH = displayHeight ;
this . bottomBoxX = 0 ;
this . bottomBoxY = 0 ;
this . bottomBoxW = 0 ;
this . bottomBoxH = 0 ;
this . backButtonW = ( int ) ( ( float ) this . f_96543_ * 0 . 1f ) ;
this . backButtonH = ( int ) ( ( float ) this . f_96544_ * 0 . 08f ) ;
this . backButtonX = ( int ) ( ( float ) this . f_96543_ * 0 . 02f ) ;
this . backButtonY = this . f_96544_ - this . backButtonH - ( int ) ( ( float ) this . f_96544_ * 0 . 02f ) ;
}
for ( i = 0 ; i < 40 ; + + i ) {
this . particles . add ( BackgroundParticle . createSpark ( this . random , this . f_96543_ , this . f_96544_ ) ) ;
}
for ( i = 0 ; i < 15 ; + + i ) {
this . particles . add ( BackgroundParticle . createEmber ( this . random , this . f_96543_ , this . f_96544_ ) ) ;
}
for ( i = 0 ; i < 8 ; + + i ) {
this . particles . add ( BackgroundParticle . createSmoke ( this . random , this . f_96543_ , this . f_96544_ ) ) ;
}
}
public void m_86600_ ( ) {
float progress ;
super . m_86600_ ( ) ;
long currentTime = System . currentTimeMillis ( ) ;
float rawDeltaTime = ( float ) ( currentTime - this . lastFrameTime ) / 1000 . 0f ;
this . lastFrameTime = currentTime ;
float deltaTime = Math . min ( rawDeltaTime , 0 . 1f ) ;
this . backgroundTime + = deltaTime ;
if ( this . isTransitioning ) {
this . transitionTime + = deltaTime ;
progress = Math . min ( 1 . 0f , this . transitionTime / 0 . 8f ) ;
if ( this . transitionTime < 0 . 4f ) {
this . transitionAlpha = 1 . 0f - progress * 2 . 0f ;
} else {
this . transitionAlpha = ( progress - 0 . 5f ) * 2 . 0f ;
if ( this . transitionTime > = 0 . 4f & & ! this . shouldSwitchState ) {
this . shouldSwitchState = true ;
if ( this . currentState = = ScreenState . CHOOSING_MODE ) {
if ( this . realisticAnimator ! = null ) {
this . realisticAnimator . close ( ) ;
}
if ( this . vanillaAnimator ! = null ) {
this . vanillaAnimator . close ( ) ;
}
if ( this . realistic2Animator ! = null ) {
this . realistic2Animator . close ( ) ;
}
this . nextState = ScreenState . CHOOSING_STYLE ;
} else if ( this . currentState = = ScreenState . CHOOSING_STYLE ) {
if ( this . style256Animator ! = null ) {
this . style256Animator . close ( ) ;
}
if ( this . style64Animator ! = null ) {
this . style64Animator . close ( ) ;
}
this . nextState = ScreenState . CHOOSING_MODE ;
}
this . currentState = this . nextState ;
this . m_7856_ ( ) ;
}
}
if ( this . transitionTime > = 0 . 8f ) {
this . isTransitioning = false ;
this . transitionAlpha = 1 . 0f ;
this . transitionTime = 0 . 0f ;
this . shouldSwitchState = false ;
}
}
if ( this . fadingIn ) {
this . fadeTime + = deltaTime ;
progress = Math . min ( 1 . 0f , this . fadeTime / 5 . 0f ) ;
this . screenAlpha = this . easeOutCubic ( progress ) ;
if ( this . fadeTime > = 5 . 0f ) {
this . fadingIn = false ;
this . screenAlpha = 1 . 0f ;
}
} else if ( this . fadingOut ) {
long threshold ;
long elapsed ;
this . fadeTime + = deltaTime ;
progress = Math . min ( 1 . 0f , this . fadeTime / 3 . 0f ) ;
this . screenAlpha = this . fadeOutStartAlpha * ( 1 . 0f - this . easeInCubic ( progress ) ) ;
if ( this . fadeTime > = 3 . 0f ) {
boolean musicStillFading ;
boolean bl = musicStillFading = this . musicManager ! = null & & this . musicManager . isFadingOut ( ) ;
if ( ! musicStillFading ) {
ExplosionOverhaul . LOGGER . info ( " Screen and music fade out complete. Opening TitleScreen. " ) ;
this . cleanupAnimators ( ) ;
2026-05-04 13:33:41 +02:00
Minecraft . getInstance ( ) . m_91152_ ( ( Screen ) new TitleScreen ( ) ) ;
2026-05-04 12:09:37 +02:00
} else {
ExplosionOverhaul . LOGGER . info ( " Waiting for music to finish fading... " ) ;
}
}
if ( this . fadeOutStartMillis > 0L & & ( elapsed = System . currentTimeMillis ( ) - this . fadeOutStartMillis ) > ( threshold = 5000L ) ) {
ExplosionOverhaul . LOGGER . warn ( " Fade out timeout exceeded ({} ms). Forcing close and opening TitleScreen. " , ( Object ) elapsed ) ;
if ( this . musicManager ! = null ) {
this . musicManager . stop ( ) ;
}
this . cleanupAnimators ( ) ;
this . fadingOut = false ;
this . fadeOutStartMillis = - 1L ;
2026-05-04 13:33:41 +02:00
Minecraft . getInstance ( ) . m_91152_ ( ( Screen ) new TitleScreen ( ) ) ;
2026-05-04 12:09:37 +02:00
return ;
}
}
if ( this . musicManager ! = null ) {
this . musicManager . tick ( deltaTime ) ;
}
if ( this . currentState = = ScreenState . CHOOSING_MODE ) {
if ( this . realisticAnimator ! = null ) {
this . realisticAnimator . tick ( deltaTime ) ;
}
if ( this . vanillaAnimator ! = null ) {
this . vanillaAnimator . tick ( deltaTime ) ;
}
if ( this . realistic2Animator ! = null ) {
this . realistic2Animator . tick ( deltaTime ) ;
}
} else if ( this . currentState = = ScreenState . CHOOSING_STYLE ) {
if ( this . style256Animator ! = null ) {
this . style256Animator . tick ( deltaTime ) ;
}
if ( this . style64Animator ! = null ) {
this . style64Animator . tick ( deltaTime ) ;
}
}
this . leftHoverScale = Mth . m_14179_ ( ( float ) 0 . 15f , ( float ) this . leftHoverScale , ( float ) ( this . leftHovered ? 1 . 05f : 1 . 0f ) ) ;
this . rightHoverScale = Mth . m_14179_ ( ( float ) 0 . 15f , ( float ) this . rightHoverScale , ( float ) ( this . rightHovered ? 1 . 05f : 1 . 0f ) ) ;
this . bottomHoverScale = Mth . m_14179_ ( ( float ) 0 . 15f , ( float ) this . bottomHoverScale , ( float ) ( this . bottomHovered ? 1 . 05f : 1 . 0f ) ) ;
this . particles . removeIf ( p - > {
p . tick ( deltaTime ) ;
return p . isDead ( ) | | p . x < - 50 . 0f | | p . x > ( float ) ( this . f_96543_ + 50 ) | | p . y < - 50 . 0f | | p . y > ( float ) ( this . f_96544_ + 50 ) ;
} ) ;
if ( this . random . m_188501_ ( ) < 0 . 15f ) {
this . particles . add ( BackgroundParticle . createSpark ( this . random , this . f_96543_ , this . f_96544_ ) ) ;
}
if ( this . random . m_188501_ ( ) < 0 . 05f ) {
this . particles . add ( BackgroundParticle . createEmber ( this . random , this . f_96543_ , this . f_96544_ ) ) ;
}
if ( this . random . m_188501_ ( ) < 0 . 02f ) {
this . particles . add ( BackgroundParticle . createSmoke ( this . random , this . f_96543_ , this . f_96544_ ) ) ;
}
if ( this . random . m_188501_ ( ) < 0 . 01f ) {
this . particles . add ( BackgroundParticle . createFlash ( this . random , this . f_96543_ , this . f_96544_ ) ) ;
}
}
private void cleanupAnimators ( ) {
if ( this . realisticAnimator ! = null ) {
this . realisticAnimator . close ( ) ;
}
if ( this . vanillaAnimator ! = null ) {
this . vanillaAnimator . close ( ) ;
}
if ( this . realistic2Animator ! = null ) {
this . realistic2Animator . close ( ) ;
}
if ( this . style256Animator ! = null ) {
this . style256Animator . close ( ) ;
}
if ( this . style64Animator ! = null ) {
this . style64Animator . close ( ) ;
}
}
public void m_88315_ ( GuiGraphics graphics , int mouseX , int mouseY , float partialTick ) {
2026-05-04 13:33:41 +02:00
graphics . fill ( 0 , 0 , this . f_96543_ , this . f_96544_ , - 16777216 ) ;
2026-05-04 12:09:37 +02:00
if ( this . screenAlpha < 0 . 01f ) {
return ;
}
RenderSystem . enableBlend ( ) ;
RenderSystem . defaultBlendFunc ( ) ;
float renderAlpha = this . screenAlpha * this . transitionAlpha ;
RenderSystem . setShaderColor ( ( float ) 1 . 0f , ( float ) 1 . 0f , ( float ) 1 . 0f , ( float ) renderAlpha ) ;
graphics . m_280168_ ( ) . m_85836_ ( ) ;
this . renderCinematicBackground ( graphics , partialTick , renderAlpha ) ;
if ( this . currentState = = ScreenState . CHOOSING_MODE ) {
this . renderModeSelection ( graphics , mouseX , mouseY , renderAlpha ) ;
} else if ( this . currentState = = ScreenState . CHOOSING_STYLE ) {
this . renderStyleSelection ( graphics , mouseX , mouseY , renderAlpha ) ;
}
graphics . m_280168_ ( ) . m_85849_ ( ) ;
RenderSystem . setShaderColor ( ( float ) 1 . 0f , ( float ) 1 . 0f , ( float ) 1 . 0f , ( float ) 1 . 0f ) ;
super . m_88315_ ( graphics , mouseX , mouseY , partialTick ) ;
}
private void renderModeSelection ( GuiGraphics graphics , int mouseX , int mouseY , float renderAlpha ) {
String title = " Choose Your Explosion Style " ;
2026-05-04 13:33:41 +02:00
int titleWidth = this . f_96547_ . width ( title ) ;
2026-05-04 12:09:37 +02:00
int titleX = ( this . f_96543_ - titleWidth ) / 2 ;
int titleY = this . leftBoxY - 40 ;
int titleAlpha = ( int ) ( renderAlpha * 255 . 0f ) < < 24 ;
graphics . m_280056_ ( this . f_96547_ , title , titleX + 2 , titleY + 2 , 0xF28B0C | ( int ) ( 64 . 0f * renderAlpha ) < < 24 , false ) ;
graphics . m_280056_ ( this . f_96547_ , title , titleX + 1 , titleY + 1 , 0xF28B0C | ( int ) ( 128 . 0f * renderAlpha ) < < 24 , false ) ;
graphics . m_280056_ ( this . f_96547_ , title , titleX , titleY , 0xF28B0C | titleAlpha , true ) ;
String subtitle = " You can change this anytime in the config " ;
2026-05-04 13:33:41 +02:00
int subtitleWidth = this . f_96547_ . width ( subtitle ) ;
2026-05-04 12:09:37 +02:00
graphics . m_280056_ ( this . f_96547_ , subtitle , ( this . f_96543_ - subtitleWidth ) / 2 , titleY + 15 , 0xCCCCCC | titleAlpha , false ) ;
String psNote = " P.S. Colors in the game may differ from the animations because compression has altered the colors " ;
2026-05-04 13:33:41 +02:00
int psWidth = this . f_96547_ . width ( psNote ) ;
2026-05-04 12:09:37 +02:00
int psColor = 0x999999 | titleAlpha ;
graphics . m_280056_ ( this . f_96547_ , psNote , ( this . f_96543_ - psWidth ) / 2 , titleY + 30 , psColor , false ) ;
if ( ! this . isTransitioning ) {
boolean wasLeftHovered = this . leftHovered ;
boolean wasRightHovered = this . rightHovered ;
boolean wasBottomHovered = this . bottomHovered ;
this . leftHovered = this . isMouseOver ( mouseX , mouseY , this . leftBoxX , this . leftBoxY , this . leftBoxW , this . leftBoxH ) ;
this . rightHovered = this . isMouseOver ( mouseX , mouseY , this . rightBoxX , this . rightBoxY , this . rightBoxW , this . rightBoxH ) ;
this . bottomHovered = this . isMouseOver ( mouseX , mouseY , this . bottomBoxX , this . bottomBoxY , this . bottomBoxW , this . bottomBoxH ) ;
if ( this . leftHovered & & ! wasLeftHovered ) {
this . realisticAnimator . reset ( ) ;
this . realisticAnimator . play ( ) ;
} else if ( ! this . leftHovered & & wasLeftHovered ) {
this . realisticAnimator . reset ( ) ;
}
if ( this . rightHovered & & ! wasRightHovered ) {
this . vanillaAnimator . reset ( ) ;
this . vanillaAnimator . play ( ) ;
} else if ( ! this . rightHovered & & wasRightHovered ) {
this . vanillaAnimator . reset ( ) ;
}
if ( this . bottomHovered & & ! wasBottomHovered ) {
this . realistic2Animator . reset ( ) ;
this . realistic2Animator . play ( ) ;
} else if ( ! this . bottomHovered & & wasBottomHovered ) {
this . realistic2Animator . reset ( ) ;
}
}
this . renderBox ( graphics , this . leftBoxX , this . leftBoxY , this . leftBoxW , this . leftBoxH , this . leftHoverScale , this . realisticAnimator , " REALISTIC " , this . leftHovered , - 881908 , renderAlpha ) ;
this . renderBox ( graphics , this . rightBoxX , this . rightBoxY , this . rightBoxW , this . rightBoxH , this . rightHoverScale , this . vanillaAnimator , " VANILLA-LIKE " , this . rightHovered , - 4250588 , renderAlpha ) ;
this . renderBox ( graphics , this . bottomBoxX , this . bottomBoxY , this . bottomBoxW , this . bottomBoxH , this . bottomHoverScale , this . realistic2Animator , " REALISTIC 2 " , this . bottomHovered , - 2529701 , renderAlpha ) ;
}
private void renderStyleSelection ( GuiGraphics graphics , int mouseX , int mouseY , float renderAlpha ) {
String title = " Choose Render Style " ;
2026-05-04 13:33:41 +02:00
int titleWidth = this . f_96547_ . width ( title ) ;
2026-05-04 12:09:37 +02:00
int titleX = ( this . f_96543_ - titleWidth ) / 2 ;
int titleY = this . leftBoxY - 40 ;
int titleAlpha = ( int ) ( renderAlpha * 255 . 0f ) < < 24 ;
graphics . m_280056_ ( this . f_96547_ , title , titleX + 2 , titleY + 2 , 0xF28B0C | ( int ) ( 64 . 0f * renderAlpha ) < < 24 , false ) ;
graphics . m_280056_ ( this . f_96547_ , title , titleX + 1 , titleY + 1 , 0xF28B0C | ( int ) ( 128 . 0f * renderAlpha ) < < 24 , false ) ;
graphics . m_280056_ ( this . f_96547_ , title , titleX , titleY , 0xF28B0C | titleAlpha , true ) ;
String subtitle = " Higher quality requires more VRAM " ;
2026-05-04 13:33:41 +02:00
int subtitleWidth = this . f_96547_ . width ( subtitle ) ;
2026-05-04 12:09:37 +02:00
graphics . m_280056_ ( this . f_96547_ , subtitle , ( this . f_96543_ - subtitleWidth ) / 2 , titleY + 15 , 0xCCCCCC | titleAlpha , false ) ;
if ( ! this . isTransitioning ) {
boolean wasLeftHovered = this . leftHovered ;
boolean wasRightHovered = this . rightHovered ;
boolean wasBackHovered = this . backButtonHovered ;
this . leftHovered = this . isMouseOver ( mouseX , mouseY , this . leftBoxX , this . leftBoxY , this . leftBoxW , this . leftBoxH ) ;
this . rightHovered = this . isMouseOver ( mouseX , mouseY , this . rightBoxX , this . rightBoxY , this . rightBoxW , this . rightBoxH ) ;
this . backButtonHovered = this . isMouseOver ( mouseX , mouseY , this . backButtonX , this . backButtonY , this . backButtonW , this . backButtonH ) ;
this . bottomHovered = false ;
if ( this . leftHovered & & ! wasLeftHovered ) {
this . style256Animator . reset ( ) ;
this . style256Animator . play ( ) ;
} else if ( ! this . leftHovered & & wasLeftHovered ) {
this . style256Animator . reset ( ) ;
}
if ( this . rightHovered & & ! wasRightHovered ) {
this . style64Animator . reset ( ) ;
this . style64Animator . play ( ) ;
} else if ( ! this . rightHovered & & wasRightHovered ) {
this . style64Animator . reset ( ) ;
}
if ( this . backButtonHovered & & ! wasBackHovered | | this . backButtonHovered | | wasBackHovered ) {
// empty if block
}
}
this . backButtonScale = Mth . m_14179_ ( ( float ) 0 . 15f , ( float ) this . backButtonScale , ( float ) ( this . backButtonHovered ? 1 . 05f : 1 . 0f ) ) ;
this . renderBox ( graphics , this . leftBoxX , this . leftBoxY , this . leftBoxW , this . leftBoxH , this . leftHoverScale , this . style256Animator , " 256 PIXELS " , this . leftHovered , - 881908 , renderAlpha ) ;
this . renderBox ( graphics , this . rightBoxX , this . rightBoxY , this . rightBoxW , this . rightBoxH , this . rightHoverScale , this . style64Animator , " 64 PIXELS " , this . rightHovered , - 4250588 , renderAlpha ) ;
this . renderBackButton ( graphics , renderAlpha ) ;
}
private void renderBox ( GuiGraphics graphics , int x , int y , int width , int height , float scale , SpriteSheetAnimator animator , String label , boolean hovered , int accentColor , float alpha ) {
graphics . m_280168_ ( ) . m_85836_ ( ) ;
int centerX = x + width / 2 ;
int centerY = y + height / 2 ;
graphics . m_280168_ ( ) . m_252880_ ( ( float ) centerX , ( float ) centerY , 0 . 0f ) ;
graphics . m_280168_ ( ) . m_85841_ ( scale , scale , 1 . 0f ) ;
graphics . m_280168_ ( ) . m_252880_ ( ( float ) ( - width / 2 ) , ( float ) ( - height / 2 ) , 0 . 0f ) ;
if ( hovered ) {
int glowSize = 4 ;
int glowAlpha = ( int ) ( 128 . 0f * alpha ) < < 24 ;
2026-05-04 13:33:41 +02:00
graphics . fill ( - glowSize , - glowSize , width + glowSize , height + glowSize , accentColor & 0xFFFFFF | glowAlpha ) ;
2026-05-04 12:09:37 +02:00
}
int bgAlpha = ( int ) ( 255 . 0f * alpha ) < < 24 ;
2026-05-04 13:33:41 +02:00
graphics . fill ( 0 , 0 , width , height , 0x591515 | bgAlpha ) ;
2026-05-04 12:09:37 +02:00
if ( animator ! = null & & animator . getTextureLocation ( ) ! = null ) {
RenderSystem . enableBlend ( ) ;
RenderSystem . defaultBlendFunc ( ) ;
RenderSystem . setShaderColor ( ( float ) 1 . 0f , ( float ) 1 . 0f , ( float ) 1 . 0f , ( float ) alpha ) ;
RenderSystem . setShaderTexture ( ( int ) 0 , ( ResourceLocation ) animator . getTextureLocation ( ) ) ;
graphics . m_280163_ ( animator . getTextureLocation ( ) , 0 , 0 , 0 . 0f , 0 . 0f , width , height , width , height ) ;
RenderSystem . setShaderColor ( ( float ) 1 . 0f , ( float ) 1 . 0f , ( float ) 1 . 0f , ( float ) 1 . 0f ) ;
} else {
int placeholderTextColor = ( int ) ( 150 . 0f * alpha ) < < 24 | 0xFFFFFFFF ;
String placeholder = " [Image not found] " ;
2026-05-04 13:33:41 +02:00
int placeholderWidth = this . f_96547_ . width ( placeholder ) ;
2026-05-04 12:09:37 +02:00
graphics . m_280056_ ( this . f_96547_ , placeholder , ( width - placeholderWidth ) / 2 , height / 2 - 5 , placeholderTextColor , false ) ;
}
int borderColor = hovered ? accentColor : - 2529701 ;
int borderAlpha = ( int ) ( 255 . 0f * alpha ) < < 24 ;
int fadedBorderColor = borderColor & 0xFFFFFF | borderAlpha ;
2026-05-04 13:33:41 +02:00
graphics . fill ( 0 , 0 , width , 2 , fadedBorderColor ) ;
graphics . fill ( 0 , height - 2 , width , height , fadedBorderColor ) ;
graphics . fill ( 0 , 0 , 2 , height , fadedBorderColor ) ;
graphics . fill ( width - 2 , 0 , width , height , fadedBorderColor ) ;
2026-05-04 12:09:37 +02:00
graphics . m_280168_ ( ) . m_85849_ ( ) ;
int labelAlpha = ( int ) ( 255 . 0f * alpha ) < < 24 ;
int labelColor = hovered ? accentColor : - 1 ;
int fadedLabelColor = labelColor & 0xFFFFFF | labelAlpha ;
2026-05-04 13:33:41 +02:00
int labelWidth = this . f_96547_ . width ( label ) ;
2026-05-04 12:09:37 +02:00
graphics . m_280056_ ( this . f_96547_ , label , x + ( width - labelWidth ) / 2 , y + height + 10 , fadedLabelColor , true ) ;
}
public boolean m_6375_ ( double mouseX , double mouseY , int button ) {
if ( this . fadingOut | | this . isTransitioning ) {
return true ;
}
if ( button = = 0 ) {
if ( this . currentState = = ScreenState . CHOOSING_MODE ) {
if ( this . isMouseOver ( ( int ) mouseX , ( int ) mouseY , this . leftBoxX , this . leftBoxY , this . leftBoxW , this . leftBoxH ) ) {
this . selectRealisticMode ( ) ;
return true ;
}
if ( this . isMouseOver ( ( int ) mouseX , ( int ) mouseY , this . rightBoxX , this . rightBoxY , this . rightBoxW , this . rightBoxH ) ) {
this . selectVanillaLike ( ) ;
return true ;
}
if ( this . isMouseOver ( ( int ) mouseX , ( int ) mouseY , this . bottomBoxX , this . bottomBoxY , this . bottomBoxW , this . bottomBoxH ) ) {
this . selectRealistic2Mode ( ) ;
return true ;
}
} else if ( this . currentState = = ScreenState . CHOOSING_STYLE ) {
if ( this . isMouseOver ( ( int ) mouseX , ( int ) mouseY , this . leftBoxX , this . leftBoxY , this . leftBoxW , this . leftBoxH ) ) {
this . selectStyle256 ( ) ;
return true ;
}
if ( this . isMouseOver ( ( int ) mouseX , ( int ) mouseY , this . rightBoxX , this . rightBoxY , this . rightBoxW , this . rightBoxH ) ) {
this . selectStyle64 ( ) ;
return true ;
}
if ( this . isMouseOver ( ( int ) mouseX , ( int ) mouseY , this . backButtonX , this . backButtonY , this . backButtonW , this . backButtonH ) ) {
this . goBack ( ) ;
return true ;
}
}
}
return super . m_6375_ ( mouseX , mouseY , button ) ;
}
private void selectRealisticMode ( ) {
this . playButtonSound ( ) ;
this . selectedRenderMode = Config . Client . ParticleRenderMode . REALISTIC ;
this . isTransitioning = true ;
this . transitionTime = 0 . 0f ;
this . transitionAlpha = 1 . 0f ;
}
private void selectRealistic2Mode ( ) {
this . playButtonSound ( ) ;
this . selectedRenderMode = Config . Client . ParticleRenderMode . REALISTIC_2 ;
this . isTransitioning = true ;
this . transitionTime = 0 . 0f ;
this . transitionAlpha = 1 . 0f ;
}
private void selectStyle256 ( ) {
this . playButtonSound ( ) ;
Config . CLIENT . glowTextureQuality . set ( ( Object ) Config . Client . GlowTextureQuality . QUALITY_256 ) ;
Config . CLIENT . particleRenderMode . set ( ( Object ) this . selectedRenderMode ) ;
this . saveAndClose ( ) ;
}
private void selectStyle64 ( ) {
this . playButtonSound ( ) ;
Config . CLIENT . glowTextureQuality . set ( ( Object ) Config . Client . GlowTextureQuality . QUALITY_64 ) ;
Config . CLIENT . particleRenderMode . set ( ( Object ) this . selectedRenderMode ) ;
this . saveAndClose ( ) ;
}
private boolean isMouseOver ( int mouseX , int mouseY , int x , int y , int width , int height ) {
return mouseX > = x & & mouseX < = x + width & & mouseY > = y & & mouseY < = y + height ;
}
private void selectVanillaLike ( ) {
this . playButtonSound ( ) ;
Config . CLIENT . particleRenderMode . set ( ( Object ) Config . Client . ParticleRenderMode . VANILA ) ;
this . saveAndClose ( ) ;
}
private void goBack ( ) {
this . playButtonSound ( ) ;
this . isTransitioning = true ;
this . transitionTime = 0 . 0f ;
this . transitionAlpha = 1 . 0f ;
this . selectedRenderMode = null ;
}
private void saveAndClose ( ) {
Config . CLIENT . firstLaunchComplete . set ( ( Object ) true ) ;
Config . CLIENT_SPEC . save ( ) ;
ExplosionTextureManager . getInstance ( ) . reload ( ) ;
if ( this . musicManager ! = null & & this . musicManager . isPlaying ( ) ) {
ExplosionOverhaul . LOGGER . info ( " Starting music and screen fade out (duration: {} seconds) " , ( Object ) Float . valueOf ( 3 . 0f ) ) ;
this . musicManager . startFadeOut ( ) ;
}
if ( this . fadingIn ) {
this . fadingIn = false ;
ExplosionOverhaul . LOGGER . info ( " Interrupting fade in (was at {:.1f}%) to start fade out from current alpha " , ( Object ) Float . valueOf ( this . screenAlpha * 100 . 0f ) ) ;
}
this . fadeOutStartAlpha = this . screenAlpha ;
this . fadingOut = true ;
this . fadeTime = 0 . 0f ;
this . fadeOutStartMillis = System . currentTimeMillis ( ) ;
}
private void renderCinematicBackground ( GuiGraphics graphics , float partialTick , float globalAlpha ) {
int i ;
int bgAlpha1 ;
int bgColor1 = bgAlpha1 = ( int ) ( 255 . 0f * globalAlpha ) < < 24 ;
int bgColor2 = 0xD0D0D | bgAlpha1 ;
graphics . m_280024_ ( 0 , 0 , this . f_96543_ , this . f_96544_ / 2 , bgColor1 , bgColor2 ) ;
graphics . m_280024_ ( 0 , this . f_96544_ / 2 , this . f_96543_ , this . f_96544_ , bgColor2 , bgColor1 ) ;
RenderSystem . enableBlend ( ) ;
RenderSystem . defaultBlendFunc ( ) ;
for ( BackgroundParticle p : this . particles ) {
float particleAlpha = p . getAlpha ( ) ;
float finalAlpha = particleAlpha * globalAlpha ;
int colorWithAlpha = p . color & 0xFFFFFF | ( int ) ( finalAlpha * 255 . 0f ) < < 24 ;
switch ( p . type ) {
case SPARK : {
float sparkLen = p . size * 3 . 0f ;
float sparkAngle = ( float ) Math . atan2 ( p . vy , p . vx ) ;
int ex = ( int ) ( ( double ) p . x + Math . cos ( sparkAngle ) * ( double ) sparkLen ) ;
int ey = ( int ) ( ( double ) p . y + Math . sin ( sparkAngle ) * ( double ) sparkLen ) ;
this . drawLine ( graphics , ( int ) p . x , ( int ) p . y , ex , ey , colorWithAlpha ) ;
break ;
}
case EMBER : {
int emberSize = ( int ) p . size ;
2026-05-04 13:33:41 +02:00
graphics . fill ( ( int ) p . x - emberSize , ( int ) p . y - emberSize , ( int ) p . x + emberSize , ( int ) p . y + emberSize , colorWithAlpha ) ;
2026-05-04 12:09:37 +02:00
break ;
}
case FLASH : {
int flashSize = ( int ) ( p . size * 0 . 7f ) ;
int flashColor = colorWithAlpha & 0xFFFFFF | ( int ) ( finalAlpha * 180 . 0f ) < < 24 ;
2026-05-04 13:33:41 +02:00
graphics . fill ( ( int ) p . x - flashSize , ( int ) p . y - flashSize , ( int ) p . x + flashSize , ( int ) p . y + flashSize , flashColor ) ;
2026-05-04 12:09:37 +02:00
break ;
}
case SMOKE : {
int smokeSize = ( int ) p . size ;
int smokeColor = colorWithAlpha & 0xFFFFFF | ( int ) ( finalAlpha * 60 . 0f ) < < 24 ;
2026-05-04 13:33:41 +02:00
graphics . fill ( ( int ) p . x - smokeSize , ( int ) p . y - smokeSize , ( int ) p . x + smokeSize , ( int ) p . y + smokeSize , smokeColor ) ;
2026-05-04 12:09:37 +02:00
}
}
}
int vignetteSteps = 15 ;
for ( i = 0 ; i < vignetteSteps ; + + i ) {
float ratio = ( float ) i / ( float ) vignetteSteps ;
int vignetteAlpha = ( int ) ( ratio * ratio * 180 . 0f * globalAlpha ) ;
int vignetteColor = vignetteAlpha < < 24 ;
int thickness = 4 ;
2026-05-04 13:33:41 +02:00
graphics . fill ( 0 , i * thickness , this . f_96543_ , ( i + 1 ) * thickness , vignetteColor ) ;
graphics . fill ( 0 , this . f_96544_ - ( i + 1 ) * thickness , this . f_96543_ , this . f_96544_ - i * thickness , vignetteColor ) ;
graphics . fill ( i * thickness , 0 , ( i + 1 ) * thickness , this . f_96544_ , vignetteColor ) ;
graphics . fill ( this . f_96543_ - ( i + 1 ) * thickness , 0 , this . f_96543_ - i * thickness , this . f_96544_ , vignetteColor ) ;
2026-05-04 12:09:37 +02:00
}
for ( i = 0 ; i < 150 ; + + i ) {
int gx = this . random . m_188503_ ( this . f_96543_ ) ;
int gy = this . random . m_188503_ ( this . f_96544_ ) ;
int grainAlpha = ( int ) ( ( float ) ( 20 + this . random . m_188503_ ( 30 ) ) * globalAlpha ) ;
int grainColor = grainAlpha < < 24 | 0xFFFFFF ;
2026-05-04 13:33:41 +02:00
graphics . fill ( gx , gy , gx + 1 , gy + 1 , grainColor ) ;
2026-05-04 12:09:37 +02:00
}
for ( int y = 0 ; y < this . f_96544_ ; y + = 4 ) {
2026-05-04 13:33:41 +02:00
graphics . fill ( 0 , y , this . f_96543_ , y + 1 , 0x8000000 ) ;
2026-05-04 12:09:37 +02:00
}
RenderSystem . disableBlend ( ) ;
}
private void drawLine ( GuiGraphics graphics , int x1 , int y1 , int x2 , int y2 , int color ) {
int dx = Math . abs ( x2 - x1 ) ;
int dy = Math . abs ( y2 - y1 ) ;
int sx = x1 < x2 ? 1 : - 1 ;
int sy = y1 < y2 ? 1 : - 1 ;
int err = dx - dy ;
for ( int steps = 0 ; steps < 200 ; + + steps ) {
2026-05-04 13:33:41 +02:00
graphics . fill ( x1 , y1 , x1 + 1 , y1 + 1 , color ) ;
2026-05-04 12:09:37 +02:00
if ( x1 = = x2 & & y1 = = y2 ) break ;
int e2 = 2 * err ;
if ( e2 > - dy ) {
err - = dy ;
x1 + = sx ;
}
if ( e2 > = dx ) continue ;
err + = dx ;
y1 + = sy ;
}
}
public void m_7379_ ( ) {
if ( ! this . fadingOut ) {
this . cleanupAnimators ( ) ;
super . m_7379_ ( ) ;
}
}
public boolean m_7933_ ( int keyCode , int scanCode , int modifiers ) {
if ( keyCode = = 256 ) {
return true ;
}
return super . m_7933_ ( keyCode , scanCode , modifiers ) ;
}
public boolean m_7043_ ( ) {
return true ;
}
private float easeOutCubic ( float x ) {
return 1 . 0f - ( float ) Math . pow ( 1 . 0f - x , 3 . 0 ) ;
}
private float easeInCubic ( float x ) {
return x * x * x ;
}
private void renderBackButton ( GuiGraphics graphics , float alpha ) {
graphics . m_280168_ ( ) . m_85836_ ( ) ;
int centerX = this . backButtonX + this . backButtonW / 2 ;
int centerY = this . backButtonY + this . backButtonH / 2 ;
graphics . m_280168_ ( ) . m_252880_ ( ( float ) centerX , ( float ) centerY , 0 . 0f ) ;
graphics . m_280168_ ( ) . m_85841_ ( this . backButtonScale , this . backButtonScale , 1 . 0f ) ;
graphics . m_280168_ ( ) . m_252880_ ( ( float ) ( - this . backButtonW / 2 ) , ( float ) ( - this . backButtonH / 2 ) , 0 . 0f ) ;
if ( this . backButtonHovered ) {
int glowSize = 3 ;
int glowAlpha = ( int ) ( 128 . 0f * alpha ) < < 24 ;
2026-05-04 13:33:41 +02:00
graphics . fill ( - glowSize , - glowSize , this . backButtonW + glowSize , this . backButtonH + glowSize , 0xF28B0C | glowAlpha ) ;
2026-05-04 12:09:37 +02:00
}
int bgAlpha = ( int ) ( 255 . 0f * alpha ) < < 24 ;
2026-05-04 13:33:41 +02:00
graphics . fill ( 0 , 0 , this . backButtonW , this . backButtonH , 0x591515 | bgAlpha ) ;
2026-05-04 12:09:37 +02:00
int borderColor = this . backButtonHovered ? - 881908 : - 2529701 ;
int borderAlpha = ( int ) ( 255 . 0f * alpha ) < < 24 ;
int fadedBorderColor = borderColor & 0xFFFFFF | borderAlpha ;
2026-05-04 13:33:41 +02:00
graphics . fill ( 0 , 0 , this . backButtonW , 2 , fadedBorderColor ) ;
graphics . fill ( 0 , this . backButtonH - 2 , this . backButtonW , this . backButtonH , fadedBorderColor ) ;
graphics . fill ( 0 , 0 , 2 , this . backButtonH , fadedBorderColor ) ;
graphics . fill ( this . backButtonW - 2 , 0 , this . backButtonW , this . backButtonH , fadedBorderColor ) ;
2026-05-04 12:09:37 +02:00
graphics . m_280168_ ( ) . m_85849_ ( ) ;
String buttonText = " BACK " ;
2026-05-04 13:33:41 +02:00
int textWidth = this . f_96547_ . width ( buttonText ) ;
2026-05-04 12:09:37 +02:00
int textColor = this . backButtonHovered ? - 881908 : - 1 ;
int textAlpha = ( int ) ( 255 . 0f * alpha ) < < 24 ;
int fadedTextColor = textColor & 0xFFFFFF | textAlpha ;
graphics . m_280056_ ( this . f_96547_ , buttonText , this . backButtonX + ( this . backButtonW - textWidth ) / 2 , this . backButtonY + ( this . backButtonH - 8 ) / 2 , fadedTextColor , true ) ;
}
private void playButtonSound ( ) {
try {
2026-05-04 13:33:41 +02:00
Minecraft minecraft = Minecraft . getInstance ( ) ;
2026-05-04 12:09:37 +02:00
if ( minecraft . m_91106_ ( ) ! = null ) {
minecraft . m_91106_ ( ) . m_120367_ ( ( SoundInstance ) SimpleSoundInstance . m_119755_ ( ( SoundEvent ) ( ( SoundEvent ) ModSounds . BUTTON_SOUND . get ( ) ) , ( float ) 1 . 0f , ( float ) 1 . 0f ) ) ;
}
}
catch ( Exception e ) {
ExplosionOverhaul . LOGGER . warn ( " Failed to play button sound " , ( Throwable ) e ) ;
}
}
private static enum ScreenState {
CHOOSING_MODE ,
CHOOSING_STYLE ,
FADING_OUT ;
}
}