diff --git a/CHANGELOG.md b/CHANGELOG.md index e4c37ec..d1d7677 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,2 +1 @@ -- Ported to 1.19.4 (thanks, [Pqtato](https://pqtato.neocities.org/)!) -- Mod Menu is no longer a strictly required dependency +- Ported to 1.20.1 \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 775dc8d..bfc3dcd 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,24 +3,24 @@ org.gradle.jvmargs=-Xmx1G # Fabric Properties # check these on https://fabricmc.net/develop - minecraft_version=1.19.4 - accepted_minecraft_version=1.19.4 - yarn_mappings=1.19.4+build.1 - loader_version=0.14.18 + minecraft_version=1.20.1 + accepted_minecraft_version=1.20.1 + yarn_mappings=1.20.1+build.10 + loader_version=0.14.22 # Mod Properties - mod_version = 1.2+1.19.4 - mod_version_friendly = 1.2 for 1.19.4 + mod_version = 1.2+1.20.1 + mod_version_friendly = 1.2 for 1.20.1 maven_group = zone.oat archives_base_name = gmod-title-screen # Dependencies - fabric_version=0.76.0+1.19.4 + fabric_version=0.87.0+1.20.1 # https://modrinth.com/mod/modmenu - modmenu_version=6.1.0-rc.4 + modmenu_version=7.2.1 # Dev environment # https://modrinth.com/mod/suggestion-tweaker #suggestion_tweaker_version = 1.19.1-1.3.1 # https://modrinth.com/mod/cloth-config - cloth_config_version = 10.0.96 + cloth_config_version = 11.1.106 diff --git a/remappedSrc/zone/oat/gmodtitlescreen/Mod.java b/remappedSrc/zone/oat/gmodtitlescreen/Mod.java new file mode 100644 index 0000000..4fa9d23 --- /dev/null +++ b/remappedSrc/zone/oat/gmodtitlescreen/Mod.java @@ -0,0 +1,18 @@ +package zone.oat.gmodtitlescreen; + +import me.shedaniel.autoconfig.AutoConfig; +import me.shedaniel.autoconfig.serializer.Toml4jConfigSerializer; +import net.fabricmc.api.ClientModInitializer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Mod implements ClientModInitializer { + public static final Logger LOGGER = LoggerFactory.getLogger(""); + public static ModConfig config; + + @Override + public void onInitializeClient() { + AutoConfig.register(ModConfig.class, Toml4jConfigSerializer::new); + config = AutoConfig.getConfigHolder(ModConfig.class).getConfig(); + } +} diff --git a/remappedSrc/zone/oat/gmodtitlescreen/ModConfig.java b/remappedSrc/zone/oat/gmodtitlescreen/ModConfig.java new file mode 100644 index 0000000..0d3e0a2 --- /dev/null +++ b/remappedSrc/zone/oat/gmodtitlescreen/ModConfig.java @@ -0,0 +1,14 @@ +package zone.oat.gmodtitlescreen; + +import me.shedaniel.autoconfig.ConfigData; +import me.shedaniel.autoconfig.annotation.Config; +import me.shedaniel.autoconfig.annotation.ConfigEntry; + +@Config(name = "gmod-title-screen") +@Config.Gui.Background("textures/block/blue_concrete_powder.png") +public +class ModConfig implements ConfigData { + @ConfigEntry.Gui.Tooltip(count = 2) + public boolean showGModLogo = false; + public boolean showSplashText = true; +} \ No newline at end of file diff --git a/remappedSrc/zone/oat/gmodtitlescreen/ModIdentifier.java b/remappedSrc/zone/oat/gmodtitlescreen/ModIdentifier.java new file mode 100644 index 0000000..31a7da7 --- /dev/null +++ b/remappedSrc/zone/oat/gmodtitlescreen/ModIdentifier.java @@ -0,0 +1,9 @@ +package zone.oat.gmodtitlescreen; + +import net.minecraft.util.Identifier; + +public class ModIdentifier extends Identifier { + public ModIdentifier(String path) { + super("gmod-title-screen", path); + } +} diff --git a/remappedSrc/zone/oat/gmodtitlescreen/ModMenuIntegration.java b/remappedSrc/zone/oat/gmodtitlescreen/ModMenuIntegration.java new file mode 100644 index 0000000..80811a9 --- /dev/null +++ b/remappedSrc/zone/oat/gmodtitlescreen/ModMenuIntegration.java @@ -0,0 +1,15 @@ +package zone.oat.gmodtitlescreen; + +import com.terraformersmc.modmenu.api.ConfigScreenFactory; +import com.terraformersmc.modmenu.api.ModMenuApi; +import me.shedaniel.autoconfig.AutoConfig; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +@Environment(EnvType.CLIENT) +public class ModMenuIntegration implements ModMenuApi { + @Override + public ConfigScreenFactory getModConfigScreenFactory() { + return parent -> AutoConfig.getConfigScreen(ModConfig.class, parent).get(); + } +} diff --git a/remappedSrc/zone/oat/gmodtitlescreen/PressableTextWithTooltipWidget.java b/remappedSrc/zone/oat/gmodtitlescreen/PressableTextWithTooltipWidget.java new file mode 100644 index 0000000..034fb2d --- /dev/null +++ b/remappedSrc/zone/oat/gmodtitlescreen/PressableTextWithTooltipWidget.java @@ -0,0 +1,19 @@ +package zone.oat.gmodtitlescreen; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.tooltip.Tooltip; +import net.minecraft.client.gui.widget.PressableTextWidget; +import net.minecraft.text.Text; + +@Environment(EnvType.CLIENT) +public class PressableTextWithTooltipWidget extends PressableTextWidget { + protected final Tooltip tooltip; + + public PressableTextWithTooltipWidget(int x, int y, int width, int height, Text text, PressAction onPress, TextRenderer textRenderer, Tooltip tooltip) { + super(x, y, width, height, text, onPress, textRenderer); + this.tooltip = tooltip; + setTooltip(tooltip); + } +} diff --git a/remappedSrc/zone/oat/gmodtitlescreen/mixin/LoadCustomTitleScreenMixin.java b/remappedSrc/zone/oat/gmodtitlescreen/mixin/LoadCustomTitleScreenMixin.java new file mode 100644 index 0000000..933062a --- /dev/null +++ b/remappedSrc/zone/oat/gmodtitlescreen/mixin/LoadCustomTitleScreenMixin.java @@ -0,0 +1,18 @@ +package zone.oat.gmodtitlescreen.mixin; + +import net.minecraft.client.texture.TextureManager; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import zone.oat.gmodtitlescreen.screen.CustomTitleScreen; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; + +@Mixin(TextureManager.class) +public class LoadCustomTitleScreenMixin { + @Redirect(method = "reload", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/TitleScreen;loadTexturesAsync(Lnet/minecraft/client/texture/TextureManager;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;")) + private CompletableFuture injected(TextureManager textureManager, Executor executor) { + return CustomTitleScreen.loadTexturesAsync(textureManager, executor); + } +} diff --git a/remappedSrc/zone/oat/gmodtitlescreen/mixin/RedirectTitleScreenMixin.java b/remappedSrc/zone/oat/gmodtitlescreen/mixin/RedirectTitleScreenMixin.java new file mode 100644 index 0000000..854437b --- /dev/null +++ b/remappedSrc/zone/oat/gmodtitlescreen/mixin/RedirectTitleScreenMixin.java @@ -0,0 +1,27 @@ +package zone.oat.gmodtitlescreen.mixin; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screen.TitleScreen; +import org.objectweb.asm.Opcodes; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import zone.oat.gmodtitlescreen.screen.CustomTitleScreen; + +// this sucks. lmao. +@Mixin(MinecraftClient.class) +public class RedirectTitleScreenMixin { + @Redirect(method = "setScreen", at = @At(value = "FIELD", target = "Lnet/minecraft/client/MinecraftClient;currentScreen:Lnet/minecraft/client/gui/screen/Screen;", opcode = Opcodes.PUTFIELD)) + private void injected(MinecraftClient instance, Screen value) { + if (value instanceof TitleScreen) { + //instance.currentScreen = new CustomTitleScreen(); + // this causes a fabric api error of all things, so let's do a little redundancy, shall we? + instance.setScreen(new CustomTitleScreen()); + // yes. Wonderful. let's fucking call it Twice. + // (i genuinely could not find anything that Isn't this) + } else { + instance.currentScreen = value; + } + } +} diff --git a/remappedSrc/zone/oat/gmodtitlescreen/screen/CustomTitleScreen.java b/remappedSrc/zone/oat/gmodtitlescreen/screen/CustomTitleScreen.java new file mode 100644 index 0000000..f640fd8 --- /dev/null +++ b/remappedSrc/zone/oat/gmodtitlescreen/screen/CustomTitleScreen.java @@ -0,0 +1,372 @@ +package zone.oat.gmodtitlescreen.screen; + +import com.mojang.blaze3d.platform.GlStateManager; +import com.mojang.blaze3d.systems.RenderSystem; +import com.terraformersmc.modmenu.gui.ModsScreen; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.loader.api.FabricLoader; +import net.minecraft.SharedConstants; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.DrawableHelper; +import net.minecraft.client.gui.screen.ConfirmLinkScreen; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen; +import net.minecraft.client.gui.screen.option.AccessibilityOptionsScreen; +import net.minecraft.client.gui.screen.option.LanguageOptionsScreen; +import net.minecraft.client.gui.screen.option.OptionsScreen; +import net.minecraft.client.gui.screen.world.SelectWorldScreen; +import net.minecraft.client.gui.tooltip.Tooltip; +import net.minecraft.client.gui.widget.ButtonWidget; +import net.minecraft.client.gui.widget.PressableTextWidget; +import net.minecraft.client.gui.widget.TexturedButtonWidget; +import net.minecraft.client.render.GameRenderer; +import net.minecraft.client.texture.TextureManager; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; +import net.minecraft.util.Identifier; +import net.minecraft.util.Util; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.RotationAxis; +import org.jetbrains.annotations.Nullable; +import zone.oat.gmodtitlescreen.Mod; +import zone.oat.gmodtitlescreen.ModIdentifier; +import zone.oat.gmodtitlescreen.PressableTextWithTooltipWidget; + +import java.util.Random; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; + +@Environment(EnvType.CLIENT) +public class CustomTitleScreen extends Screen { + public static final Text VERSION_TEXT = Text.translatable("menu.gmod-title-screen.version", SharedConstants.getGameVersion().getName(), FabricLoader.getInstance().getModContainer("gmod-title-screen").get().getMetadata().getVersion().getFriendlyString()); + private static final Identifier ACCESSIBILITY_ICON_TEXTURE = new Identifier("textures/gui/accessibility.png"); + private final boolean isMinceraft; + @Nullable + private String splashText; + private static final Identifier MINECRAFT_TITLE_TEXTURE = new Identifier("textures/gui/title/minecraft.png"); + private static final Identifier EDITION_TITLE_TEXTURE = new Identifier("textures/gui/title/edition.png"); + private static final Identifier GMOD_TITLE_TEXTURE = new ModIdentifier("textures/gui/title/gmod_title.png"); + + private PressableTextWidget version; + + private class SmallPressableTextWidget extends PressableTextWidget { + public SmallPressableTextWidget(int x, int y, int width, int height, Text text, PressAction onPress, TextRenderer textRenderer) { + super(x, y, width, height, text, onPress, textRenderer); + } + + public boolean shouldDownscale() { + return this.width > CustomTitleScreen.this.width * 0.6f; + } + + @Override + public void renderButton(MatrixStack matrices, int mouseX, int mouseY, float delta) { + matrices.push(); + if (shouldDownscale()) { + matrices.translate(CustomTitleScreen.this.width, 0d, 0d); + matrices.scale(0.5f, 0.5f, 1.0f); + matrices.translate(-CustomTitleScreen.this.width, 0d, 0d); + } + + int padding = 3; + + RenderSystem.disableBlend(); + RenderSystem.setShader(GameRenderer::getPositionTexProgram); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + DrawableHelper.fill(matrices, version.getX() - padding, version.getY() - padding, version.getX() + version.getWidth() + padding * 2, version.getY() + version.getHeight() + padding * 2, 0xFF111111); + + super.renderButton(matrices, mouseX, mouseY, delta); + + matrices.pop(); + } + } + + private static CompletableFuture loadBackgroundTexturesAsync(TextureManager textureManager, Executor executor) { + return SlideshowBackground.loadBackgroundTexturesAsync(textureManager, executor); + } + + private void openLink(String url) { + this.client.setScreen(new ConfirmLinkScreen(openInBrowser -> { + if (openInBrowser) { + Util.getOperatingSystem().open(url); + } + + this.client.setScreen(this); + }, url, true)); + } + + public CustomTitleScreen() { + super(Text.translatable("narrator.screen.title")); + this.isMinceraft = (double)new Random().nextFloat() < 1.0E-4; + } + + public static CompletableFuture loadTexturesAsync(TextureManager textureManager, Executor executor) { + return CompletableFuture.allOf( + textureManager.loadTextureAsync(MINECRAFT_TITLE_TEXTURE, executor), + textureManager.loadTextureAsync(EDITION_TITLE_TEXTURE, executor), + textureManager.loadTextureAsync(GMOD_TITLE_TEXTURE, executor), + loadBackgroundTexturesAsync(textureManager, executor) + ); + } + + @Override + public boolean shouldPause() { + return false; + } + + @Override + public boolean shouldCloseOnEsc() { + return false; + } + + private int getXPadding() { + return this.width / 22; + } + + private int getLogoY() { + if (Mod.config.showGModLogo) { + return this.height / 32; + } else { + return this.height / 12; + } + } + + private int getLogoHeight() { + if (Mod.config.showGModLogo) { + return 75; + } else { + return 50; + } + } + + private double getSplashTextX() { + if (Mod.config.showGModLogo) { + return 220d; + } else { + return 260d; + } + } + + @Override + protected void init() { + if (this.splashText == null) { + this.splashText = this.client.getSplashTextLoader().get(); + } + + int versionWidth = this.textRenderer.getWidth(VERSION_TEXT) - 1; + int versionX = this.width - versionWidth; + int buttonsX = getXPadding(); + int buttonsY = getLogoY() * 2 + getLogoHeight(); + + int buttonHeight = 12; + int buttonSpacing = buttonHeight + 1; + int buttonSectionSpacing = 6; + + this.addDrawableChild(new PressableTextWidget( + buttonsX, + buttonsY, + 130, + buttonHeight, + Text.translatable("menu.gmod-title-screen.singleplayer"), + button -> this.client.setScreen(new SelectWorldScreen(this)), + this.textRenderer + )); + + this.addDrawableChild(new PressableTextWidget( + buttonsX, + buttonsY + buttonSpacing * 1, + 130, + buttonHeight, + Text.translatable("menu.gmod-title-screen.multiplayer"), + button -> { + this.client.setScreen(new MultiplayerScreen(this)); + }, + this.textRenderer + )); + + boolean modsButtonActive = FabricLoader.getInstance().isModLoaded("modmenu"); + if (modsButtonActive) { + var modsButton = this.addDrawableChild(new PressableTextWidget( + buttonsX, + buttonsY + buttonSpacing * 2 + buttonSectionSpacing, + 98, + buttonHeight, + Text.translatable("menu.gmod-title-screen.modmenu"), + button -> this.client.setScreen(new ModsScreen(this)), + textRenderer + )); + modsButton.active = true; + } else { + var modsButton = this.addDrawableChild(new PressableTextWithTooltipWidget( + buttonsX, + buttonsY + buttonSpacing * 2 + buttonSectionSpacing, + 98, + buttonHeight, + Text.translatable("menu.gmod-title-screen.modmenu").formatted(Formatting.GRAY), + button -> {}, + textRenderer, + Tooltip.of(Text.translatable("menu.gmod-title-screen.modmenu.not-installed"), Text.translatable("menu.gmod-title-screen.modmenu.not-installed")) + )); + modsButton.active = false; + } + + this.addDrawableChild(new PressableTextWidget( + buttonsX, + buttonsY + buttonSpacing * 3 + buttonSectionSpacing, + 98, + buttonHeight, + Text.translatable("menu.gmod-title-screen.dupes").formatted(Formatting.GRAY), + button -> {}, + textRenderer + )).active = false; + this.addDrawableChild(new PressableTextWidget( + buttonsX, + buttonsY + buttonSpacing * 4 + buttonSectionSpacing, + 98, + buttonHeight, + Text.translatable("menu.gmod-title-screen.demos").formatted(Formatting.GRAY), + button -> {}, + textRenderer + )).active = false; + this.addDrawableChild(new PressableTextWidget( + buttonsX, + buttonsY + buttonSpacing * 5 + buttonSectionSpacing, + 98, + buttonHeight, + Text.translatable("menu.gmod-title-screen.saves").formatted(Formatting.GRAY), + button -> {}, + textRenderer + )).active = false; + + this.addDrawableChild(new PressableTextWidget( + buttonsX, + buttonsY + buttonSpacing * 6 + buttonSectionSpacing * 2, + 98, + buttonHeight, + Text.translatable("menu.gmod-title-screen.options"), + button -> this.client.setScreen(new OptionsScreen(this, this.client.options)), + textRenderer + )); + + this.addDrawableChild(new PressableTextWidget( + buttonsX, + buttonsY + buttonSpacing * 7 + buttonSectionSpacing * 3, + 98, + buttonHeight, + Text.translatable("menu.gmod-title-screen.quit"), + button -> this.client.scheduleStop(), + textRenderer + )); + + this.addDrawableChild( + new TexturedButtonWidget( + this.width - 22, + this.height - 22, + 20, + 20, + 0, + 106, + 20, + ButtonWidget.WIDGETS_TEXTURE, + 256, + 256, + button -> this.client.setScreen(new LanguageOptionsScreen(this, this.client.options, this.client.getLanguageManager())), + Text.translatable("narrator.button.language") + ) + ); + this.addDrawableChild(new TexturedButtonWidget( + this.width - 22 - 22, + this.height - 22, + 20, + 20, + 0, + 0, + 20, + ACCESSIBILITY_ICON_TEXTURE, + 32, + 64, + button -> this.client.setScreen(new AccessibilityOptionsScreen(this, this.client.options)), + Text.translatable("narrator.button.accessibility") + )); + + version = this.addDrawableChild( + new SmallPressableTextWidget( + versionX - 8, 6, versionWidth, 7, VERSION_TEXT, button -> openLink("https://git.oat.zone/oat/gmod-title-screen"), this.textRenderer + ) + ); + version.setAlpha(0.8f); + } + + @Override + public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { + int logoX = getXPadding(); + int logoY = getLogoY(); + + SlideshowBackground.render(matrices, delta, this.width, this.height); + + RenderSystem.disableBlend(); + RenderSystem.setShader(GameRenderer::getPositionTexProgram); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + + int gradientWidth = (int)(this.width * 0.7); + + matrices.push(); + matrices.translate(gradientWidth/2f, this.height/2f, 0); + matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(-90f)); + DrawableHelper.fillGradient(matrices, -(int)Math.floor(this.height/2f), -(int)Math.floor(gradientWidth/2f) - 1, (int)Math.ceil(this.height/2f), (int)Math.ceil(gradientWidth/2f), 0x7b000000, 0x00000000, 0); + matrices.pop(); + + DrawableHelper.fill(matrices, 0, this.height - 24, this.width, this.height, 0x70111111); + + if (Mod.config.showGModLogo) { + RenderSystem.setShader(GameRenderer::getPositionTexProgram); + //RenderSystem.defaultBlendFunc(); + RenderSystem.enableBlend(); + RenderSystem.blendFunc(GlStateManager.SrcFactor.ONE, GlStateManager.DstFactor.ONE_MINUS_SRC_ALPHA); + RenderSystem.setShaderTexture(0, GMOD_TITLE_TEXTURE); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + + this.drawTexture(matrices, logoX, logoY, 0, 0, 256, 256); + + RenderSystem.disableBlend(); + RenderSystem.defaultBlendFunc(); + } else { + RenderSystem.setShader(GameRenderer::getPositionTexProgram); + RenderSystem.setShaderTexture(0, MINECRAFT_TITLE_TEXTURE); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + if (this.isMinceraft) { + this.drawWithOutline(logoX, logoY, (x, y) -> { + this.drawTexture(matrices, x + 0, y, 0, 0, 99, 44); + this.drawTexture(matrices, x + 99, y, 129, 0, 27, 44); + this.drawTexture(matrices, x + 99 + 26, y, 126, 0, 3, 44); + this.drawTexture(matrices, x + 99 + 26 + 3, y, 99, 0, 26, 44); + this.drawTexture(matrices, x + 155, y, 0, 45, 155, 44); + }); + } else { + this.drawWithOutline(logoX, logoY, (x, y) -> { + this.drawTexture(matrices, x + 0, y, 0, 0, 155, 44); + this.drawTexture(matrices, x + 155, y, 0, 45, 155, 44); + }); + } + } + + /* + RenderSystem.setShaderTexture(0, EDITION_TITLE_TEXTURE); + drawTexture(matrices, logoX + 88, logoY + 37, 0.0F, 0.0F, 98, 14, 128, 16); + */ + + if (this.splashText != null && Mod.config.showSplashText) { + matrices.push(); + matrices.translate(getSplashTextX(), logoY + getLogoHeight() - 10, 0.0); + matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(-20.0F)); + float h = 1.8F - MathHelper.abs(MathHelper.sin((float)(Util.getMeasuringTimeMs() % 1000L) / 1000.0F * (float) (Math.PI * 2)) * 0.1F); + h = h * 100.0F / (float)(this.textRenderer.getWidth(this.splashText) + 32); + matrices.scale(h, h, h); + drawCenteredTextWithShadow(matrices, this.textRenderer, this.splashText, 0, -8, 16776960); + matrices.pop(); + } + + super.render(matrices, mouseX, mouseY, delta); + } +} diff --git a/remappedSrc/zone/oat/gmodtitlescreen/screen/SlideshowBackground.java b/remappedSrc/zone/oat/gmodtitlescreen/screen/SlideshowBackground.java new file mode 100644 index 0000000..bca112b --- /dev/null +++ b/remappedSrc/zone/oat/gmodtitlescreen/screen/SlideshowBackground.java @@ -0,0 +1,103 @@ +package zone.oat.gmodtitlescreen.screen; + +import com.mojang.blaze3d.platform.GlStateManager; +import com.mojang.blaze3d.systems.RenderSystem; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.render.GameRenderer; +import net.minecraft.client.texture.TextureManager; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.client.util.math.Vector2f; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.RotationAxis; +import zone.oat.gmodtitlescreen.ModIdentifier; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; + +import static net.minecraft.client.gui.DrawableHelper.drawTexture; + +@Environment(EnvType.CLIENT) +public class SlideshowBackground { + private static final Identifier[] BACKGROUNDS = { + new ModIdentifier("textures/gui/title/background/background_0.png"), + new ModIdentifier("textures/gui/title/background/background_1.png"), + new ModIdentifier("textures/gui/title/background/background_2.png"), + new ModIdentifier("textures/gui/title/background/background_3.png"), + new ModIdentifier("textures/gui/title/background/background_4.png"), + new ModIdentifier("textures/gui/title/background/background_5.png"), + new ModIdentifier("textures/gui/title/background/background_6.png"), + }; + private static final Integer[][] BACKGROUND_SIZES = { + {960, 528}, + {960, 528}, + {960, 528}, + {960, 528}, + {960, 528}, + {960, 528}, + {960, 528}, + }; + private static final float SLIDESHOW_IMAGE_LENGTH = 400f; + private static final float TRANSITION_LENGTH = 30f; + private static float t = TRANSITION_LENGTH; + + public static CompletableFuture loadBackgroundTexturesAsync(TextureManager textureManager, Executor executor) { + CompletableFuture[] completableFutures = new CompletableFuture[BACKGROUNDS.length]; + + for(int i = 0; i < completableFutures.length; ++i) { + completableFutures[i] = textureManager.loadTextureAsync(BACKGROUNDS[i], executor); + } + + return CompletableFuture.allOf(completableFutures); + } + + private static void renderBackground(MatrixStack matrices, float a, int backgroundIndex, float alpha, int width, int height) { + matrices.push(); + + Identifier bg = BACKGROUNDS[backgroundIndex]; + Integer[] backgroundSize = BACKGROUND_SIZES[backgroundIndex]; + float baseScale = Math.max(width / (float) backgroundSize[0], height / (float) backgroundSize[1]); + Vector2f overscan = new Vector2f(backgroundSize[0] * baseScale - width, backgroundSize[1] * baseScale - height); + + RenderSystem.setShader(GameRenderer::getPositionTexProgram); + RenderSystem.setShaderTexture(0, bg); + RenderSystem.enableBlend(); + RenderSystem.blendFunc(GlStateManager.SrcFactor.SRC_ALPHA, GlStateManager.DstFactor.ONE_MINUS_SRC_ALPHA); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, alpha); + + float scale = MathHelper.lerp(a, 1.1f, 1.2f); + float angle = MathHelper.lerp(a, -1f, 3f); + + matrices.translate(width / 2f, height / 2f, 0f); + matrices.scale(scale, scale, 1f); + matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(angle)); + drawTexture( + matrices, + (int) Math.floor(-overscan.getX()/2f - width/2f), + (int) Math.floor(-overscan.getY()/2f - height/2f), + width + (int) Math.ceil(overscan.getX()), + height + (int) Math.ceil(overscan.getY()), + 0.0F, + 0.0F, + 1, 1, 1, 1 + ); + matrices.translate(width / 2f, height / 2f, 0f); + + matrices.pop(); + } + + public static void render(MatrixStack matrices, float delta, int width, int height) { + t += delta; + + int index = (int) Math.floor(t / SLIDESHOW_IMAGE_LENGTH) % BACKGROUNDS.length; + int previousIndex = (index - 1 + BACKGROUNDS.length) % BACKGROUNDS.length; + float a = (t % SLIDESHOW_IMAGE_LENGTH) / SLIDESHOW_IMAGE_LENGTH; + float transition = MathHelper.clamp(a / (TRANSITION_LENGTH / SLIDESHOW_IMAGE_LENGTH), 0f, 1f); + + if (transition < 1f) { + renderBackground(matrices, a + 1f, previousIndex, 1f, width, height); + } + renderBackground(matrices, a, index, transition, width, height); + } +} diff --git a/src/main/java/zone/oat/gmodtitlescreen/screen/CustomTitleScreen.java b/src/main/java/zone/oat/gmodtitlescreen/screen/CustomTitleScreen.java index f640fd8..3ea80f5 100644 --- a/src/main/java/zone/oat/gmodtitlescreen/screen/CustomTitleScreen.java +++ b/src/main/java/zone/oat/gmodtitlescreen/screen/CustomTitleScreen.java @@ -1,6 +1,5 @@ package zone.oat.gmodtitlescreen.screen; -import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; import com.terraformersmc.modmenu.gui.ModsScreen; import net.fabricmc.api.EnvType; @@ -8,9 +7,11 @@ import net.fabricmc.api.Environment; import net.fabricmc.loader.api.FabricLoader; import net.minecraft.SharedConstants; import net.minecraft.client.font.TextRenderer; -import net.minecraft.client.gui.DrawableHelper; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.LogoDrawer; import net.minecraft.client.gui.screen.ConfirmLinkScreen; import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screen.SplashTextRenderer; import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen; import net.minecraft.client.gui.screen.option.AccessibilityOptionsScreen; import net.minecraft.client.gui.screen.option.LanguageOptionsScreen; @@ -27,14 +28,13 @@ import net.minecraft.text.Text; import net.minecraft.util.Formatting; import net.minecraft.util.Identifier; import net.minecraft.util.Util; -import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.RotationAxis; import org.jetbrains.annotations.Nullable; import zone.oat.gmodtitlescreen.Mod; import zone.oat.gmodtitlescreen.ModIdentifier; import zone.oat.gmodtitlescreen.PressableTextWithTooltipWidget; -import java.util.Random; +import java.util.Objects; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; @@ -42,11 +42,9 @@ import java.util.concurrent.Executor; public class CustomTitleScreen extends Screen { public static final Text VERSION_TEXT = Text.translatable("menu.gmod-title-screen.version", SharedConstants.getGameVersion().getName(), FabricLoader.getInstance().getModContainer("gmod-title-screen").get().getMetadata().getVersion().getFriendlyString()); private static final Identifier ACCESSIBILITY_ICON_TEXTURE = new Identifier("textures/gui/accessibility.png"); - private final boolean isMinceraft; + private final LogoDrawer logoDrawer; @Nullable - private String splashText; - private static final Identifier MINECRAFT_TITLE_TEXTURE = new Identifier("textures/gui/title/minecraft.png"); - private static final Identifier EDITION_TITLE_TEXTURE = new Identifier("textures/gui/title/edition.png"); + private SplashTextRenderer splashText; private static final Identifier GMOD_TITLE_TEXTURE = new ModIdentifier("textures/gui/title/gmod_title.png"); private PressableTextWidget version; @@ -61,7 +59,8 @@ public class CustomTitleScreen extends Screen { } @Override - public void renderButton(MatrixStack matrices, int mouseX, int mouseY, float delta) { + public void renderButton(DrawContext ctx, int mouseX, int mouseY, float delta) { + MatrixStack matrices = ctx.getMatrices(); matrices.push(); if (shouldDownscale()) { matrices.translate(CustomTitleScreen.this.width, 0d, 0d); @@ -74,9 +73,9 @@ public class CustomTitleScreen extends Screen { RenderSystem.disableBlend(); RenderSystem.setShader(GameRenderer::getPositionTexProgram); RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); - DrawableHelper.fill(matrices, version.getX() - padding, version.getY() - padding, version.getX() + version.getWidth() + padding * 2, version.getY() + version.getHeight() + padding * 2, 0xFF111111); + ctx.fill(version.getX() - padding, version.getY() - padding, version.getX() + version.getWidth() + padding * 2, version.getY() + version.getHeight() + padding * 2, 0xFF111111); - super.renderButton(matrices, mouseX, mouseY, delta); + super.renderButton(ctx, mouseX, mouseY, delta); matrices.pop(); } @@ -97,14 +96,16 @@ public class CustomTitleScreen extends Screen { } public CustomTitleScreen() { + this(null); + } + + public CustomTitleScreen(@Nullable LogoDrawer logoDrawer) { super(Text.translatable("narrator.screen.title")); - this.isMinceraft = (double)new Random().nextFloat() < 1.0E-4; + this.logoDrawer = Objects.requireNonNullElseGet(logoDrawer, () -> new LogoDrawer(false)); } public static CompletableFuture loadTexturesAsync(TextureManager textureManager, Executor executor) { return CompletableFuture.allOf( - textureManager.loadTextureAsync(MINECRAFT_TITLE_TEXTURE, executor), - textureManager.loadTextureAsync(EDITION_TITLE_TEXTURE, executor), textureManager.loadTextureAsync(GMOD_TITLE_TEXTURE, executor), loadBackgroundTexturesAsync(textureManager, executor) ); @@ -299,11 +300,15 @@ public class CustomTitleScreen extends Screen { } @Override - public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { + public void render(DrawContext ctx, int mouseX, int mouseY, float delta) { + MatrixStack matrices = ctx.getMatrices(); + int logoX = getXPadding(); + // reverse of `int i = screenWidth / 2 - 128;` + int logoXMiddle = (logoX + 128) * 2; int logoY = getLogoY(); - SlideshowBackground.render(matrices, delta, this.width, this.height); + SlideshowBackground.render(ctx, delta, this.width, this.height); RenderSystem.disableBlend(); RenderSystem.setShader(GameRenderer::getPositionTexProgram); @@ -314,41 +319,25 @@ public class CustomTitleScreen extends Screen { matrices.push(); matrices.translate(gradientWidth/2f, this.height/2f, 0); matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(-90f)); - DrawableHelper.fillGradient(matrices, -(int)Math.floor(this.height/2f), -(int)Math.floor(gradientWidth/2f) - 1, (int)Math.ceil(this.height/2f), (int)Math.ceil(gradientWidth/2f), 0x7b000000, 0x00000000, 0); + ctx.fillGradient(-(int)Math.floor(this.height/2f), -(int)Math.floor(gradientWidth/2f) - 1, (int)Math.ceil(this.height/2f), (int)Math.ceil(gradientWidth/2f), 0x7b000000, 0x00000000, 0); matrices.pop(); - DrawableHelper.fill(matrices, 0, this.height - 24, this.width, this.height, 0x70111111); + ctx.fill(0, this.height - 24, this.width, this.height, 0x70111111); if (Mod.config.showGModLogo) { - RenderSystem.setShader(GameRenderer::getPositionTexProgram); + /*RenderSystem.setShader(GameRenderer::getPositionTexProgram); //RenderSystem.defaultBlendFunc(); RenderSystem.enableBlend(); RenderSystem.blendFunc(GlStateManager.SrcFactor.ONE, GlStateManager.DstFactor.ONE_MINUS_SRC_ALPHA); RenderSystem.setShaderTexture(0, GMOD_TITLE_TEXTURE); RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); - this.drawTexture(matrices, logoX, logoY, 0, 0, 256, 256); + this.drawTexture(ctx, logoX, logoY, 0, 0, 256, 256); RenderSystem.disableBlend(); - RenderSystem.defaultBlendFunc(); + RenderSystem.defaultBlendFunc();*/ } else { - RenderSystem.setShader(GameRenderer::getPositionTexProgram); - RenderSystem.setShaderTexture(0, MINECRAFT_TITLE_TEXTURE); - RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); - if (this.isMinceraft) { - this.drawWithOutline(logoX, logoY, (x, y) -> { - this.drawTexture(matrices, x + 0, y, 0, 0, 99, 44); - this.drawTexture(matrices, x + 99, y, 129, 0, 27, 44); - this.drawTexture(matrices, x + 99 + 26, y, 126, 0, 3, 44); - this.drawTexture(matrices, x + 99 + 26 + 3, y, 99, 0, 26, 44); - this.drawTexture(matrices, x + 155, y, 0, 45, 155, 44); - }); - } else { - this.drawWithOutline(logoX, logoY, (x, y) -> { - this.drawTexture(matrices, x + 0, y, 0, 0, 155, 44); - this.drawTexture(matrices, x + 155, y, 0, 45, 155, 44); - }); - } + logoDrawer.draw(ctx, logoXMiddle, 1.0f, logoY); } /* @@ -357,6 +346,10 @@ public class CustomTitleScreen extends Screen { */ if (this.splashText != null && Mod.config.showSplashText) { + this.splashText.render(ctx, logoXMiddle, this.textRenderer, 0xFF000000); + } + + /*if (this.splashText != null && Mod.config.showSplashText) { matrices.push(); matrices.translate(getSplashTextX(), logoY + getLogoHeight() - 10, 0.0); matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(-20.0F)); @@ -365,8 +358,8 @@ public class CustomTitleScreen extends Screen { matrices.scale(h, h, h); drawCenteredTextWithShadow(matrices, this.textRenderer, this.splashText, 0, -8, 16776960); matrices.pop(); - } + }*/ - super.render(matrices, mouseX, mouseY, delta); + super.render(ctx, mouseX, mouseY, delta); } } diff --git a/src/main/java/zone/oat/gmodtitlescreen/screen/SlideshowBackground.java b/src/main/java/zone/oat/gmodtitlescreen/screen/SlideshowBackground.java index bca112b..11863b8 100644 --- a/src/main/java/zone/oat/gmodtitlescreen/screen/SlideshowBackground.java +++ b/src/main/java/zone/oat/gmodtitlescreen/screen/SlideshowBackground.java @@ -4,6 +4,7 @@ import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; +import net.minecraft.client.gui.DrawContext; import net.minecraft.client.render.GameRenderer; import net.minecraft.client.texture.TextureManager; import net.minecraft.client.util.math.MatrixStack; @@ -16,8 +17,6 @@ import zone.oat.gmodtitlescreen.ModIdentifier; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; -import static net.minecraft.client.gui.DrawableHelper.drawTexture; - @Environment(EnvType.CLIENT) public class SlideshowBackground { private static final Identifier[] BACKGROUNDS = { @@ -52,7 +51,9 @@ public class SlideshowBackground { return CompletableFuture.allOf(completableFutures); } - private static void renderBackground(MatrixStack matrices, float a, int backgroundIndex, float alpha, int width, int height) { + private static void renderBackground(DrawContext ctx, float a, int backgroundIndex, float alpha, int width, int height) { + MatrixStack matrices = ctx.getMatrices(); + matrices.push(); Identifier bg = BACKGROUNDS[backgroundIndex]; @@ -72,8 +73,8 @@ public class SlideshowBackground { matrices.translate(width / 2f, height / 2f, 0f); matrices.scale(scale, scale, 1f); matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(angle)); - drawTexture( - matrices, + ctx.drawTexture( + bg, (int) Math.floor(-overscan.getX()/2f - width/2f), (int) Math.floor(-overscan.getY()/2f - height/2f), width + (int) Math.ceil(overscan.getX()), @@ -87,7 +88,7 @@ public class SlideshowBackground { matrices.pop(); } - public static void render(MatrixStack matrices, float delta, int width, int height) { + public static void render(DrawContext ctx, float delta, int width, int height) { t += delta; int index = (int) Math.floor(t / SLIDESHOW_IMAGE_LENGTH) % BACKGROUNDS.length; @@ -96,8 +97,8 @@ public class SlideshowBackground { float transition = MathHelper.clamp(a / (TRANSITION_LENGTH / SLIDESHOW_IMAGE_LENGTH), 0f, 1f); if (transition < 1f) { - renderBackground(matrices, a + 1f, previousIndex, 1f, width, height); + renderBackground(ctx, a + 1f, previousIndex, 1f, width, height); } - renderBackground(matrices, a, index, transition, width, height); + renderBackground(ctx, a, index, transition, width, height); } } diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 4eee906..def414f 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -30,13 +30,13 @@ ], "depends": { - "fabricloader": ">=0.14.6", + "fabricloader": ">=0.14.22", "fabric": "*", - "minecraft": ["1.19.4"], + "minecraft": ["1.20.1"], "java": ">=17", - "cloth-config": ">=6.0.0" + "cloth-config": ">=11.0.0" }, "recommends": { - "modmenu": ">=3.0.0" + "modmenu": ">=7.0.0" } }