2026-05-04 12:09:37 +02:00
package com.vinlanx.explosionoverhaul.client ;
2026-05-07 23:08:09 +02:00
import com.vinlanx.explosionoverhaul.Config ;
2026-05-04 12:09:37 +02:00
import net.minecraft.client.gui.GuiGraphics ;
import net.minecraft.client.gui.screens.Screen ;
import net.minecraft.network.chat.Component ;
2026-05-07 23:08:09 +02:00
import net.minecraft.resources.ResourceLocation ;
2026-05-04 12:09:37 +02:00
2026-05-07 00:14:48 +02:00
public class FirstTimeScreen extends Screen {
2026-05-09 00:25:19 +02:00
private static final int FRAME_WIDTH = 256 ;
private static final int FRAME_HEIGHT = 144 ;
2026-05-08 00:33:17 +02:00
private static final int COLUMNS = 10 ;
private static final int ROWS = 10 ;
private static final int FRAME_COUNT = COLUMNS * ROWS ;
private static final int BORDER = 0xFFFF7A70 ;
private static final int BORDER_HOVER = 0xFFFF9B91 ;
private static final Choice [ ] CHOICES = new Choice [ ] {
2026-05-09 00:25:19 +02:00
new Choice ( " gui_screen_1.png " , 12 , " REALISTIC " , Config . Client . ParticleRenderMode . REALISTIC ) ,
new Choice ( " gui_screen_2.png " , 28 , " VANILLA-LIKE " , Config . Client . ParticleRenderMode . VANILA ) ,
new Choice ( " gui_screen_3.png " , 44 , " REALISTIC 2 " , Config . Client . ParticleRenderMode . REALISTIC_2 )
2026-05-08 00:33:17 +02:00
} ;
2026-05-07 23:08:09 +02:00
2026-05-08 00:33:17 +02:00
private final Rect [ ] cardRects = new Rect [ ] { Rect . empty ( ) , Rect . empty ( ) , Rect . empty ( ) } ;
2026-05-07 23:08:09 +02:00
2026-05-04 12:09:37 +02:00
public FirstTimeScreen ( ) {
2026-05-07 23:08:09 +02:00
super ( Component . literal ( " Explosion Overhaul Setup " ) ) ;
}
@Override
2026-05-08 00:33:17 +02:00
public void render ( GuiGraphics graphics , int mouseX , int mouseY , float partialTick ) {
graphics . fill ( 0 , 0 , this . width , this . height , 0xFF050506 ) ;
this . drawAmbient ( graphics ) ;
2026-05-09 00:25:19 +02:00
int top = Math . max ( 28 , this . height / 9 ) ;
2026-05-08 00:33:17 +02:00
graphics . drawCenteredString ( this . font , Component . literal ( " Choose Your Explosion Style. " ) , this . width / 2 , top , 0xFFFF9900 ) ;
graphics . drawCenteredString ( this . font , Component . literal ( " You can change this anytime in the config " ) , this . width / 2 , top + 25 , 0xFFE5E5E5 ) ;
graphics . drawCenteredString ( this . font , Component . literal ( " The game may differ from the animations because compression has altered them. " ) , this . width / 2 , top + 48 , 0xFF9C9C9C ) ;
2026-05-09 00:25:19 +02:00
int availableCardH = Math . max ( 78 , ( this . height - top - 188 ) / 2 ) ;
int cardW = Math . min ( 360 , Math . max ( 150 , ( this . width - 170 ) / 2 ) ) ;
cardW = Math . min ( cardW , availableCardH * FRAME_WIDTH / FRAME_HEIGHT ) ;
2026-05-08 00:33:17 +02:00
int cardH = cardW * FRAME_HEIGHT / FRAME_WIDTH ;
int gap = Math . max ( 34 , this . width / 28 ) ;
int firstX = this . width / 2 - cardW - gap / 2 ;
int secondX = this . width / 2 + gap / 2 ;
2026-05-09 00:25:19 +02:00
int firstRowY = top + 92 ;
int secondRowY = firstRowY + cardH + 60 ;
2026-05-08 00:33:17 +02:00
this . cardRects [ 0 ] = new Rect ( firstX , firstRowY , cardW , cardH + 58 ) ;
this . cardRects [ 1 ] = new Rect ( secondX , firstRowY , cardW , cardH + 58 ) ;
this . cardRects [ 2 ] = new Rect ( ( this . width - cardW ) / 2 , secondRowY , cardW , cardH + 58 ) ;
for ( int i = 0 ; i < CHOICES . length ; + + i ) {
this . drawChoice ( graphics , CHOICES [ i ] , this . cardRects [ i ] , this . cardRects [ i ] . contains ( mouseX , mouseY ) ) ;
}
2026-05-07 23:08:09 +02:00
}
2026-05-08 00:33:17 +02:00
@Override
public boolean mouseClicked ( double mouseX , double mouseY , int button ) {
if ( button = = 0 ) {
for ( int i = 0 ; i < this . cardRects . length ; + + i ) {
if ( this . cardRects [ i ] . contains ( mouseX , mouseY ) ) {
this . finish ( CHOICES [ i ] ) ;
return true ;
}
}
2026-05-07 23:08:09 +02:00
}
2026-05-08 00:33:17 +02:00
return super . mouseClicked ( mouseX , mouseY , button ) ;
2026-05-07 23:08:09 +02:00
}
2026-05-08 00:33:17 +02:00
private void finish ( Choice choice ) {
Config . CLIENT . particleRenderMode . set ( choice . mode ) ;
Config . CLIENT . glowTextureQuality . set ( Config . Client . GlowTextureQuality . QUALITY_256 ) ;
2026-05-07 23:08:09 +02:00
Config . CLIENT . firstLaunchComplete . set ( true ) ;
Config . CLIENT . introSetupComplete . set ( true ) ;
Config . CLIENT_SPEC . save ( ) ;
this . onClose ( ) ;
2026-05-04 12:09:37 +02:00
}
2026-05-08 00:33:17 +02:00
private void drawChoice ( GuiGraphics graphics , Choice choice , Rect rect , boolean hovered ) {
int imageX = rect . x ;
int imageY = rect . y ;
int imageW = rect . w ;
int imageH = rect . w * FRAME_HEIGHT / FRAME_WIDTH ;
graphics . fill ( imageX - 6 , imageY - 6 , imageX + imageW + 6 , imageY + imageH + 6 , hovered ? BORDER_HOVER : BORDER ) ;
2026-05-09 00:25:19 +02:00
this . drawSheetFrame ( graphics , choice . texture , ( this . currentFrame ( 65L ) + choice . frameOffset ) % FRAME_COUNT , imageX , imageY , imageW , imageH ) ;
2026-05-08 00:33:17 +02:00
graphics . drawCenteredString ( this . font , Component . literal ( choice . label ) , imageX + imageW / 2 , imageY + imageH + 28 , 0xFFFFFFFF ) ;
2026-05-04 12:09:37 +02:00
}
2026-05-07 23:08:09 +02:00
2026-05-08 00:33:17 +02:00
private void drawSheetFrame ( GuiGraphics graphics , ResourceLocation texture , int frame , int x , int y , int width , int height ) {
int clamped = Math . max ( 0 , Math . min ( frame , FRAME_COUNT - 1 ) ) ;
int u = clamped % COLUMNS * FRAME_WIDTH ;
int v = clamped / COLUMNS * FRAME_HEIGHT ;
float scaleX = ( float ) width / ( float ) FRAME_WIDTH ;
float scaleY = ( float ) height / ( float ) FRAME_HEIGHT ;
graphics . pose ( ) . pushPose ( ) ;
graphics . pose ( ) . translate ( x , y , 0 . 0F ) ;
graphics . pose ( ) . scale ( scaleX , scaleY , 1 . 0F ) ;
graphics . blit ( texture , 0 , 0 , ( float ) u , ( float ) v , FRAME_WIDTH , FRAME_HEIGHT , FRAME_WIDTH * COLUMNS , FRAME_HEIGHT * ROWS ) ;
graphics . pose ( ) . popPose ( ) ;
}
2026-05-09 00:25:19 +02:00
private int currentFrame ( long frameTimeMillis ) {
return ( int ) ( ( System . currentTimeMillis ( ) / frameTimeMillis ) % FRAME_COUNT ) ;
}
2026-05-08 00:33:17 +02:00
private void drawAmbient ( GuiGraphics graphics ) {
2026-05-09 00:25:19 +02:00
for ( int i = 0 ; i < 48 ; + + i ) {
2026-05-08 00:33:17 +02:00
int x = Math . floorMod ( i * 173 + 19 , Math . max ( 1 , this . width ) ) ;
int y = Math . floorMod ( i * 97 + 53 , Math . max ( 1 , this . height ) ) ;
int color = i % 7 = = 0 ? 0xFFFFB347 : 0xFF414141 ;
2026-05-09 00:25:19 +02:00
graphics . fill ( x , y , x + 1 , y + 1 , color ) ;
2026-05-08 00:33:17 +02:00
}
2026-05-07 23:08:09 +02:00
}
@Override
public boolean shouldCloseOnEsc ( ) {
return false ;
}
2026-05-08 00:33:17 +02:00
private static final class Choice {
private final ResourceLocation texture ;
2026-05-09 00:25:19 +02:00
private final int frameOffset ;
2026-05-08 00:33:17 +02:00
private final String label ;
private final Config . Client . ParticleRenderMode mode ;
2026-05-09 00:25:19 +02:00
private Choice ( String fileName , int frameOffset , String label , Config . Client . ParticleRenderMode mode ) {
this . texture = ResourceLocation . fromNamespaceAndPath ( " explosionoverhaul " , " intro_gui/preview/ " + fileName ) ;
this . frameOffset = frameOffset ;
2026-05-08 00:33:17 +02:00
this . label = label ;
this . mode = mode ;
}
}
private static final class Rect {
private final int x ;
private final int y ;
private final int w ;
private final int h ;
private Rect ( int x , int y , int w , int h ) {
this . x = x ;
this . y = y ;
this . w = w ;
this . h = h ;
}
private static Rect empty ( ) {
return new Rect ( 0 , 0 , 0 , 0 ) ;
}
private boolean contains ( double mouseX , double mouseY ) {
return mouseX > = this . x & & mouseY > = this . y & & mouseX < this . x + this . w & & mouseY < this . y + this . h ;
}
}
2026-05-04 12:09:37 +02:00
}