/* * Decompiled with CFR 0.152. */ package com.vinlanx.explosionoverhaul.client; import com.mojang.blaze3d.systems.RenderSystem; import com.vinlanx.explosionoverhaul.ExplosionOverhaul; import com.vinlanx.explosionoverhaul.ModSounds; import com.vinlanx.explosionoverhaul.client.AnimationSoundManager; import com.vinlanx.explosionoverhaul.client.BackgroundParticle; import com.vinlanx.explosionoverhaul.client.FirstTimeScreen; import com.vinlanx.explosionoverhaul.client.IntroMusicManager; import com.vinlanx.explosionoverhaul.client.SpriteSheetAnimator; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.Objects; import java.util.Queue; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.renderer.GameRenderer; 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 GuideSlidesScreen extends Screen { private static final SlideData[] SLIDES = new SlideData[]{new SlideData("claster_slide.png", 177, "Cluster TNT \u2013 If you place more than two TNT blocks next to each other, the explosion will be much stronger!"), new SlideData("cave_slide.png", 121, "Caves \u2013 If an explosion happens on the surface while you're underground, you'll hear a terrifying rumble, and the ground and dripstones will start to crumble!"), new SlideData("glass_slide.png", 98, "Glass Shattering \u2013 Explosions create shockwaves! Be careful when working with explosives near settlements."), new SlideData("lamp_slide.png", 154, "Lamp Flickering \u2013 If an explosion happens near lamps, the lights will start to flicker."), new SlideData("speed_of_sound_slide.png", 140, "Speed of Sound \u2013 Explosions travel at the speed of sound. You can also enable \"Epic Mode\" in the settings!")}; private static final int FRAME_WIDTH = 854; private static final int FRAME_HEIGHT = 480; private static final int COLUMNS = 14; private static final int ROWS = 14; private static final int FPS = 24; 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 static final int COLOR_TEXT = -1; private static final int COLOR_PROGRESS_BG = Integer.MIN_VALUE; private static final int COLOR_PROGRESS_FILL = -881908; private static final float FADE_IN_DURATION = 1.5f; private static final float SLIDE_TRANSITION_DURATION = 1.0f; private static final float AUTO_ADVANCE_DELAY = 0.5f; private int currentSlideIndex = 0; private SpriteSheetAnimator currentAnimator; private float fadeAlpha = 0.0f; private boolean fadingIn = true; private float fadeTime = 0.0f; private boolean isTransitioning = false; private float transitionTime = 0.0f; private int transitionToIndex = -1; private float transitionAlpha = 0.0f; private SpriteSheetAnimator nextAnimator; private float autoAdvanceTimer = 0.0f; private boolean waitingForAutoAdvance = false; private Queue transitionQueue = new LinkedList(); private int animationX; private int animationY; private int animationWidth; private int animationHeight; private int progressBarX; private int progressBarY; private int progressBarWidth; private int progressBarHeight; private int leftArrowX; private int leftArrowY; private int arrowSize; private int rightArrowX; private int rightArrowY; private boolean leftArrowHovered = false; private boolean rightArrowHovered = false; private float leftArrowScale = 1.0f; private float rightArrowScale = 1.0f; private int continueButtonX; private int continueButtonY; private int continueButtonWidth; private int continueButtonHeight; private boolean continueButtonHovered = false; private float continueButtonScale = 1.0f; private List particles = new ArrayList(); private RandomSource random = RandomSource.m_216327_(); private long lastFrameTime = System.currentTimeMillis(); private IntroMusicManager musicManager; public GuideSlidesScreen() { super((Component)Component.m_237113_((String)"Guide Slides")); } protected void m_7856_() { int i; super.m_7856_(); this.fadingIn = true; this.fadeTime = 0.0f; this.fadeAlpha = 0.0f; this.isTransitioning = false; this.waitingForAutoAdvance = false; this.autoAdvanceTimer = 0.0f; this.lastFrameTime = System.currentTimeMillis(); this.musicManager = IntroMusicManager.getInstance(); this.loadSlide(this.currentSlideIndex); int maxWidth = (int)((float)this.f_96543_ * 0.76f); int maxHeight = (int)((float)this.f_96544_ * 0.65f); float aspectRatio = 1.7791667f; if ((float)maxWidth / aspectRatio <= (float)maxHeight) { this.animationWidth = maxWidth; this.animationHeight = (int)((float)maxWidth / aspectRatio); } else { this.animationHeight = maxHeight; this.animationWidth = (int)((float)maxHeight * aspectRatio); } this.animationX = (this.f_96543_ - this.animationWidth) / 2; this.animationY = (int)((float)this.f_96544_ * 0.12f); this.progressBarWidth = this.animationWidth; this.progressBarHeight = (int)((float)this.f_96544_ * 0.025f); this.progressBarX = this.animationX; this.progressBarY = this.animationY + this.animationHeight + (int)((float)this.f_96544_ * 0.03f); this.arrowSize = (int)((float)this.f_96544_ * 0.08f); int arrowGap = (int)((float)this.f_96543_ * 0.02f); this.leftArrowX = this.animationX - this.arrowSize - arrowGap; this.leftArrowY = this.animationY + (this.animationHeight - this.arrowSize) / 2; this.rightArrowX = this.animationX + this.animationWidth + arrowGap; this.rightArrowY = this.animationY + (this.animationHeight - this.arrowSize) / 2; this.continueButtonWidth = (int)((float)this.f_96543_ * 0.15f); this.continueButtonHeight = (int)((float)this.f_96544_ * 0.06f); this.continueButtonX = (this.f_96543_ - this.continueButtonWidth) / 2; this.continueButtonY = (int)((float)this.f_96544_ * 0.88f); for (i = 0; i < 30; ++i) { this.particles.add(BackgroundParticle.createSpark(this.random, this.f_96543_, this.f_96544_)); } for (i = 0; i < 10; ++i) { this.particles.add(BackgroundParticle.createEmber(this.random, this.f_96543_, this.f_96544_)); } for (i = 0; i < 5; ++i) { this.particles.add(BackgroundParticle.createSmoke(this.random, this.f_96543_, this.f_96544_)); } } private void loadSlide(int index) { if (index < 0 || index >= SLIDES.length) { return; } if (this.currentAnimator != null) { this.currentAnimator.close(); } SlideData slide = SLIDES[index]; this.currentAnimator = new SpriteSheetAnimator(slide.spriteSheet, 854, 480, 14, 14, slide.totalFrames, 24); this.currentAnimator.load(); this.registerSoundCallbacks(index, this.currentAnimator); this.currentAnimator.play(); ExplosionOverhaul.LOGGER.info("Loaded guide slide {} - texture created fresh", (Object)index); } private void registerSoundCallbacks(int slideIndex, SpriteSheetAnimator animator) { switch (slideIndex) { case 0: { animator.registerFrameCallback(43, AnimationSoundManager::playRandomFarPower2Sound); animator.registerFrameCallback(132, AnimationSoundManager::playRandomSuperfar4Sound); break; } case 1: { animator.registerFrameCallback(43, AnimationSoundManager::playRandomMediumCavePower4Sound); break; } case 2: { animator.registerFrameCallback(30, AnimationSoundManager::playRandomFarPower3Sound); break; } case 3: { animator.registerFrameCallback(34, AnimationSoundManager::playRandomFarPower2Sound); break; } case 4: { animator.registerFrameCallback(30, AnimationSoundManager::playRandomFarPower2Sound); } } } public void m_86600_() { float progress; super.m_86600_(); long currentTime = System.currentTimeMillis(); float deltaTime = Math.min((float)(currentTime - this.lastFrameTime) / 1000.0f, 0.1f); this.lastFrameTime = currentTime; if (this.fadingIn) { this.fadeTime += deltaTime; progress = Math.min(1.0f, this.fadeTime / 1.5f); this.fadeAlpha = this.easeOutCubic(progress); if (this.fadeTime >= 1.5f) { this.fadingIn = false; this.fadeAlpha = 1.0f; } } if (this.isTransitioning) { this.transitionTime += deltaTime; progress = Math.min(1.0f, this.transitionTime / 1.0f); this.transitionAlpha = this.easeInOutCubic(progress); if (this.transitionTime >= 1.0f) { this.isTransitioning = false; this.currentSlideIndex = this.transitionToIndex; if (this.currentAnimator != null) { this.currentAnimator.close(); } this.currentAnimator = this.nextAnimator; this.nextAnimator = null; this.transitionToIndex = -1; this.waitingForAutoAdvance = false; this.autoAdvanceTimer = 0.0f; ExplosionOverhaul.LOGGER.info("Transition complete to slide {}", (Object)this.currentSlideIndex); if (!this.transitionQueue.isEmpty()) { int nextIndex = this.transitionQueue.poll(); ExplosionOverhaul.LOGGER.info("Processing queued transition to slide {}", (Object)nextIndex); this.startTransition(nextIndex); } } else if (this.transitionAlpha >= 0.5f && this.nextAnimator == null && this.transitionToIndex >= 0 && this.transitionToIndex < SLIDES.length) { SlideData slide = SLIDES[this.transitionToIndex]; this.nextAnimator = new SpriteSheetAnimator(slide.spriteSheet, 854, 480, 14, 14, slide.totalFrames, 24); this.nextAnimator.load(); this.registerSoundCallbacks(this.transitionToIndex, this.nextAnimator); this.nextAnimator.play(); ExplosionOverhaul.LOGGER.info("Created next slide {} animator at transition midpoint", (Object)this.transitionToIndex); } } if (this.currentAnimator != null && !this.isTransitioning) { this.currentAnimator.tick(deltaTime); } float scaleSpeed = 0.2f; float targetScale = 1.1f; this.leftArrowScale = Mth.m_14179_((float)scaleSpeed, (float)this.leftArrowScale, (float)(this.leftArrowHovered ? targetScale : 1.0f)); this.rightArrowScale = Mth.m_14179_((float)scaleSpeed, (float)this.rightArrowScale, (float)(this.rightArrowHovered ? targetScale : 1.0f)); this.continueButtonScale = Mth.m_14179_((float)scaleSpeed, (float)this.continueButtonScale, (float)(this.continueButtonHovered ? targetScale : 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.1f) { this.particles.add(BackgroundParticle.createSpark(this.random, this.f_96543_, this.f_96544_)); } if (this.random.m_188501_() < 0.03f) { this.particles.add(BackgroundParticle.createEmber(this.random, this.f_96543_, this.f_96544_)); } if (this.random.m_188501_() < 0.01f) { this.particles.add(BackgroundParticle.createSmoke(this.random, this.f_96543_, this.f_96544_)); } if (this.musicManager != null) { this.musicManager.tick(deltaTime); } } private void startTransition(int toIndex) { if (toIndex < 0 || toIndex >= SLIDES.length || this.isTransitioning) { return; } this.isTransitioning = true; this.transitionTime = 0.0f; this.transitionAlpha = 0.0f; this.transitionToIndex = toIndex; this.waitingForAutoAdvance = false; this.autoAdvanceTimer = 0.0f; ExplosionOverhaul.LOGGER.info("Starting transition from slide {} to {}", (Object)this.currentSlideIndex, (Object)toIndex); } public void m_88315_(GuiGraphics graphics, int mouseX, int mouseY, float partialTick) { graphics.m_280509_(0, 0, this.f_96543_, this.f_96544_, -15921907); if (this.fadeAlpha < 0.01f) { return; } RenderSystem.enableBlend(); RenderSystem.defaultBlendFunc(); this.renderBackgroundParticles(graphics, this.fadeAlpha * 0.6f); if (this.isTransitioning) { float currentAlpha = 1.0f - this.transitionAlpha; float nextAlpha = this.transitionAlpha; if (this.currentAnimator != null && currentAlpha > 0.01f) { this.renderAnimation(graphics, this.currentAnimator, this.fadeAlpha * currentAlpha); } if (this.nextAnimator != null && nextAlpha > 0.01f) { this.renderAnimation(graphics, this.nextAnimator, this.fadeAlpha * nextAlpha); } } else if (this.currentAnimator != null) { this.renderAnimation(graphics, this.currentAnimator, this.fadeAlpha); } this.renderGuideText(graphics, this.fadeAlpha); this.renderArrows(graphics, mouseX, mouseY, this.fadeAlpha); this.renderContinueButton(graphics, mouseX, mouseY, this.fadeAlpha); RenderSystem.disableBlend(); } private void renderBackgroundParticles(GuiGraphics graphics, float alpha) { for (BackgroundParticle p : this.particles) { float particleAlpha = p.getAlpha(); float finalAlpha = particleAlpha * alpha; 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; graphics.m_280509_((int)p.x - emberSize, (int)p.y - emberSize, (int)p.x + emberSize, (int)p.y + emberSize, colorWithAlpha); break; } case FLASH: { int flashSize = (int)(p.size * 0.7f); int flashColor = colorWithAlpha & 0xFFFFFF | (int)(finalAlpha * 180.0f) << 24; graphics.m_280509_((int)p.x - flashSize, (int)p.y - flashSize, (int)p.x + flashSize, (int)p.y + flashSize, flashColor); break; } case SMOKE: { int smokeSize = (int)p.size; int smokeColor = colorWithAlpha & 0xFFFFFF | (int)(finalAlpha * 60.0f) << 24; graphics.m_280509_((int)p.x - smokeSize, (int)p.y - smokeSize, (int)p.x + smokeSize, (int)p.y + smokeSize, smokeColor); } } } } private void renderAnimation(GuiGraphics graphics, SpriteSheetAnimator animator, float alpha) { ResourceLocation texture = animator.getTextureLocation(); if (texture == null) { return; } RenderSystem.setShader(GameRenderer::m_172817_); RenderSystem.setShaderTexture((int)0, (ResourceLocation)texture); RenderSystem.setShaderColor((float)1.0f, (float)1.0f, (float)1.0f, (float)alpha); graphics.m_280411_(texture, this.animationX, this.animationY, this.animationWidth, this.animationHeight, 0.0f, 0.0f, 854, 480, 854, 480); int glowColor = (int)(alpha * 32.0f) << 24 | 0xF28B0C; int borderThickness = 2; graphics.m_280509_(this.animationX - borderThickness, this.animationY - borderThickness, this.animationX + this.animationWidth + borderThickness, this.animationY, glowColor); graphics.m_280509_(this.animationX - borderThickness, this.animationY + this.animationHeight, this.animationX + this.animationWidth + borderThickness, this.animationY + this.animationHeight + borderThickness, glowColor); graphics.m_280509_(this.animationX - borderThickness, this.animationY, this.animationX, this.animationY + this.animationHeight, glowColor); graphics.m_280509_(this.animationX + this.animationWidth, this.animationY, this.animationX + this.animationWidth + borderThickness, this.animationY + this.animationHeight, glowColor); } private void renderProgressBar(GuiGraphics graphics, float alpha) { if (this.currentAnimator == null) { return; } int currentFrame = this.currentAnimator.getCurrentFrame(); int totalFrames = GuideSlidesScreen.SLIDES[this.currentSlideIndex].totalFrames; float progress = (float)currentFrame / (float)totalFrames; int bgColor = (int)(alpha * 128.0f) << 24 | 0; graphics.m_280509_(this.progressBarX, this.progressBarY, this.progressBarX + this.progressBarWidth, this.progressBarY + this.progressBarHeight, bgColor); int fillWidth = (int)((float)this.progressBarWidth * progress); int fillColor = (int)(alpha * 255.0f) << 24 | 0xF28B0C; graphics.m_280509_(this.progressBarX, this.progressBarY, this.progressBarX + fillWidth, this.progressBarY + this.progressBarHeight, fillColor); if (fillWidth > 0) { int glowColor = (int)(alpha * 64.0f) << 24 | 0xF28B0C; graphics.m_280509_(this.progressBarX + fillWidth - 4, this.progressBarY - 1, this.progressBarX + fillWidth, this.progressBarY + this.progressBarHeight + 1, glowColor); } } private void renderGuideText(GuiGraphics graphics, float alpha) { String text = GuideSlidesScreen.SLIDES[this.currentSlideIndex].guideText; int textColor = (int)(alpha * 255.0f) << 24 | 0xFFFFFF; int textY = this.animationY + this.animationHeight + (int)((float)this.f_96544_ * 0.04f); int maxLineWidth = this.animationWidth; List lines = this.wrapText(text, maxLineWidth); Objects.requireNonNull(this.f_96547_); int lineHeight = 9 + 4; int totalTextHeight = lines.size() * lineHeight; int startY = textY; for (int i = 0; i < lines.size(); ++i) { String line = lines.get(i); int lineWidth = this.f_96547_.m_92895_(line); int x = this.animationX + (this.animationWidth - lineWidth) / 2; graphics.m_280056_(this.f_96547_, line, x, startY + i * lineHeight, textColor, true); } } private List wrapText(String text, int maxWidth) { ArrayList lines = new ArrayList(); String[] words = text.split(" "); StringBuilder currentLine = new StringBuilder(); for (String word : words) { Object testLine = currentLine.length() > 0 ? currentLine + " " + word : word; int width = this.f_96547_.m_92895_((String)testLine); if (width > maxWidth && currentLine.length() > 0) { lines.add(currentLine.toString()); currentLine = new StringBuilder(word); continue; } if (currentLine.length() > 0) { currentLine.append(" "); } currentLine.append(word); } if (currentLine.length() > 0) { lines.add(currentLine.toString()); } return lines; } private void renderArrows(GuiGraphics graphics, int mouseX, int mouseY, float alpha) { this.leftArrowHovered = this.isPointInArrow(mouseX, mouseY, this.leftArrowX, this.leftArrowY, this.arrowSize); this.rightArrowHovered = this.isPointInArrow(mouseX, mouseY, this.rightArrowX, this.rightArrowY, this.arrowSize); if (this.currentSlideIndex > 0) { this.renderArrow(graphics, this.leftArrowX, this.leftArrowY, this.arrowSize, true, this.leftArrowScale, this.leftArrowHovered, alpha); } if (this.currentSlideIndex < SLIDES.length - 1) { this.renderArrow(graphics, this.rightArrowX, this.rightArrowY, this.arrowSize, false, this.rightArrowScale, this.rightArrowHovered, alpha); } } private void renderArrow(GuiGraphics graphics, int x, int y, int size, boolean pointLeft, float scale, boolean hovered, float alpha) { int scaledSize = (int)((float)size * scale); int offset = (scaledSize - size) / 2; int drawX = x - offset; int drawY = y - offset; int bgColor = hovered ? (int)(alpha * 192.0f) << 24 | 0xF28B0C : (int)(alpha * 128.0f) << 24 | 0x591515; this.fillCircle(graphics, drawX + scaledSize / 2, drawY + scaledSize / 2, scaledSize / 2, bgColor); int arrowColor = (int)(alpha * 255.0f) << 24 | 0xFFFFFF; int centerX = drawX + scaledSize / 2; int centerY = drawY + scaledSize / 2; int arrowWidth = scaledSize / 3; int arrowHeight = scaledSize / 4; if (pointLeft) { this.fillTriangle(graphics, centerX + arrowWidth / 2, centerY - arrowHeight, centerX + arrowWidth / 2, centerY + arrowHeight, centerX - arrowWidth / 2, centerY, arrowColor); } else { this.fillTriangle(graphics, centerX - arrowWidth / 2, centerY - arrowHeight, centerX - arrowWidth / 2, centerY + arrowHeight, centerX + arrowWidth / 2, centerY, arrowColor); } if (hovered) { int glowColor = (int)(alpha * 64.0f) << 24 | 0xF28B0C; this.fillCircle(graphics, drawX + scaledSize / 2, drawY + scaledSize / 2, scaledSize / 2 + 4, glowColor); } } private boolean isPointInArrow(int px, int py, int arrowX, int arrowY, int size) { int centerX = arrowX + size / 2; int dx = px - centerX; int centerY = arrowY + size / 2; int dy = py - centerY; int radius = size / 2; return dx * dx + dy * dy <= radius * radius; } private void fillCircle(GuiGraphics graphics, int centerX, int centerY, int radius, int color) { for (int y = -radius; y <= radius; ++y) { for (int x = -radius; x <= radius; ++x) { if (x * x + y * y > radius * radius) continue; graphics.m_280509_(centerX + x, centerY + y, centerX + x + 1, centerY + y + 1, color); } } } private void fillTriangle(GuiGraphics graphics, int x1, int y1, int x2, int y2, int x3, int y3, int color) { int minY = Math.min(y1, Math.min(y2, y3)); int maxY = Math.max(y1, Math.max(y2, y3)); for (int y = minY; y <= maxY; ++y) { int x; int minX = Integer.MAX_VALUE; int maxX = Integer.MIN_VALUE; if (this.checkIntersection(y, y1, y2, x1, x2)) { x = this.interpolate(y, y1, y2, x1, x2); minX = Math.min(minX, x); maxX = Math.max(maxX, x); } if (this.checkIntersection(y, y2, y3, x2, x3)) { x = this.interpolate(y, y2, y3, x2, x3); minX = Math.min(minX, x); maxX = Math.max(maxX, x); } if (this.checkIntersection(y, y3, y1, x3, x1)) { x = this.interpolate(y, y3, y1, x3, x1); minX = Math.min(minX, x); maxX = Math.max(maxX, x); } if (minX == Integer.MAX_VALUE || maxX == Integer.MIN_VALUE) continue; graphics.m_280509_(minX, y, maxX + 1, y + 1, color); } } private boolean checkIntersection(int y, int y1, int y2, int x1, int x2) { return y >= Math.min(y1, y2) && y <= Math.max(y1, y2) && y1 != y2; } private int interpolate(int y, int y1, int y2, int x1, int x2) { return x1 + (y - y1) * (x2 - x1) / (y2 - y1); } public boolean m_6375_(double mouseX, double mouseY, int button) { if (button == 0) { if (this.isPointInButton((int)mouseX, (int)mouseY)) { this.playButtonSound(); this.transitionToFirstTimeScreen(); return true; } if (this.currentSlideIndex > 0 && this.isPointInArrow((int)mouseX, (int)mouseY, this.leftArrowX, this.leftArrowY, this.arrowSize)) { Integer nextTransition; this.playButtonSound(); int targetIndex = this.currentSlideIndex - 1; this.transitionQueue.offer(targetIndex); if (!this.isTransitioning && (nextTransition = this.transitionQueue.poll()) != null) { this.startTransition(nextTransition); } ExplosionOverhaul.LOGGER.info("Queued left arrow transition to {}, queue size: {}", (Object)targetIndex, (Object)this.transitionQueue.size()); return true; } if (this.currentSlideIndex < SLIDES.length - 1 && this.isPointInArrow((int)mouseX, (int)mouseY, this.rightArrowX, this.rightArrowY, this.arrowSize)) { Integer nextTransition; this.playButtonSound(); int targetIndex = this.currentSlideIndex + 1; this.transitionQueue.offer(targetIndex); if (!this.isTransitioning && (nextTransition = this.transitionQueue.poll()) != null) { this.startTransition(nextTransition); } ExplosionOverhaul.LOGGER.info("Queued right arrow transition to {}, queue size: {}", (Object)targetIndex, (Object)this.transitionQueue.size()); return true; } } return super.m_6375_(mouseX, mouseY, button); } private boolean isPointInButton(int px, int py) { return px >= this.continueButtonX && px <= this.continueButtonX + this.continueButtonWidth && py >= this.continueButtonY && py <= this.continueButtonY + this.continueButtonHeight; } private void renderContinueButton(GuiGraphics graphics, int mouseX, int mouseY, float alpha) { this.continueButtonHovered = this.isPointInButton(mouseX, mouseY); int scaledWidth = (int)((float)this.continueButtonWidth * this.continueButtonScale); int scaledHeight = (int)((float)this.continueButtonHeight * this.continueButtonScale); int offsetX = (scaledWidth - this.continueButtonWidth) / 2; int offsetY = (scaledHeight - this.continueButtonHeight) / 2; int drawX = this.continueButtonX - offsetX; int drawY = this.continueButtonY - offsetY; int bgColor = this.continueButtonHovered ? (int)(alpha * 220.0f) << 24 | 0xF28B0C : (int)(alpha * 160.0f) << 24 | 0x591515; graphics.m_280509_(drawX, drawY, drawX + scaledWidth, drawY + scaledHeight, bgColor); if (this.continueButtonHovered) { int glowColor = (int)(alpha * 80.0f) << 24 | 0xF28B0C; int border = 3; graphics.m_280509_(drawX - border, drawY - border, drawX + scaledWidth + border, drawY, glowColor); graphics.m_280509_(drawX - border, drawY + scaledHeight, drawX + scaledWidth + border, drawY + scaledHeight + border, glowColor); graphics.m_280509_(drawX - border, drawY, drawX, drawY + scaledHeight, glowColor); graphics.m_280509_(drawX + scaledWidth, drawY, drawX + scaledWidth + border, drawY + scaledHeight, glowColor); } String text = "Skip Guide"; int textColor = (int)(alpha * 255.0f) << 24 | 0xFFFFFF; int textX = drawX + (scaledWidth - this.f_96547_.m_92895_(text)) / 2; Objects.requireNonNull(this.f_96547_); int textY = drawY + (scaledHeight - 9) / 2; graphics.m_280056_(this.f_96547_, text, textX, textY, textColor, true); } public boolean m_6913_() { return false; } public boolean m_7043_() { return false; } public void m_7861_() { super.m_7861_(); this.transitionQueue.clear(); if (this.currentAnimator != null) { this.currentAnimator.close(); } if (this.nextAnimator != null) { this.nextAnimator.close(); } } private void transitionToFirstTimeScreen() { ExplosionOverhaul.LOGGER.info("All guide slides complete. Transitioning to FirstTimeScreen."); Minecraft.m_91087_().m_91152_((Screen)new FirstTimeScreen()); } 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) { graphics.m_280509_(x1, y1, x1 + 1, y1 + 1, color); 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; } } private float easeOutCubic(float t) { return 1.0f - (float)Math.pow(1.0f - t, 3.0); } private float easeInCubic(float t) { return t * t * t; } private float easeInOutCubic(float t) { return t < 0.5f ? 4.0f * t * t * t : 1.0f - (float)Math.pow(-2.0f * t + 2.0f, 3.0) / 2.0f; } private void playButtonSound() { try { Minecraft minecraft = Minecraft.m_91087_(); 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 class SlideData { final ResourceLocation spriteSheet; final int totalFrames; final String guideText; SlideData(String filename, int frames, String text) { this.spriteSheet = ResourceLocation.fromNamespaceAndPath((String)"explosionoverhaul", (String)("intro_gui/" + filename)); this.totalFrames = frames; this.guideText = text; } } }