diff --git a/src/main/java/org/saturnclient/saturnclient/mixin/SetScreenMixin.java b/src/main/java/org/saturnclient/saturnclient/mixin/SetScreenMixin.java new file mode 100644 index 0000000..913d004 --- /dev/null +++ b/src/main/java/org/saturnclient/saturnclient/mixin/SetScreenMixin.java @@ -0,0 +1,35 @@ +package org.saturnclient.saturnclient.mixin; + +import org.saturnclient.saturnclient.SaturnClientConfig; +import org.saturnclient.ui2.screens.TitleMenu; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screen.TitleScreen; + +@Mixin(MinecraftClient.class) +public class SetScreenMixin { + + private boolean replacingScreen = false; + + @Inject(method = "setScreen", at = @At("HEAD"), cancellable = true) + private void onSetScreen(Screen screen, CallbackInfo ci) { + if (replacingScreen) + return; + + @SuppressWarnings("resource") // False positive bc MinecraftClient has close() + MinecraftClient client = ((MinecraftClient) (Object) this); + + if (SaturnClientConfig.saturnTitleScreen.value + && ((screen == null && client.world == null) || screen instanceof TitleScreen)) { + replacingScreen = true; + client.setScreen(new TitleMenu()); + ci.cancel(); + replacingScreen = false; + } + } +} \ No newline at end of file diff --git a/src/main/java/org/saturnclient/saturnclient/mixin/SplashOverlayMixin.java b/src/main/java/org/saturnclient/saturnclient/mixin/SplashOverlayMixin.java index f06b992..f9889d8 100644 --- a/src/main/java/org/saturnclient/saturnclient/mixin/SplashOverlayMixin.java +++ b/src/main/java/org/saturnclient/saturnclient/mixin/SplashOverlayMixin.java @@ -51,71 +51,96 @@ public abstract class SplashOverlayMixin { } /** - * @author SaturnClient * @reason Replace vanilla splash rendering completely but keep exit logic */ @Overwrite public void render(DrawContext context, int mouseX, int mouseY, float delta) { - int width = context.getScaledWindowWidth(); - int height = context.getScaledWindowHeight(); + int screenWidth = context.getScaledWindowWidth(); + int screenHeight = context.getScaledWindowHeight(); long currentTime = Util.getMeasuringTimeMs(); - // Handle reload start timing (vanilla uses 500ms fade-in) - if (this.reloadStartTime == -1L) { - this.reloadStartTime = currentTime; + // Initialize reload start time if not set + if (reloadStartTime == -1L) { + reloadStartTime = currentTime; } - // Compute fade-out timing - float f = this.reloadCompleteTime > -1L ? (float) (currentTime - this.reloadCompleteTime) / 1000f : -1f; + // Compute fade-out progress after reload completes + float fadeOutProgress = reloadCompleteTime > -1L + ? (float) (currentTime - reloadCompleteTime) / 1000f + : -1f; - int alpha = f >= 0f - ? MathHelper.ceil((1.0f - MathHelper.clamp(f - 1f, 0f, 1f)) * 255f) + int logoAlpha = fadeOutProgress >= 0f + ? MathHelper.ceil((1.0f - MathHelper.clamp(fadeOutProgress - 1f, 0f, 1f)) * 255f) : 255; - long l = Util.getMeasuringTimeMs(); - float g = this.reloadStartTime > -1L ? (float) (l - this.reloadStartTime) / 500.0F : -1.0F; + // Compute fade-in progress while reloading + float reloadProgress = reloadStartTime > -1L + ? (float) (currentTime - reloadStartTime) / 500f + : -1f; - int k; - - if (f >= 1.0F) { - if (this.client.currentScreen != null) { - this.client.currentScreen.render(context, 0, 0, delta); + // Draw background overlay + if (fadeOutProgress >= 1.0F) { + renderCurrentScreen(context, mouseX, mouseY, delta); + int overlayAlpha = computeOverlayAlpha(fadeOutProgress - 1f); + context.fill(RenderLayer.getGuiOverlay(), 0, 0, screenWidth, screenHeight, + withAlpha(0x28282B, overlayAlpha)); + } else if (reloading) { + if (reloadProgress < 1.0F) { + renderCurrentScreen(context, mouseX, mouseY, delta); } - - k = MathHelper.ceil((1.0F - MathHelper.clamp(f - 1.0F, 0.0F, 1.0F)) * - 255.0F); - context.fill(RenderLayer.getGuiOverlay(), 0, 0, width, height, - withAlpha(0x28282B, k)); - } else if (this.reloading) { - if (this.client.currentScreen != null && g < 1.0F) { - this.client.currentScreen.render(context, mouseX, mouseY, delta); - } - - k = MathHelper.ceil(MathHelper.clamp((double) g, 0.15, 1.0) * 255.0); - context.fill(RenderLayer.getGuiOverlay(), 0, 0, width, height, - withAlpha(0x28282B, k)); + int overlayAlpha = MathHelper.ceil(MathHelper.clamp(reloadProgress, 0.15, 1.0) * 255.0); + context.fill(RenderLayer.getGuiOverlay(), 0, 0, screenWidth, screenHeight, + withAlpha(0x28282B, overlayAlpha)); } + // Draw central logo + drawLogo(context, screenWidth, screenHeight, logoAlpha); + + // Remove overlay after fade-out completes + if (fadeOutProgress >= 2.0F) { + client.setOverlay(null); + } + + // Handle reload completion and exceptions + handleReloadCompletion(context); + } + + private void renderCurrentScreen(DrawContext context, int mouseX, int mouseY, float delta) { + if (client.currentScreen != null) { + client.currentScreen.render(context, mouseX, mouseY, delta); + } + } + + /** Draw the main logo centered */ + private void drawLogo(DrawContext context, int screenWidth, int screenHeight, int alpha) { RenderScope scope = new RenderScope(context); scope.setRenderLayer(RenderLayer::getGuiTextured); - scope.drawTexture(Textures.LOGO, width / 2 - 49, height / 2 - 49, 0, 0, 98, 98, withAlpha(0xFFFFFF, alpha)); + scope.drawTexture(Textures.LOGO, screenWidth / 2 - 49, screenHeight / 2 - 49, 0, 0, 98, 98, + withAlpha(0xFFFFFF, alpha)); + } - if (f >= 2.0F) { - this.client.setOverlay(null); - } + /** Compute overlay alpha from fade progress */ + private int computeOverlayAlpha(float progress) { + return MathHelper.ceil((1.0F - MathHelper.clamp(progress, 0.0F, 1.0F)) * 255.0F); + } - if (this.reloadCompleteTime == -1L && this.reload.isComplete() && (!this.reloading || g >= 2.0F)) { + /** Handle reload completion logic */ + private void handleReloadCompletion(DrawContext context) { + float reloadProgress = reloadStartTime > -1L ? (float) (Util.getMeasuringTimeMs() - reloadStartTime) / 500f + : -1f; + + if (reloadCompleteTime == -1L && reload.isComplete() && (!reloading || reloadProgress >= 2.0F)) { try { - this.reload.throwException(); - this.exceptionHandler.accept(Optional.empty()); - } catch (Throwable var24) { - this.exceptionHandler.accept(Optional.of(var24)); + reload.throwException(); + exceptionHandler.accept(Optional.empty()); + } catch (Throwable ex) { + exceptionHandler.accept(Optional.of(ex)); } - this.reloadCompleteTime = Util.getMeasuringTimeMs(); - if (this.client.currentScreen != null) { - this.client.currentScreen.init(this.client, context.getScaledWindowWidth(), - context.getScaledWindowHeight()); + reloadCompleteTime = Util.getMeasuringTimeMs(); + + if (client.currentScreen != null) { + client.currentScreen.init(client, context.getScaledWindowWidth(), context.getScaledWindowHeight()); } } } diff --git a/src/main/java/org/saturnclient/saturnclient/mixin/TitleScreenMixin.java b/src/main/java/org/saturnclient/saturnclient/mixin/TitleScreenMixin.java deleted file mode 100644 index 44151c1..0000000 --- a/src/main/java/org/saturnclient/saturnclient/mixin/TitleScreenMixin.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.saturnclient.saturnclient.mixin; - -import org.saturnclient.saturnclient.SaturnClient; -import org.saturnclient.saturnclient.SaturnClientConfig; -import org.saturnclient.ui2.screens.TitleMenu; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import net.minecraft.client.gui.screen.TitleScreen; - -@Mixin(TitleScreen.class) -public class TitleScreenMixin { - @Inject(method = "init", at = @At("HEAD"), cancellable = true) - private void onInit(CallbackInfo ci) { - if (SaturnClientConfig.saturnTitleScreen.value) { - SaturnClient.client.setScreen(new TitleMenu()); - ci.cancel(); - } - } -} diff --git a/src/main/java/org/saturnclient/ui2/SaturnScreen.java b/src/main/java/org/saturnclient/ui2/SaturnScreen.java index d69b579..05bde40 100644 --- a/src/main/java/org/saturnclient/ui2/SaturnScreen.java +++ b/src/main/java/org/saturnclient/ui2/SaturnScreen.java @@ -22,6 +22,7 @@ import net.minecraft.util.Identifier; public abstract class SaturnScreen extends Screen { private final Pool pool = new Pool(3); protected List elements = new ArrayList<>(); + protected float backgroundOpacity = 1.0f; public int blurDuration = 700; public float blurProgress = 0.0f; public int backgroundBlur = 10; @@ -43,7 +44,7 @@ public abstract class SaturnScreen extends Screen { synchronized (elements) { elements.add(element); } - + if (element.animation != null) { element.animation.init(element); @@ -93,16 +94,16 @@ public abstract class SaturnScreen extends Screen { mouseY *= 2; if (client.world == null && client.getCurrentServerEntry() == null) { - ROTATING_PANORAMA_RENDERER.render(context, this.width, this.height, 1.0F, delta); + ROTATING_PANORAMA_RENDERER.render(context, this.width, this.height, backgroundOpacity, delta); } PostEffectProcessor postEffectProcessor = this.client.getShaderLoader().loadPostEffect( - Identifier.ofVanilla("blur"), - DefaultFramebufferSet.MAIN_ONLY); - if (postEffectProcessor != null) { - postEffectProcessor.setUniforms("Radius", backgroundBlur * blurProgress); - postEffectProcessor.render(this.client.getFramebuffer(), this.pool); - } + Identifier.ofVanilla("blur"), + DefaultFramebufferSet.MAIN_ONLY); + if (postEffectProcessor != null) { + postEffectProcessor.setUniforms("Radius", backgroundBlur * blurProgress); + postEffectProcessor.render(this.client.getFramebuffer(), this.pool); + } // We are using a Abstracted RenderScope because older minecraft versions don't // use DrawContext diff --git a/src/main/java/org/saturnclient/ui2/screens/TitleMenu.java b/src/main/java/org/saturnclient/ui2/screens/TitleMenu.java index 8bcde8e..bfe76b0 100644 --- a/src/main/java/org/saturnclient/ui2/screens/TitleMenu.java +++ b/src/main/java/org/saturnclient/ui2/screens/TitleMenu.java @@ -20,14 +20,17 @@ import net.minecraft.client.gui.screen.world.SelectWorldScreen; public class TitleMenu extends SaturnScreen { public TitleMenu() { super("Tile Menu"); + this.backgroundOpacity = 0.0f; } @Override public void ui() { backgroundBlur = 0; - draw(new ImageTexture(Textures.LOGO_TEXT).dimensions(98, 10).centerOffset(width, height, 0, -36).animation(new Fade(700))); - draw(new ImageTexture(SaturnClientConfig.getLogo()).dimensions(98, 98).centerOffset(width, height, 0, -82).animation(new SlideY(700, -20))); + draw(new ImageTexture(Textures.LOGO_TEXT).dimensions(98, 10).centerOffset(width, height, 0, -36) + .animation(new Fade(700))); + draw(new ImageTexture(SaturnClientConfig.getLogo()).dimensions(98, 98).centerOffset(width, height, 0, -82) + .animation(new SlideY(700, -20))); draw(new Button("SINGLEPLAYER", () -> { client.setScreen(new SelectWorldScreen(new TitleMenu())); diff --git a/src/main/resources/saturnclient.mixins.json b/src/main/resources/saturnclient.mixins.json index fc7de68..3bc9ccc 100644 --- a/src/main/resources/saturnclient.mixins.json +++ b/src/main/resources/saturnclient.mixins.json @@ -9,8 +9,8 @@ "PlayerEntityRendererMixin", "WhoAmI", "DrawContextAccessor", - "TitleScreenMixin", - "SplashOverlayMixin" + "SplashOverlayMixin", + "SetScreenMixin" ], "injectors": { "defaultRequire": 1