From 2eb811c8f7e61c6632530218298db09481a16dae Mon Sep 17 00:00:00 2001 From: kirillsaint Date: Fri, 7 Jul 2023 23:38:03 +0600 Subject: [PATCH] New Main Menu --- .../java/net/silentclient/client/Client.java | 7 +- .../client/gui/minecraft/GuiMainMenu.java | 6 + .../client/gui/silentmainmenu/MenuButton.java | 51 +++++ .../gui/silentmainmenu/SilentMainMenu.java | 193 ++++++++++++++++++ .../client/mixin/mixins/MinecraftMixin.java | 9 +- .../minecraft/silentclient/icons/back.png | Bin 0 -> 699 bytes .../minecraft/silentclient/icons/language.png | Bin 1256 -> 2641 bytes 7 files changed, 259 insertions(+), 7 deletions(-) create mode 100644 src/main/java/net/silentclient/client/gui/silentmainmenu/MenuButton.java create mode 100644 src/main/java/net/silentclient/client/gui/silentmainmenu/SilentMainMenu.java create mode 100644 src/main/resources/assets/minecraft/silentclient/icons/back.png diff --git a/src/main/java/net/silentclient/client/Client.java b/src/main/java/net/silentclient/client/Client.java index 33a7982..2c523da 100644 --- a/src/main/java/net/silentclient/client/Client.java +++ b/src/main/java/net/silentclient/client/Client.java @@ -20,7 +20,6 @@ import net.silentclient.client.gui.clickgui.ClickGUI; import net.silentclient.client.gui.font.SilentFontRenderer; import net.silentclient.client.gui.util.BackgroundPanorama; import net.silentclient.client.keybinds.KeyBindManager; -import net.silentclient.client.mixin.SilentClientTweaker; import net.silentclient.client.mods.ModInstances; import net.silentclient.client.mods.SettingsManager; import net.silentclient.client.mods.settings.FPSBoostMod; @@ -137,7 +136,7 @@ public class Client { } logger.info("---------[ Silent Client Initialising ]---------"); logger.info("MC Version: 1.8.9"); - logger.info("SC Version: " + getVersion()); + logger.info("SC Version: " + getFullVersion()); logger.info("Width: " + Minecraft.getMinecraft().displayWidth); logger.info("Height: " + Minecraft.getMinecraft().displayHeight); logger.info("Fullscreen: " + Minecraft.getMinecraft().isFullScreen()); @@ -472,6 +471,10 @@ public class Client { } public String getVersion() { + return version; + } + + public String getFullVersion() { return "v" + version + "-" + getBuildData().getCommit() + "-" + getBuildData().getBranch(); } diff --git a/src/main/java/net/silentclient/client/gui/minecraft/GuiMainMenu.java b/src/main/java/net/silentclient/client/gui/minecraft/GuiMainMenu.java index 49cb6a0..37be777 100644 --- a/src/main/java/net/silentclient/client/gui/minecraft/GuiMainMenu.java +++ b/src/main/java/net/silentclient/client/gui/minecraft/GuiMainMenu.java @@ -5,6 +5,7 @@ import java.net.URI; import java.util.Random; import net.minecraft.client.gui.*; +import net.silentclient.client.gui.silentmainmenu.SilentMainMenu; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.lwjgl.opengl.GLContext; @@ -143,6 +144,7 @@ public class GuiMainMenu extends GuiScreen implements GuiYesNoCallback this.buttonList.add(new IconButton(88, 4, 5, new ResourceLocation("silentclient/icons/news.png"))); this.buttonList.add(cosmetics = new IconButton(87, 26, 5, new ResourceLocation("silentclient/icons/settings/cosmetics.png"))); + this.buttonList.add(new IconButton(89, 48, 5, new ResourceLocation("silentclient/icons/back.png"))); if (this.mc.isDemo()) { this.addDemoButtons(j, 24); @@ -219,6 +221,10 @@ public class GuiMainMenu extends GuiScreen implements GuiYesNoCallback this.mc.displayGuiScreen(new GuiMultiplayer(this)); } + if(button.id == 89) { + mc.displayGuiScreen(new SilentMainMenu()); + } + if (button.id == 14 && this.realmsButton.visible) { this.switchToRealms(); diff --git a/src/main/java/net/silentclient/client/gui/silentmainmenu/MenuButton.java b/src/main/java/net/silentclient/client/gui/silentmainmenu/MenuButton.java new file mode 100644 index 0000000..19843c9 --- /dev/null +++ b/src/main/java/net/silentclient/client/gui/silentmainmenu/MenuButton.java @@ -0,0 +1,51 @@ +package net.silentclient.client.gui.silentmainmenu; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.audio.SoundHandler; +import net.minecraft.client.gui.GuiButton; +import net.silentclient.client.Client; +import net.silentclient.client.gui.font.SilentFontRenderer; +import net.silentclient.client.gui.util.RenderUtil; +import net.silentclient.client.mods.settings.GeneralMod; +import net.silentclient.client.utils.TimerUtils; + +import java.awt.*; + +public class MenuButton extends GuiButton { + private int animatedOpcaity = 0; + private TimerUtils animateTimer = new TimerUtils(); + + public MenuButton(int buttonId, int x, int y, String buttonText) { + super(buttonId, x, y, 80, 20, buttonText); + } + + @Override + public void drawButton(Minecraft mc, int mouseX, int mouseY) { + this.hovered = mouseX >= this.xPosition && mouseY >= this.yPosition && mouseX < this.xPosition + this.width && mouseY < this.yPosition + this.height; + + RenderUtil.drawRoundedRect(this.xPosition, this.yPosition, 80, 20, 1, new Color(20, 20, 20, 102).getRGB()); + RenderUtil.drawRoundedRect(xPosition, yPosition, width, height, 1, new Color(255, 255, 255, animatedOpcaity).getRGB()); + RenderUtil.drawRoundedOutline(this.xPosition, this.yPosition, 80, 20, 1, 1, new Color(214, 213, 210).getRGB()); + Client.getInstance().getSilentFontRenderer().drawCenteredString(this.displayString, this.xPosition + 40, this.yPosition + 3, 14, SilentFontRenderer.FontType.TITLE, 70); + + if (this.hovered && this.enabled) { + if (this.animatedOpcaity < 75 && animateTimer.delay(30)) { + this.animatedOpcaity += 15; + animateTimer.reset(); + } + } else { + if (this.animatedOpcaity != 0 && animateTimer.delay(30)) { + this.animatedOpcaity -= 15; + animateTimer.reset(); + } + } + } + + @Override + public void playPressSound(SoundHandler soundHandlerIn) { + if(!Client.getInstance().getSettingsManager().getSettingByClass(GeneralMod.class, "Silent Button Sounds").getValBoolean()) { + return; + } + super.playPressSound(soundHandlerIn); + } +} diff --git a/src/main/java/net/silentclient/client/gui/silentmainmenu/SilentMainMenu.java b/src/main/java/net/silentclient/client/gui/silentmainmenu/SilentMainMenu.java new file mode 100644 index 0000000..e45a472 --- /dev/null +++ b/src/main/java/net/silentclient/client/gui/silentmainmenu/SilentMainMenu.java @@ -0,0 +1,193 @@ +package net.silentclient.client.gui.silentmainmenu; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.*; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.texture.DynamicTexture; +import net.minecraft.util.ResourceLocation; +import net.silentclient.client.Client; +import net.silentclient.client.admin.AdminRender; +import net.silentclient.client.cosmetics.gui.CosmeticsGui; +import net.silentclient.client.gui.GuiNews; +import net.silentclient.client.gui.SilentScreen; +import net.silentclient.client.gui.clickgui.utils.MouseUtils; +import net.silentclient.client.gui.clickgui.utils.RenderUtils; +import net.silentclient.client.gui.font.SilentFontRenderer; +import net.silentclient.client.gui.minecraft.GuiMainMenu; +import net.silentclient.client.gui.util.RenderUtil; +import net.silentclient.client.utils.SCTextureManager; + +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.net.URI; +import java.util.Random; + +public class SilentMainMenu extends SilentScreen { + public static ResourceLocation imageLocation = null; + public static BufferedImage image = null; + public static boolean loading = false; + public static boolean initPanel = false; + + private MenuButton singleplayerButton; + private MenuButton multiplayerButton; + private MenuButton quitGameButton; + + @Override + public void initGui() { + super.initGui(); + this.buttonList.clear(); + Client.backgroundPanorama.updateWidthHeight(this.width, this.height); + + this.buttonList.add(this.singleplayerButton = new MenuButton(1, this.width / 2 - 130, 40, "Singleplayer")); + this.buttonList.add(this.multiplayerButton = new MenuButton(2, this.width / 2 - 40, 40, "Multiplayer")); + this.buttonList.add(this.quitGameButton = new MenuButton(3, this.width / 2 + 50, 40, "Quit Game")); + } + + @Override + public void drawScreen(int mouseX, int mouseY, float partialTicks) { + this.loadPanels(); + GlStateManager.disableAlpha(); + Client.backgroundPanorama.renderSkybox(mouseX, mouseY, partialTicks); + GlStateManager.enableAlpha(); + this.drawGradientRect(0, 0, this.width, this.height, new Color(0, 0, 0, 127).getRGB(), new Color(0, 0, 0, 200).getRGB()); + + this.drawHeader(); + this.drawBlock(mouseX, mouseY); + this.drawFooter(); + + super.drawScreen(mouseX, mouseY, partialTicks); + } + + private void drawBlock(int mouseX, int mouseY) { + int blockY = this.height / 2 - 75; + int blockX = this.width / 2 - 160; + if(blockY < 70) { + blockY = 70; + } + RenderUtils.drawRect(blockX, blockY, 320, 150, new Color(20, 20, 20).getRGB()); + if(imageLocation != null) { + RenderUtil.drawImage(imageLocation, blockX + 78, blockY + 10, 231, 130, false); + } + + int optionY = blockY + 10; + this.drawOptionButton(mouseX, mouseY, blockX + 5, optionY, new ResourceLocation("silentclient/icons/settings/cosmetics.png"), "Cosmetics"); + optionY += 15; + this.drawOptionButton(mouseX, mouseY, blockX + 5, optionY, new ResourceLocation("silentclient/icons/store_icon.png"), "Store"); + optionY += 15; + this.drawOptionButton(mouseX, mouseY, blockX + 5, optionY, new ResourceLocation("silentclient/icons/settings.png"), "Options"); + optionY += 15; + this.drawOptionButton(mouseX, mouseY, blockX + 5, optionY, new ResourceLocation("silentclient/icons/language.png"), "Language"); + optionY += 15; + this.drawOptionButton(mouseX, mouseY, blockX + 5, optionY, new ResourceLocation("silentclient/icons/back.png"), "Vanilla Menu"); + } + + private void drawOptionButton(int mouseX, int mouseY, int x, int y, ResourceLocation icon, String text) { + if(Client.getInstance().getSilentFontRenderer().getStringWidth(text, 12, SilentFontRenderer.FontType.TITLE) > 60) { + int difference = -(60 - Client.getInstance().getSilentFontRenderer().getStringWidth(text, 12, SilentFontRenderer.FontType.TITLE)); + int oneSymbolWidth = Client.getInstance().getSilentFontRenderer().getStringWidth("a", 12, SilentFontRenderer.FontType.TITLE); + int symbolsCount = difference / oneSymbolWidth; + + text = text.substring(0, text.length() - symbolsCount - 3); + text += "..."; + } + if(optionHovered(mouseX, mouseY, x - 5, y)) { + RenderUtils.drawRect(x - 5, y, 75, 15, new Color(255, 255, 255, 70).getRGB()); + } + RenderUtil.drawImage(icon, x, y + 3, 10, 10); + Client.getInstance().getSilentFontRenderer().drawString(text, x + 13, y + 2, 12, SilentFontRenderer.FontType.TITLE); + } + + private boolean optionHovered(int mouseX, int mouseY, int x, int y) { + return MouseUtils.isInside(mouseX, mouseY, x, y, 70, 15); + } + + private void drawHeader() { + RenderUtils.drawRect(0, 0, this.width, 25, new Color(20, 20, 20).getRGB()); + RenderUtil.drawImage(new ResourceLocation("silentclient/logos/logo.png"), this.width / 2 - 48.8F, 3, 97.7F, 19); + } + + private void drawFooter() { + Client.getInstance().getSilentFontRenderer().drawString("Silent Client " + Client.getInstance().getVersion(), 5, this.height - 17, 14, SilentFontRenderer.FontType.TITLE); + Client.getInstance().getSilentFontRenderer().drawString("Version 1.8.9", this.width - (Client.getInstance().getSilentFontRenderer().getStringWidth("Version 1.8.9", 14, SilentFontRenderer.FontType.TITLE)) - 5, this.height - 17, 14, SilentFontRenderer.FontType.TITLE); + } + + private void loadPanels() { + if(image == null && !loading && GuiNews.news != null) { + loading = true; + (new Thread("NewsThread") { + public void run() { + SilentMainMenu.image = SCTextureManager.getImage(GuiNews.news.getItem().getCover()); + SilentMainMenu.loading = false; + } + }).start(); + } + if(image != null && !initPanel) { + imageLocation = Minecraft.getMinecraft().getTextureManager().getDynamicTextureLocation("image_panel_" + new Random().nextLong(), new DynamicTexture(image)); + initPanel = true; + } + } + + @Override + protected void actionPerformed(GuiButton button) throws IOException { + super.actionPerformed(button); + switch (button.id) { + case 1: + mc.displayGuiScreen(new GuiSelectWorld(this)); + break; + case 2: + mc.displayGuiScreen(new GuiMultiplayer(this)); + break; + case 3: + mc.shutdown(); + break; + } + } + + @Override + protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException { + super.mouseClicked(mouseX, mouseY, mouseButton); + int blockX = this.width / 2 - 160; + int blockY = this.height / 2 - 75; + if(blockY < 70) { + blockY = 70; + } + + int optionY = blockY + 10; + if(this.optionHovered(mouseX, mouseY, blockX, optionY)) { + mc.displayGuiScreen(new CosmeticsGui()); + return; + } + optionY += 15; + if(this.optionHovered(mouseX, mouseY, blockX, optionY)) { + try { + Class oclass = Class.forName("java.awt.Desktop"); + Object object = oclass.getMethod("getDesktop", new Class[0]).invoke((Object)null, new Object[0]); + oclass.getMethod("browse", new Class[] {URI.class}).invoke(object, new Object[] {new URI("https://store.silentclient.net/")}); + } catch (Throwable err) { + err.printStackTrace(); + } + return; + } + optionY += 15; + if(this.optionHovered(mouseX, mouseY, blockX, optionY)) { + mc.displayGuiScreen(new GuiOptions(this, mc.gameSettings)); + return; + } + optionY += 15; + if(this.optionHovered(mouseX, mouseY, blockX, optionY)) { + mc.displayGuiScreen(new GuiLanguage(this, mc.gameSettings, mc.getLanguageManager())); + return; + } + optionY += 15; + if(this.optionHovered(mouseX, mouseY, blockX, optionY)) { + mc.displayGuiScreen(new GuiMainMenu()); + } + } + + @Override + public void updateScreen() { + super.updateScreen(); + Client.backgroundPanorama.tickPanorama(); + } +} diff --git a/src/main/java/net/silentclient/client/mixin/mixins/MinecraftMixin.java b/src/main/java/net/silentclient/client/mixin/mixins/MinecraftMixin.java index 46a1c06..760a5a7 100644 --- a/src/main/java/net/silentclient/client/mixin/mixins/MinecraftMixin.java +++ b/src/main/java/net/silentclient/client/mixin/mixins/MinecraftMixin.java @@ -18,7 +18,7 @@ import net.minecraft.util.ResourceLocation; import net.minecraft.world.WorldSettings; import net.silentclient.client.Client; import net.silentclient.client.event.impl.*; -import net.silentclient.client.gui.GuiNews; +import net.silentclient.client.gui.silentmainmenu.SilentMainMenu; import net.silentclient.client.gui.util.BackgroundPanorama; import net.silentclient.client.hooks.MinecraftHook; import net.silentclient.client.mods.render.AnimationsMod; @@ -38,7 +38,6 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import java.io.File; @@ -60,7 +59,7 @@ public abstract class MinecraftMixin { if(Client.backgroundPanorama == null) { Client.backgroundPanorama = new BackgroundPanorama(Minecraft.getMinecraft()); } - displayGuiScreen(new GuiNews()); + displayGuiScreen(new SilentMainMenu()); } @Inject(method = "shutdownMinecraftApplet", at = @At("HEAD")) @@ -70,7 +69,7 @@ public abstract class MinecraftMixin { @Redirect(method = "createDisplay", at = @At(value = "INVOKE", target = "Lorg/lwjgl/opengl/Display;setTitle(Ljava/lang/String;)V")) public void setWindowTitle(String newTitle) { - Display.setTitle("Silent Client " + Client.getInstance().getVersion() + " (1.8.9)"); + Display.setTitle("Silent Client " + Client.getInstance().getFullVersion() + " (1.8.9)"); } @Redirect(method = "", at = @At(value = "INVOKE", target = "Lorg/apache/logging/log4j/Logger;info(Ljava/lang/String;)V", ordinal = 1)) @@ -123,7 +122,7 @@ public abstract class MinecraftMixin { Client.backgroundPanorama = new BackgroundPanorama(Minecraft.getMinecraft()); } if(guiScreenIn instanceof GuiMainMenu) { - displayGuiScreen(new net.silentclient.client.gui.minecraft.GuiMainMenu()); + displayGuiScreen(new SilentMainMenu()); return; } if(guiScreenIn instanceof GuiIngameMenu) { diff --git a/src/main/resources/assets/minecraft/silentclient/icons/back.png b/src/main/resources/assets/minecraft/silentclient/icons/back.png new file mode 100644 index 0000000000000000000000000000000000000000..c9517cebd282daaa8110bbd62d1c514fabc2b04e GIT binary patch literal 699 zcmV;s0!00ZP) z6;T+6eWz6j4!75d~eyef=F~uFM^{&N&Ow_jn$7n0xOG-1~55&K%|ffj}S-xPXYr1KL8@ z=qBx;Z{Z^hdrc>3K}s?4AK?=Ws-ja;o<8_O5<4R&a{wP;NM+8*7TJV$lGp`{SaVG` zKr_i{Y!ho3p?9GbiDzS*)7a2QpFu0h$PQV?PScmrisavVvZwJ2XoWxiq2%9sip-kh zp%t;a&w3Ni($Y|&oY9!1f5cIR<0V;`A==qu=_K>O)8MsK8d zRHR;4!;e^l>3T>1Wp|`Uc$b@-@QY=RaLMwvqReYwxR(7O9XUn?eleQ;ARYXl>VLo% zVfiv2`pXjUIB z@$Bs~k=4^H(2lrW)Ai~{+Q5ik7ctspq#NliXh-bV-iB7uzBm#0W$0h{fY@KtbMOVR zyJhXbCnSF&n}lyL>PwmE9r_bK!mtk#|7CM1@q>aT`kP+D84}?XVcdOgo+RJ1Oc(i_ hsenKr5C{YUh9i5=@5Lle5mo>I002ovPDHLkV1mJ@I?4b5 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/minecraft/silentclient/icons/language.png b/src/main/resources/assets/minecraft/silentclient/icons/language.png index 4eb6ea2e45dcc742b757589caadf8b842a444767..59fd4ab7e1489a72cd2d4c5e86d782add70733b1 100644 GIT binary patch literal 2641 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 SMNW(W0000