блять там 3 строки поменятьну слушай получилось довольно не плохой скид но внизу где серый текст у векса текст белым ссылкой у тебя нету и фон чуть темнее чем у векса а так годно
Смотрите видео ниже, чтобы узнать, как установить наш сайт в качестве веб-приложения на домашнем экране.
Примечание: Эта возможность может быть недоступна в некоторых браузерах.
блять там 3 строки поменятьну слушай получилось довольно не плохой скид но внизу где серый текст у векса текст белым ссылкой у тебя нету и фон чуть темнее чем у векса а так годно
бля очень ахуенноврод похоже хз
фонты думаю сами найдете
векса:код:package rich.screens.menu; import net.minecraft.client.gui.Click; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen; import net.minecraft.client.gui.screen.multiplayer.MultiplayerWarningScreen; import net.minecraft.client.gui.screen.option.OptionsScreen; import net.minecraft.client.gui.screen.world.SelectWorldScreen; import net.minecraft.client.input.KeyInput; import net.minecraft.client.input.CharInput; import net.minecraft.text.Text; import net.minecraft.util.Identifier; import net.minecraft.util.Util; import net.minecraft.util.math.MathHelper; import rich.Initialization; import rich.screens.account.AccountEntry; import rich.screens.account.AccountRenderer; import rich.util.config.impl.account.AccountConfig; import rich.util.render.Render2D; import rich.util.render.font.Fonts; import rich.util.session.SessionChanger; import rich.util.sounds.SoundManager; import antidaunleak.api.UserProfile; import java.awt.*; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.List; import java.util.Random; public class MainMenuScreen extends Screen { private static final Identifier BACKGROUND_TEXTURE = Identifier.of("rich", "textures/menu/backmenu.png"); private static final float FIXED_GUI_SCALE = 2.0f; private static final int PARTICLE_COUNT = 50; private static final float PARTICLE_FADE_THRESHOLD = 0.8f; private static class Particle { float x, y; float vx, vy; float size; float alpha; float lifetime; float maxLifetime; boolean isDead = false; Particle(float x, float y) { this.x = x; this.y = y; Random rand = new Random(); this.vx = (rand.nextFloat() - 0.5f) * 0.2f; this.vy = (rand.nextFloat() - 0.5f) * 0.2f; this.size = 0.5f + rand.nextFloat() * 1f; this.alpha = 0.2f + rand.nextFloat() * 0.3f; this.maxLifetime = 10f + rand.nextFloat() * 10f; this.lifetime = 0f; } void update(float delta, int width, int height) { lifetime += delta / 60f; if (lifetime > maxLifetime * PARTICLE_FADE_THRESHOLD) { float fadeProgress = (lifetime - maxLifetime * PARTICLE_FADE_THRESHOLD) / (maxLifetime * (1f - PARTICLE_FADE_THRESHOLD)); alpha = Math.max(0, alpha * (1f - fadeProgress)); } if (lifetime >= maxLifetime) { isDead = true; return; } x += vx * delta; y += vy * delta; if (x < -10 || x > width + 10 || y < -10 || y > height + 10) { isDead = true; } } } private final List<Particle> particles = new java.util.ArrayList<>(); private boolean particlesInitialized = false; private int lastWindowWidth = 0; private int lastWindowHeight = 0; private enum View { MAIN_MENU, ALT_SCREEN } private View currentView = View.MAIN_MENU; private long screenStartTime = 0L; private boolean initialized = false; private long lastRenderTime = 0L; private int hoveredButton = -1; private float[] buttonHoverProgress = new float[6]; private final AccountRenderer accountRenderer; private final AccountConfig accountConfig; private String nicknameText = ""; private boolean nicknameFieldFocused = false; private float scrollOffset = 0f; private float targetScrollOffset = 0f; public MainMenuScreen() { super(Text.literal("Main Menu")); for (int i = 0; i < 6; i++) { buttonHoverProgress[i] = 0f; } this.accountRenderer = new AccountRenderer(); this.accountConfig = AccountConfig.getInstance(); this.accountConfig.load(); } @Override protected void init() { initialized = false; particlesInitialized = false; } private int getFixedScaledWidth() { return (int) Math.ceil((double) client.getWindow().getFramebufferWidth() / FIXED_GUI_SCALE); } private int getFixedScaledHeight() { return (int) Math.ceil((double) client.getWindow().getFramebufferHeight() / FIXED_GUI_SCALE); } private float toFixedCoord(double coord) { float currentScale = (float) client.getWindow().getScaleFactor(); return (float) (coord * currentScale / FIXED_GUI_SCALE); } private void initParticles(int width, int height) { if (particlesInitialized) return; Random rand = new Random(); for (int i = 0; i < PARTICLE_COUNT; i++) { particles.add(new Particle(rand.nextFloat() * width, rand.nextFloat() * height)); } particlesInitialized = true; } private void drawBackground() { int screenWidth = getFixedScaledWidth(); int screenHeight = getFixedScaledHeight(); Render2D.rect(0, 0, screenWidth, screenHeight, new Color(12, 15, 18).getRGB()); initParticles(screenWidth, screenHeight); for (Particle p : particles) { if (!p.isDead && p.alpha > 0.01f) { int alpha = (int) (p.alpha * 255); Render2D.rect(p.x, p.y, p.size, p.size, new Color(255, 255, 255, alpha).getRGB()); } } } @Override public void render(DrawContext context, int mouseX, int mouseY, float delta) { long currentTime = Util.getMeasuringTimeMs(); if (!initialized) { screenStartTime = currentTime; lastRenderTime = currentTime; initialized = true; } float deltaTime = Math.min(delta, 0.05f); lastRenderTime = currentTime; int fixedWidth = getFixedScaledWidth(); int fixedHeight = getFixedScaledHeight(); if (lastWindowWidth != fixedWidth || lastWindowHeight != fixedHeight) { particles.clear(); particlesInitialized = false; lastWindowWidth = fixedWidth; lastWindowHeight = fixedHeight; } for (Particle p : particles) { p.update(deltaTime * 60f, fixedWidth, fixedHeight); } particles.removeIf(p -> p.isDead); Random rand = new Random(); while (particles.size() < PARTICLE_COUNT) { particles.add(new Particle(rand.nextFloat() * fixedWidth, rand.nextFloat() * fixedHeight)); } float scaledMouseX = toFixedCoord(mouseX); float scaledMouseY = toFixedCoord(mouseY); updateButtonAnimations(deltaTime, scaledMouseX, scaledMouseY, fixedWidth, fixedHeight); Render2D.beginOverlay(); drawBackground(); if (currentView == View.MAIN_MENU) { renderMainMenu(fixedWidth, fixedHeight, scaledMouseX, scaledMouseY); } else { renderAltScreen(fixedWidth, fixedHeight, scaledMouseX, scaledMouseY, currentTime); } Render2D.endOverlay(); } private void renderMainMenu(int screenWidth, int screenHeight, float mouseX, float mouseY) { float centerX = screenWidth / 2f; float centerY = screenHeight / 2f; String username = "user"; float avatarSize = 20; float avatarX = 8; float avatarY = 10; Fonts.INTER_MEDIUM.draw("Logged in as", avatarX + avatarSize + 5, avatarY, 7f, new Color(150, 150, 150).getRGB()); Fonts.INTER_MEDIUM.draw(username, avatarX + avatarSize + 5, avatarY + 9, 8f, new Color(255, 255, 255).getRGB()); Render2D.rect(avatarX, avatarY, avatarSize, avatarSize, new Color(40, 45, 55).getRGB(), avatarSize / 2f); Identifier userAvatar = Identifier.of("rich", "user.png"); int[] avatarColors = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}; float[] avatarRadii = {avatarSize / 2f, avatarSize / 2f, avatarSize / 2f, avatarSize / 2f}; Initialization.getInstance().getManager().getRenderCore().getTexturePipeline() .drawTexture(userAvatar, avatarX, avatarY, avatarSize, avatarSize, 0, 0, 1, 1, avatarColors, avatarRadii, 1f); float logoSize = 35; float logoY = centerY - 90; Identifier logoTexture = Identifier.of("rich", "images/logo.png"); int[] logoColors = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}; float[] logoRadii = {0, 0, 0, 0}; Initialization.getInstance().getManager().getRenderCore().getTexturePipeline() .drawTexture(logoTexture, centerX - logoSize / 2f, logoY, logoSize, logoSize, 0, 0, 1, 1, logoColors, logoRadii, 1f); String timeOfDay = getTimeOfDay(); String greeting = "Good " + timeOfDay + ", "; String usernameColored = username; float greetingWidth = Fonts.INTER_SEMIBOLD.getWidth(greeting, 14f); float usernameWidth = Fonts.INTER_SEMIBOLD.getWidth(usernameColored, 14f); float totalGreetingWidth = greetingWidth + usernameWidth; float greetingStartX = centerX - totalGreetingWidth / 2f; float greetingY = centerY - 38; Fonts.INTER_SEMIBOLD.draw(greeting, greetingStartX, greetingY, 14f, new Color(255, 255, 255).getRGB()); Fonts.INTER_SEMIBOLD.draw(usernameColored, greetingStartX + greetingWidth, greetingY, 14f, new Color(100, 180, 255).getRGB()); String welcomeText = "Welcome to "; String clientName = "WexSide. The best client."; String restText = ""; float welcomeWidth = Fonts.INTER_MEDIUM.getWidth(welcomeText, 9f); float clientWidth = Fonts.INTER_MEDIUM.getWidth(clientName, 9f); float restWidth = Fonts.INTER_MEDIUM.getWidth(restText, 9f); float totalWidth = welcomeWidth + clientWidth + restWidth; float startX = centerX - totalWidth / 2f; float textY = centerY - 20; Fonts.INTER_MEDIUM.draw(welcomeText, startX, textY, 9f, new Color(180, 180, 180).getRGB()); Fonts.INTER_SEMIBOLD.draw(clientName, startX + welcomeWidth, textY, 9f, new Color(90, 22, 134).getRGB()); Fonts.INTER_MEDIUM.draw(restText, startX + welcomeWidth + clientWidth, textY, 9f, new Color(180, 180, 180).getRGB()); float buttonWidth = 220; float buttonHeight = 30; float buttonSpacing = 7; float buttonStartY = centerY + 3; drawButton(centerX - buttonWidth / 2f, buttonStartY, buttonWidth, buttonHeight, "Singleplayer", 0, mouseX, mouseY, new Color(30, 35, 45), false); drawButton(centerX - buttonWidth / 2f, buttonStartY + buttonHeight + buttonSpacing, buttonWidth, buttonHeight, "Multiplayer", 1, mouseX, mouseY, new Color(30, 35, 45), false); float swapAccountsY = buttonStartY + (buttonHeight + buttonSpacing) * 2 + 5; drawButton(centerX - buttonWidth / 2f, swapAccountsY, buttonWidth, buttonHeight, "Swap Accounts", 2, mouseX, mouseY, new Color(90, 22, 134), true); float bottomY = swapAccountsY + buttonHeight + 5; float bottomButtonWidth = 65; float bottomButtonHeight = 20; float bottomSpacing = 10; float totalBottomWidth = bottomButtonWidth * 3 + bottomSpacing * 2; float bottomStartX = centerX - totalBottomWidth / 2f; drawSmallButton(bottomStartX, bottomY, bottomButtonWidth, bottomButtonHeight, "Options", 3, mouseX, mouseY); drawSmallButton(bottomStartX + bottomButtonWidth + bottomSpacing, bottomY, bottomButtonWidth, bottomButtonHeight, "Proxies", 4, mouseX, mouseY); drawSmallButton(bottomStartX + (bottomButtonWidth + bottomSpacing) * 2, bottomY, bottomButtonWidth, bottomButtonHeight, "Exit", 5, mouseX, mouseY); String footerText = "By logging into your account, you agree to all of our policies,"; String policyLinks = "including our Privacy Policy and Terms of Service"; Fonts.INTER_MEDIUM.drawCentered(footerText, centerX, screenHeight - 17, 6.5f, new Color(100, 100, 100).getRGB()); Fonts.INTER_MEDIUM.drawCentered(policyLinks, centerX, screenHeight - 8, 6.5f, new Color(100, 100, 100).getRGB()); } private String getTimeOfDay() { int hour = java.time.LocalTime.now().getHour(); if (hour >= 5 && hour < 12) return "morning"; if (hour >= 12 && hour < 17) return "afternoon"; if (hour >= 17 && hour < 21) return "evening"; return "night"; } private void drawButton(float x, float y, float width, float height, String text, int index, float mouseX, float mouseY, Color baseColor, boolean isPurple) { boolean hovered = isMouseOver(mouseX, mouseY, x, y, width, height); float hoverProgress = buttonHoverProgress[index]; Color bgColor = baseColor; if (isPurple) { int brightness = (int) (hoverProgress * 20); bgColor = new Color( Math.min(255, baseColor.getRed() + brightness), Math.min(255, baseColor.getGreen() + brightness), Math.min(255, baseColor.getBlue() + brightness) ); } else { int brightness = (int) (hoverProgress * 15); bgColor = new Color( Math.min(255, baseColor.getRed() + brightness), Math.min(255, baseColor.getGreen() + brightness), Math.min(255, baseColor.getBlue() + brightness) ); } Render2D.rect(x, y, width, height, bgColor.getRGB(), 8); if (!isPurple) { Render2D.outline(x, y, width, height, 1f, new Color(50, 55, 65, 80).getRGB(), 8); } if (hoverProgress > 0.01f) { int borderAlpha = (int) (hoverProgress * 100); Color borderColor = isPurple ? new Color(138, 43, 226, borderAlpha) : new Color(100, 110, 130, borderAlpha); Render2D.outline(x, y, width, height, 1f, borderColor.getRGB(), 8); } float fontSize = 9f; float textHeight = Fonts.INTER_MEDIUM.getHeight(fontSize); Color textColor = isPurple ? new Color(255, 255, 255) : new Color(160, 160, 160); Fonts.INTER_MEDIUM.drawCentered(text, x + width / 2f, y + (height - textHeight) / 2f, fontSize, textColor.getRGB()); } private void drawSmallButton(float x, float y, float width, float height, String text, int index, float mouseX, float mouseY) { float hoverProgress = buttonHoverProgress[index]; int baseAlpha = 150; int hoverAlpha = (int) (baseAlpha + hoverProgress * 50); float fontSize = 8f; float textHeight = Fonts.INTER_MEDIUM.getHeight(fontSize); Fonts.INTER_MEDIUM.drawCentered(text, x + width / 2f, y + (height - textHeight) / 2f, fontSize, new Color(180, 180, 180, hoverAlpha).getRGB()); } private boolean isMouseOver(float mouseX, float mouseY, float x, float y, float width, float height) { return mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height; } private void updateButtonAnimations(float deltaTime, float mouseX, float mouseY, int screenWidth, int screenHeight) { float centerX = screenWidth / 2f; float centerY = screenHeight / 2f; float lerpSpeed = 1f - (float) Math.pow(0.001f, deltaTime); if (currentView == View.MAIN_MENU) { float buttonWidth = 220; float buttonHeight = 30; float buttonSpacing = 7; float buttonStartY = centerY + 3; for (int i = 0; i < 2; i++) { float y = buttonStartY + i * (buttonHeight + buttonSpacing); boolean hovered = isMouseOver(mouseX, mouseY, centerX - buttonWidth / 2f, y, buttonWidth, buttonHeight); float target = hovered ? 1f : 0f; buttonHoverProgress[i] = MathHelper.lerp(lerpSpeed, buttonHoverProgress[i], target); } float swapAccountsY = buttonStartY + (buttonHeight + buttonSpacing) * 2 + 5; boolean swapHovered = isMouseOver(mouseX, mouseY, centerX - buttonWidth / 2f, swapAccountsY, buttonWidth, buttonHeight); buttonHoverProgress[2] = MathHelper.lerp(lerpSpeed, buttonHoverProgress[2], swapHovered ? 1f : 0f); float bottomY = swapAccountsY + buttonHeight + 5; float bottomButtonWidth = 65; float bottomButtonHeight = 20; float bottomSpacing = 10; float totalBottomWidth = bottomButtonWidth * 3 + bottomSpacing * 2; float bottomStartX = centerX - totalBottomWidth / 2f; for (int i = 0; i < 3; i++) { float x = bottomStartX + i * (bottomButtonWidth + bottomSpacing); boolean hovered = isMouseOver(mouseX, mouseY, x, bottomY, bottomButtonWidth, bottomButtonHeight); float target = hovered ? 1f : 0f; buttonHoverProgress[i + 3] = MathHelper.lerp(lerpSpeed, buttonHoverProgress[i + 3], target); } } else { for (int i = 0; i < 6; i++) { buttonHoverProgress[i] = MathHelper.lerp(lerpSpeed, buttonHoverProgress[i], 0f); } } } private void renderAltScreen(int screenWidth, int screenHeight, float mouseX, float mouseY, long currentTime) { float totalWidth = 405; float totalHeight = 163; float centerX = screenWidth / 2f; float centerY = screenHeight / 2f; float startX = centerX - totalWidth / 2f; float startY = centerY - totalHeight / 2f; float leftPanelX = startX; float leftPanelTopY = startY; accountRenderer.renderLeftPanelTop(leftPanelX, leftPanelTopY, 100, 100, 1f, nicknameText, nicknameFieldFocused, mouseX, mouseY, currentTime); float leftPanelBottomY = startY + 100 + 5; accountRenderer.renderLeftPanelBottom(leftPanelX, leftPanelBottomY, 100, 58, 1f, accountConfig.getActiveAccountName(), accountConfig.getActiveAccountDate(), accountConfig.getActiveAccountSkin()); float rightPanelX = startX + 100 + 5; float rightPanelY = startY; List<AccountEntry> sortedAccounts = accountConfig.getSortedAccounts(); accountRenderer.renderRightPanel(rightPanelX, rightPanelY, 300, 165, 1f, sortedAccounts, scrollOffset, mouseX, mouseY, 1f, (int) FIXED_GUI_SCALE); } @Override public boolean mouseClicked(Click click, boolean doubled) { float scaledMouseX = toFixedCoord(click.x()); float scaledMouseY = toFixedCoord(click.y()); if (currentView == View.MAIN_MENU) { if (click.button() == 0) { int fixedWidth = getFixedScaledWidth(); int fixedHeight = getFixedScaledHeight(); float centerX = fixedWidth / 2f; float centerY = fixedHeight / 2f; float buttonWidth = 220; float buttonHeight = 30; float buttonSpacing = 7; float buttonStartY = centerY + 3; for (int i = 0; i < 2; i++) { float y = buttonStartY + i * (buttonHeight + buttonSpacing); if (isMouseOver(scaledMouseX, scaledMouseY, centerX - buttonWidth / 2f, y, buttonWidth, buttonHeight)) { handleMainMenuButtonClick(i); return true; } } float swapAccountsY = buttonStartY + (buttonHeight + buttonSpacing) * 2 + 5; if (isMouseOver(scaledMouseX, scaledMouseY, centerX - buttonWidth / 2f, swapAccountsY, buttonWidth, buttonHeight)) { handleMainMenuButtonClick(2); return true; } float bottomY = swapAccountsY + buttonHeight + 5; float bottomButtonWidth = 65; float bottomButtonHeight = 20; float bottomSpacing = 10; float totalBottomWidth = bottomButtonWidth * 3 + bottomSpacing * 2; float bottomStartX = centerX - totalBottomWidth / 2f; for (int i = 0; i < 3; i++) { float x = bottomStartX + i * (bottomButtonWidth + bottomSpacing); if (isMouseOver(scaledMouseX, scaledMouseY, x, bottomY, bottomButtonWidth, bottomButtonHeight)) { handleMainMenuButtonClick(i + 3); return true; } } } } else if (currentView == View.ALT_SCREEN) { return handleAltScreenClick(scaledMouseX, scaledMouseY, click); } return super.mouseClicked(click, doubled); } private void handleMainMenuButtonClick(int index) { switch (index) { case 0 -> this.client.setScreen(new SelectWorldScreen(this)); case 1 -> { Screen screen = this.client.options.skipMultiplayerWarning ? new MultiplayerScreen(this) : new MultiplayerWarningScreen(this); this.client.setScreen(screen); } case 2 -> currentView = View.ALT_SCREEN; case 3 -> this.client.setScreen(new OptionsScreen(this, this.client.options)); case 4 -> {} case 5 -> this.client.scheduleStop(); } } private boolean handleAltScreenClick(float mouseX, float mouseY, Click click) { int screenWidth = getFixedScaledWidth(); int screenHeight = getFixedScaledHeight(); float totalWidth = 100 + 5 + 300; float totalHeight = 100 + 5 + 58; float centerX = screenWidth / 2f; float centerY = screenHeight / 2f; float startX = centerX - totalWidth / 2f; float startY = centerY - totalHeight / 2f; float leftPanelX = startX; float leftPanelTopY = startY; float fieldX = leftPanelX + 5; float fieldY = leftPanelTopY + 38; float fieldHeight = 14; float addButtonSize = 14; float buttonGap = 3; float fieldWidth = 100 - 10 - addButtonSize - buttonGap; if (accountRenderer.isMouseOver(mouseX, mouseY, fieldX, fieldY, fieldWidth, fieldHeight)) { nicknameFieldFocused = true; return true; } else { nicknameFieldFocused = false; } float addButtonX = fieldX + fieldWidth + buttonGap; float addButtonY = fieldY; if (accountRenderer.isMouseOver(mouseX, mouseY, addButtonX, addButtonY, addButtonSize, addButtonSize)) { if (!nicknameText.isEmpty()) { addAccount(nicknameText); nicknameText = ""; } return true; } float buttonWidth = 100 - 10; float buttonHeight = 16; float randomButtonX = leftPanelX + 5; float randomButtonY = fieldY + fieldHeight + 6; if (accountRenderer.isMouseOver(mouseX, mouseY, randomButtonX, randomButtonY, buttonWidth, buttonHeight)) { String randomNick = generateRandomNickname(); addAccount(randomNick); nicknameText = ""; return true; } float clearButtonX = leftPanelX + 5; float clearButtonY = randomButtonY + buttonHeight + 5; if (accountRenderer.isMouseOver(mouseX, mouseY, clearButtonX, clearButtonY, buttonWidth, buttonHeight)) { accountConfig.clearAllAccounts(); targetScrollOffset = 0f; scrollOffset = 0f; return true; } float rightPanelX = startX + 100 + 5; float rightPanelY = startY; float accountListX = rightPanelX + 5; float accountListY = rightPanelY + 26; float accountListWidth = 300 - 10; float accountListHeight = 165 - 31; if (!accountRenderer.isMouseOver(mouseX, mouseY, accountListX, accountListY, accountListWidth, accountListHeight)) { return false; } float cardWidth = (accountListWidth - 5) / 2f; float cardHeight = 40; float cardGap = 5; List<AccountEntry> sortedAccounts = accountConfig.getSortedAccounts(); for (int i = 0; i < sortedAccounts.size(); i++) { int col = i % 2; int row = i / 2; float cardX = accountListX + col * (cardWidth + cardGap); float cardY = accountListY + row * (cardHeight + cardGap) - scrollOffset; if (cardY + cardHeight < accountListY || cardY > accountListY + accountListHeight) { continue; } float btnSize = 12; float buttonYPos = cardY + cardHeight - btnSize - 5; float pinButtonX = cardX + cardWidth - btnSize * 2 - 8; float deleteButtonX = cardX + cardWidth - btnSize - 5; if (accountRenderer.isMouseOver(mouseX, mouseY, pinButtonX, buttonYPos, btnSize, btnSize)) { AccountEntry entry = sortedAccounts.get(i); entry.togglePinned(); if (entry.isPinned()) { setActiveAccount(entry); } accountConfig.save(); return true; } if (accountRenderer.isMouseOver(mouseX, mouseY, deleteButtonX, buttonYPos, btnSize, btnSize)) { accountConfig.removeAccountByIndex(i); return true; } if (accountRenderer.isMouseOver(mouseX, mouseY, cardX, cardY, cardWidth, cardHeight)) { setActiveAccount(sortedAccounts.get(i)); return true; } } return false; } @Override public boolean mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { if (currentView != View.ALT_SCREEN) return false; float scaledMouseX = toFixedCoord(mouseX); float scaledMouseY = toFixedCoord(mouseY); int screenWidth = getFixedScaledWidth(); int screenHeight = getFixedScaledHeight(); float totalWidth = 100 + 5 + 300; float totalHeight = 100 + 5 + 58; float centerX = screenWidth / 2f; float centerY = screenHeight / 2f; float startX = centerX - totalWidth / 2f; float startY = centerY - totalHeight / 2f; float rightPanelX = startX + 100 + 5; float rightPanelY = startY; if (accountRenderer.isMouseOver(scaledMouseX, scaledMouseY, rightPanelX, rightPanelY, 300, 165)) { float cardHeight = 40; float cardGap = 5; float accountListHeight = 165 - 31; int rows = (int) Math.ceil(accountConfig.getSortedAccounts().size() / 2.0); float maxScroll = Math.max(0, rows * (cardHeight + cardGap) - accountListHeight); targetScrollOffset -= (float) verticalAmount * 25; targetScrollOffset = MathHelper.clamp(targetScrollOffset, 0, maxScroll); float scrollSpeed = 12f; float deltaTime = 0.016f; float scrollDiff = targetScrollOffset - scrollOffset; scrollOffset += scrollDiff * Math.min(1f, deltaTime * scrollSpeed); return true; } return super.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount); } @Override public boolean keyPressed(KeyInput input) { if (currentView == View.ALT_SCREEN) { if (nicknameFieldFocused) { int keyCode = input.key(); if (keyCode == 259) { if (!nicknameText.isEmpty()) { nicknameText = nicknameText.substring(0, nicknameText.length() - 1); } return true; } if (keyCode == 256) { nicknameFieldFocused = false; return true; } if (keyCode == 257 || keyCode == 335) { if (!nicknameText.isEmpty()) { addAccount(nicknameText); nicknameText = ""; } nicknameFieldFocused = false; return true; } } if (input.key() == 256) { currentView = View.MAIN_MENU; accountConfig.save(); return true; } } return super.keyPressed(input); } @Override public boolean charTyped(CharInput input) { if (currentView == View.ALT_SCREEN && nicknameFieldFocused) { int codepoint = input.codepoint(); if (Character.isLetterOrDigit(codepoint) || codepoint == '_') { if (nicknameText.length() < 16) { nicknameText += Character.toString(codepoint); } return true; } } return super.charTyped(input); } private void setActiveAccount(AccountEntry account) { accountConfig.setActiveAccount(account.getName(), account.getDate(), account.getSkin()); SessionChanger.changeUsername(account.getName()); } private void addAccount(String nickname) { LocalDateTime now = LocalDateTime.now(); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm"); String date = now.format(formatter); AccountEntry entry = new AccountEntry(nickname, date, null); accountConfig.addAccount(entry); setActiveAccount(entry); SessionChanger.changeUsername(nickname); } private String generateRandomNickname() { Random random = new Random(); StringBuilder username = new StringBuilder(); char[] vowels = {'a', 'e', 'i', 'o', 'u'}; char[] consonants = {'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z'}; String finalUsername = null; int attempts = 0; final int MAX_ATTEMPTS = 10; List<AccountEntry> existingAccounts = accountConfig.getAccounts(); do { username.setLength(0); int length = 6 + random.nextInt(5); boolean startWithVowel = random.nextBoolean(); for (int i = 0; i < length; i++) { if (i % 2 == 0) { username.append(startWithVowel ? vowels[random.nextInt(vowels.length)] : consonants[random.nextInt(consonants.length)]); } else { username.append(startWithVowel ? consonants[random.nextInt(consonants.length)] : vowels[random.nextInt(vowels.length)]); } } if (random.nextInt(100) < 30) { username.append(random.nextInt(100)); } String tempUsername = username.substring(0, 1).toUpperCase() + username.substring(1); attempts++; boolean exists = false; for (AccountEntry account : existingAccounts) { if (account.getName().equalsIgnoreCase(tempUsername)) { exists = true; break; } } if (!exists) { finalUsername = tempUsername; break; } } while (attempts < MAX_ATTEMPTS); if (finalUsername == null) { finalUsername = username.substring(0, 1).toUpperCase() + username.substring(1) + (System.currentTimeMillis() % 1000); } return finalUsername; } @Override public void renderBackground(DrawContext context, int mouseX, int mouseY, float delta) { drawBackground(); } @Override public boolean shouldCloseOnEsc() { return false; } @Override public boolean shouldPause() { return false; } private int withAlpha(int color, int alpha) { return (color & 0x00FFFFFF) | (MathHelper.clamp(alpha, 0, 255) << 24); } } }
Посмотреть вложение 327281
мое:Посмотреть вложение 327344
upd: добавил обводку
охуенноврод похоже хз
фонты думаю сами найдете
векса:код:package rich.screens.menu; import net.minecraft.client.gui.Click; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen; import net.minecraft.client.gui.screen.multiplayer.MultiplayerWarningScreen; import net.minecraft.client.gui.screen.option.OptionsScreen; import net.minecraft.client.gui.screen.world.SelectWorldScreen; import net.minecraft.client.input.KeyInput; import net.minecraft.client.input.CharInput; import net.minecraft.text.Text; import net.minecraft.util.Identifier; import net.minecraft.util.Util; import net.minecraft.util.math.MathHelper; import rich.Initialization; import rich.screens.account.AccountEntry; import rich.screens.account.AccountRenderer; import rich.util.config.impl.account.AccountConfig; import rich.util.render.Render2D; import rich.util.render.font.Fonts; import rich.util.session.SessionChanger; import rich.util.sounds.SoundManager; import antidaunleak.api.UserProfile; import java.awt.*; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.List; import java.util.Random; public class MainMenuScreen extends Screen { private static final Identifier BACKGROUND_TEXTURE = Identifier.of("rich", "textures/menu/backmenu.png"); private static final float FIXED_GUI_SCALE = 2.0f; private static final int PARTICLE_COUNT = 50; private static final float PARTICLE_FADE_THRESHOLD = 0.8f; private static class Particle { float x, y; float vx, vy; float size; float alpha; float lifetime; float maxLifetime; boolean isDead = false; Particle(float x, float y) { this.x = x; this.y = y; Random rand = new Random(); this.vx = (rand.nextFloat() - 0.5f) * 0.2f; this.vy = (rand.nextFloat() - 0.5f) * 0.2f; this.size = 0.5f + rand.nextFloat() * 1f; this.alpha = 0.2f + rand.nextFloat() * 0.3f; this.maxLifetime = 10f + rand.nextFloat() * 10f; this.lifetime = 0f; } void update(float delta, int width, int height) { lifetime += delta / 60f; if (lifetime > maxLifetime * PARTICLE_FADE_THRESHOLD) { float fadeProgress = (lifetime - maxLifetime * PARTICLE_FADE_THRESHOLD) / (maxLifetime * (1f - PARTICLE_FADE_THRESHOLD)); alpha = Math.max(0, alpha * (1f - fadeProgress)); } if (lifetime >= maxLifetime) { isDead = true; return; } x += vx * delta; y += vy * delta; if (x < -10 || x > width + 10 || y < -10 || y > height + 10) { isDead = true; } } } private final List<Particle> particles = new java.util.ArrayList<>(); private boolean particlesInitialized = false; private int lastWindowWidth = 0; private int lastWindowHeight = 0; private enum View { MAIN_MENU, ALT_SCREEN } private View currentView = View.MAIN_MENU; private long screenStartTime = 0L; private boolean initialized = false; private long lastRenderTime = 0L; private int hoveredButton = -1; private float[] buttonHoverProgress = new float[6]; private final AccountRenderer accountRenderer; private final AccountConfig accountConfig; private String nicknameText = ""; private boolean nicknameFieldFocused = false; private float scrollOffset = 0f; private float targetScrollOffset = 0f; public MainMenuScreen() { super(Text.literal("Main Menu")); for (int i = 0; i < 6; i++) { buttonHoverProgress[i] = 0f; } this.accountRenderer = new AccountRenderer(); this.accountConfig = AccountConfig.getInstance(); this.accountConfig.load(); } @Override protected void init() { initialized = false; particlesInitialized = false; } private int getFixedScaledWidth() { return (int) Math.ceil((double) client.getWindow().getFramebufferWidth() / FIXED_GUI_SCALE); } private int getFixedScaledHeight() { return (int) Math.ceil((double) client.getWindow().getFramebufferHeight() / FIXED_GUI_SCALE); } private float toFixedCoord(double coord) { float currentScale = (float) client.getWindow().getScaleFactor(); return (float) (coord * currentScale / FIXED_GUI_SCALE); } private void initParticles(int width, int height) { if (particlesInitialized) return; Random rand = new Random(); for (int i = 0; i < PARTICLE_COUNT; i++) { particles.add(new Particle(rand.nextFloat() * width, rand.nextFloat() * height)); } particlesInitialized = true; } private void drawBackground() { int screenWidth = getFixedScaledWidth(); int screenHeight = getFixedScaledHeight(); Render2D.rect(0, 0, screenWidth, screenHeight, new Color(12, 15, 18).getRGB()); initParticles(screenWidth, screenHeight); for (Particle p : particles) { if (!p.isDead && p.alpha > 0.01f) { int alpha = (int) (p.alpha * 255); Render2D.rect(p.x, p.y, p.size, p.size, new Color(255, 255, 255, alpha).getRGB()); } } } @Override public void render(DrawContext context, int mouseX, int mouseY, float delta) { long currentTime = Util.getMeasuringTimeMs(); if (!initialized) { screenStartTime = currentTime; lastRenderTime = currentTime; initialized = true; } float deltaTime = Math.min(delta, 0.05f); lastRenderTime = currentTime; int fixedWidth = getFixedScaledWidth(); int fixedHeight = getFixedScaledHeight(); if (lastWindowWidth != fixedWidth || lastWindowHeight != fixedHeight) { particles.clear(); particlesInitialized = false; lastWindowWidth = fixedWidth; lastWindowHeight = fixedHeight; } for (Particle p : particles) { p.update(deltaTime * 60f, fixedWidth, fixedHeight); } particles.removeIf(p -> p.isDead); Random rand = new Random(); while (particles.size() < PARTICLE_COUNT) { particles.add(new Particle(rand.nextFloat() * fixedWidth, rand.nextFloat() * fixedHeight)); } float scaledMouseX = toFixedCoord(mouseX); float scaledMouseY = toFixedCoord(mouseY); updateButtonAnimations(deltaTime, scaledMouseX, scaledMouseY, fixedWidth, fixedHeight); Render2D.beginOverlay(); drawBackground(); if (currentView == View.MAIN_MENU) { renderMainMenu(fixedWidth, fixedHeight, scaledMouseX, scaledMouseY); } else { renderAltScreen(fixedWidth, fixedHeight, scaledMouseX, scaledMouseY, currentTime); } Render2D.endOverlay(); } private void renderMainMenu(int screenWidth, int screenHeight, float mouseX, float mouseY) { float centerX = screenWidth / 2f; float centerY = screenHeight / 2f; String username = "user"; float avatarSize = 20; float avatarX = 8; float avatarY = 10; Fonts.INTER_MEDIUM.draw("Logged in as", avatarX + avatarSize + 5, avatarY, 7f, new Color(150, 150, 150).getRGB()); Fonts.INTER_MEDIUM.draw(username, avatarX + avatarSize + 5, avatarY + 9, 8f, new Color(255, 255, 255).getRGB()); Render2D.rect(avatarX, avatarY, avatarSize, avatarSize, new Color(40, 45, 55).getRGB(), avatarSize / 2f); Identifier userAvatar = Identifier.of("rich", "user.png"); int[] avatarColors = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}; float[] avatarRadii = {avatarSize / 2f, avatarSize / 2f, avatarSize / 2f, avatarSize / 2f}; Initialization.getInstance().getManager().getRenderCore().getTexturePipeline() .drawTexture(userAvatar, avatarX, avatarY, avatarSize, avatarSize, 0, 0, 1, 1, avatarColors, avatarRadii, 1f); float logoSize = 35; float logoY = centerY - 90; Identifier logoTexture = Identifier.of("rich", "images/logo.png"); int[] logoColors = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}; float[] logoRadii = {0, 0, 0, 0}; Initialization.getInstance().getManager().getRenderCore().getTexturePipeline() .drawTexture(logoTexture, centerX - logoSize / 2f, logoY, logoSize, logoSize, 0, 0, 1, 1, logoColors, logoRadii, 1f); String timeOfDay = getTimeOfDay(); String greeting = "Good " + timeOfDay + ", "; String usernameColored = username; float greetingWidth = Fonts.INTER_SEMIBOLD.getWidth(greeting, 14f); float usernameWidth = Fonts.INTER_SEMIBOLD.getWidth(usernameColored, 14f); float totalGreetingWidth = greetingWidth + usernameWidth; float greetingStartX = centerX - totalGreetingWidth / 2f; float greetingY = centerY - 38; Fonts.INTER_SEMIBOLD.draw(greeting, greetingStartX, greetingY, 14f, new Color(255, 255, 255).getRGB()); Fonts.INTER_SEMIBOLD.draw(usernameColored, greetingStartX + greetingWidth, greetingY, 14f, new Color(100, 180, 255).getRGB()); String welcomeText = "Welcome to "; String clientName = "WexSide. The best client."; String restText = ""; float welcomeWidth = Fonts.INTER_MEDIUM.getWidth(welcomeText, 9f); float clientWidth = Fonts.INTER_MEDIUM.getWidth(clientName, 9f); float restWidth = Fonts.INTER_MEDIUM.getWidth(restText, 9f); float totalWidth = welcomeWidth + clientWidth + restWidth; float startX = centerX - totalWidth / 2f; float textY = centerY - 20; Fonts.INTER_MEDIUM.draw(welcomeText, startX, textY, 9f, new Color(180, 180, 180).getRGB()); Fonts.INTER_SEMIBOLD.draw(clientName, startX + welcomeWidth, textY, 9f, new Color(90, 22, 134).getRGB()); Fonts.INTER_MEDIUM.draw(restText, startX + welcomeWidth + clientWidth, textY, 9f, new Color(180, 180, 180).getRGB()); float buttonWidth = 220; float buttonHeight = 30; float buttonSpacing = 7; float buttonStartY = centerY + 3; drawButton(centerX - buttonWidth / 2f, buttonStartY, buttonWidth, buttonHeight, "Singleplayer", 0, mouseX, mouseY, new Color(30, 35, 45), false); drawButton(centerX - buttonWidth / 2f, buttonStartY + buttonHeight + buttonSpacing, buttonWidth, buttonHeight, "Multiplayer", 1, mouseX, mouseY, new Color(30, 35, 45), false); float swapAccountsY = buttonStartY + (buttonHeight + buttonSpacing) * 2 + 5; drawButton(centerX - buttonWidth / 2f, swapAccountsY, buttonWidth, buttonHeight, "Swap Accounts", 2, mouseX, mouseY, new Color(90, 22, 134), true); float bottomY = swapAccountsY + buttonHeight + 5; float bottomButtonWidth = 65; float bottomButtonHeight = 20; float bottomSpacing = 10; float totalBottomWidth = bottomButtonWidth * 3 + bottomSpacing * 2; float bottomStartX = centerX - totalBottomWidth / 2f; drawSmallButton(bottomStartX, bottomY, bottomButtonWidth, bottomButtonHeight, "Options", 3, mouseX, mouseY); drawSmallButton(bottomStartX + bottomButtonWidth + bottomSpacing, bottomY, bottomButtonWidth, bottomButtonHeight, "Proxies", 4, mouseX, mouseY); drawSmallButton(bottomStartX + (bottomButtonWidth + bottomSpacing) * 2, bottomY, bottomButtonWidth, bottomButtonHeight, "Exit", 5, mouseX, mouseY); String footerText = "By logging into your account, you agree to all of our policies,"; String policyLinks = "including our Privacy Policy and Terms of Service"; Fonts.INTER_MEDIUM.drawCentered(footerText, centerX, screenHeight - 17, 6.5f, new Color(100, 100, 100).getRGB()); Fonts.INTER_MEDIUM.drawCentered(policyLinks, centerX, screenHeight - 8, 6.5f, new Color(100, 100, 100).getRGB()); } private String getTimeOfDay() { int hour = java.time.LocalTime.now().getHour(); if (hour >= 5 && hour < 12) return "morning"; if (hour >= 12 && hour < 17) return "afternoon"; if (hour >= 17 && hour < 21) return "evening"; return "night"; } private void drawButton(float x, float y, float width, float height, String text, int index, float mouseX, float mouseY, Color baseColor, boolean isPurple) { boolean hovered = isMouseOver(mouseX, mouseY, x, y, width, height); float hoverProgress = buttonHoverProgress[index]; Color bgColor = baseColor; if (isPurple) { int brightness = (int) (hoverProgress * 20); bgColor = new Color( Math.min(255, baseColor.getRed() + brightness), Math.min(255, baseColor.getGreen() + brightness), Math.min(255, baseColor.getBlue() + brightness) ); } else { int brightness = (int) (hoverProgress * 15); bgColor = new Color( Math.min(255, baseColor.getRed() + brightness), Math.min(255, baseColor.getGreen() + brightness), Math.min(255, baseColor.getBlue() + brightness) ); } Render2D.rect(x, y, width, height, bgColor.getRGB(), 8); if (!isPurple) { Render2D.outline(x, y, width, height, 1f, new Color(50, 55, 65, 80).getRGB(), 8); } if (hoverProgress > 0.01f) { int borderAlpha = (int) (hoverProgress * 100); Color borderColor = isPurple ? new Color(138, 43, 226, borderAlpha) : new Color(100, 110, 130, borderAlpha); Render2D.outline(x, y, width, height, 1f, borderColor.getRGB(), 8); } float fontSize = 9f; float textHeight = Fonts.INTER_MEDIUM.getHeight(fontSize); Color textColor = isPurple ? new Color(255, 255, 255) : new Color(160, 160, 160); Fonts.INTER_MEDIUM.drawCentered(text, x + width / 2f, y + (height - textHeight) / 2f, fontSize, textColor.getRGB()); } private void drawSmallButton(float x, float y, float width, float height, String text, int index, float mouseX, float mouseY) { float hoverProgress = buttonHoverProgress[index]; int baseAlpha = 150; int hoverAlpha = (int) (baseAlpha + hoverProgress * 50); float fontSize = 8f; float textHeight = Fonts.INTER_MEDIUM.getHeight(fontSize); Fonts.INTER_MEDIUM.drawCentered(text, x + width / 2f, y + (height - textHeight) / 2f, fontSize, new Color(180, 180, 180, hoverAlpha).getRGB()); } private boolean isMouseOver(float mouseX, float mouseY, float x, float y, float width, float height) { return mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height; } private void updateButtonAnimations(float deltaTime, float mouseX, float mouseY, int screenWidth, int screenHeight) { float centerX = screenWidth / 2f; float centerY = screenHeight / 2f; float lerpSpeed = 1f - (float) Math.pow(0.001f, deltaTime); if (currentView == View.MAIN_MENU) { float buttonWidth = 220; float buttonHeight = 30; float buttonSpacing = 7; float buttonStartY = centerY + 3; for (int i = 0; i < 2; i++) { float y = buttonStartY + i * (buttonHeight + buttonSpacing); boolean hovered = isMouseOver(mouseX, mouseY, centerX - buttonWidth / 2f, y, buttonWidth, buttonHeight); float target = hovered ? 1f : 0f; buttonHoverProgress[i] = MathHelper.lerp(lerpSpeed, buttonHoverProgress[i], target); } float swapAccountsY = buttonStartY + (buttonHeight + buttonSpacing) * 2 + 5; boolean swapHovered = isMouseOver(mouseX, mouseY, centerX - buttonWidth / 2f, swapAccountsY, buttonWidth, buttonHeight); buttonHoverProgress[2] = MathHelper.lerp(lerpSpeed, buttonHoverProgress[2], swapHovered ? 1f : 0f); float bottomY = swapAccountsY + buttonHeight + 5; float bottomButtonWidth = 65; float bottomButtonHeight = 20; float bottomSpacing = 10; float totalBottomWidth = bottomButtonWidth * 3 + bottomSpacing * 2; float bottomStartX = centerX - totalBottomWidth / 2f; for (int i = 0; i < 3; i++) { float x = bottomStartX + i * (bottomButtonWidth + bottomSpacing); boolean hovered = isMouseOver(mouseX, mouseY, x, bottomY, bottomButtonWidth, bottomButtonHeight); float target = hovered ? 1f : 0f; buttonHoverProgress[i + 3] = MathHelper.lerp(lerpSpeed, buttonHoverProgress[i + 3], target); } } else { for (int i = 0; i < 6; i++) { buttonHoverProgress[i] = MathHelper.lerp(lerpSpeed, buttonHoverProgress[i], 0f); } } } private void renderAltScreen(int screenWidth, int screenHeight, float mouseX, float mouseY, long currentTime) { float totalWidth = 405; float totalHeight = 163; float centerX = screenWidth / 2f; float centerY = screenHeight / 2f; float startX = centerX - totalWidth / 2f; float startY = centerY - totalHeight / 2f; float leftPanelX = startX; float leftPanelTopY = startY; accountRenderer.renderLeftPanelTop(leftPanelX, leftPanelTopY, 100, 100, 1f, nicknameText, nicknameFieldFocused, mouseX, mouseY, currentTime); float leftPanelBottomY = startY + 100 + 5; accountRenderer.renderLeftPanelBottom(leftPanelX, leftPanelBottomY, 100, 58, 1f, accountConfig.getActiveAccountName(), accountConfig.getActiveAccountDate(), accountConfig.getActiveAccountSkin()); float rightPanelX = startX + 100 + 5; float rightPanelY = startY; List<AccountEntry> sortedAccounts = accountConfig.getSortedAccounts(); accountRenderer.renderRightPanel(rightPanelX, rightPanelY, 300, 165, 1f, sortedAccounts, scrollOffset, mouseX, mouseY, 1f, (int) FIXED_GUI_SCALE); } @Override public boolean mouseClicked(Click click, boolean doubled) { float scaledMouseX = toFixedCoord(click.x()); float scaledMouseY = toFixedCoord(click.y()); if (currentView == View.MAIN_MENU) { if (click.button() == 0) { int fixedWidth = getFixedScaledWidth(); int fixedHeight = getFixedScaledHeight(); float centerX = fixedWidth / 2f; float centerY = fixedHeight / 2f; float buttonWidth = 220; float buttonHeight = 30; float buttonSpacing = 7; float buttonStartY = centerY + 3; for (int i = 0; i < 2; i++) { float y = buttonStartY + i * (buttonHeight + buttonSpacing); if (isMouseOver(scaledMouseX, scaledMouseY, centerX - buttonWidth / 2f, y, buttonWidth, buttonHeight)) { handleMainMenuButtonClick(i); return true; } } float swapAccountsY = buttonStartY + (buttonHeight + buttonSpacing) * 2 + 5; if (isMouseOver(scaledMouseX, scaledMouseY, centerX - buttonWidth / 2f, swapAccountsY, buttonWidth, buttonHeight)) { handleMainMenuButtonClick(2); return true; } float bottomY = swapAccountsY + buttonHeight + 5; float bottomButtonWidth = 65; float bottomButtonHeight = 20; float bottomSpacing = 10; float totalBottomWidth = bottomButtonWidth * 3 + bottomSpacing * 2; float bottomStartX = centerX - totalBottomWidth / 2f; for (int i = 0; i < 3; i++) { float x = bottomStartX + i * (bottomButtonWidth + bottomSpacing); if (isMouseOver(scaledMouseX, scaledMouseY, x, bottomY, bottomButtonWidth, bottomButtonHeight)) { handleMainMenuButtonClick(i + 3); return true; } } } } else if (currentView == View.ALT_SCREEN) { return handleAltScreenClick(scaledMouseX, scaledMouseY, click); } return super.mouseClicked(click, doubled); } private void handleMainMenuButtonClick(int index) { switch (index) { case 0 -> this.client.setScreen(new SelectWorldScreen(this)); case 1 -> { Screen screen = this.client.options.skipMultiplayerWarning ? new MultiplayerScreen(this) : new MultiplayerWarningScreen(this); this.client.setScreen(screen); } case 2 -> currentView = View.ALT_SCREEN; case 3 -> this.client.setScreen(new OptionsScreen(this, this.client.options)); case 4 -> {} case 5 -> this.client.scheduleStop(); } } private boolean handleAltScreenClick(float mouseX, float mouseY, Click click) { int screenWidth = getFixedScaledWidth(); int screenHeight = getFixedScaledHeight(); float totalWidth = 100 + 5 + 300; float totalHeight = 100 + 5 + 58; float centerX = screenWidth / 2f; float centerY = screenHeight / 2f; float startX = centerX - totalWidth / 2f; float startY = centerY - totalHeight / 2f; float leftPanelX = startX; float leftPanelTopY = startY; float fieldX = leftPanelX + 5; float fieldY = leftPanelTopY + 38; float fieldHeight = 14; float addButtonSize = 14; float buttonGap = 3; float fieldWidth = 100 - 10 - addButtonSize - buttonGap; if (accountRenderer.isMouseOver(mouseX, mouseY, fieldX, fieldY, fieldWidth, fieldHeight)) { nicknameFieldFocused = true; return true; } else { nicknameFieldFocused = false; } float addButtonX = fieldX + fieldWidth + buttonGap; float addButtonY = fieldY; if (accountRenderer.isMouseOver(mouseX, mouseY, addButtonX, addButtonY, addButtonSize, addButtonSize)) { if (!nicknameText.isEmpty()) { addAccount(nicknameText); nicknameText = ""; } return true; } float buttonWidth = 100 - 10; float buttonHeight = 16; float randomButtonX = leftPanelX + 5; float randomButtonY = fieldY + fieldHeight + 6; if (accountRenderer.isMouseOver(mouseX, mouseY, randomButtonX, randomButtonY, buttonWidth, buttonHeight)) { String randomNick = generateRandomNickname(); addAccount(randomNick); nicknameText = ""; return true; } float clearButtonX = leftPanelX + 5; float clearButtonY = randomButtonY + buttonHeight + 5; if (accountRenderer.isMouseOver(mouseX, mouseY, clearButtonX, clearButtonY, buttonWidth, buttonHeight)) { accountConfig.clearAllAccounts(); targetScrollOffset = 0f; scrollOffset = 0f; return true; } float rightPanelX = startX + 100 + 5; float rightPanelY = startY; float accountListX = rightPanelX + 5; float accountListY = rightPanelY + 26; float accountListWidth = 300 - 10; float accountListHeight = 165 - 31; if (!accountRenderer.isMouseOver(mouseX, mouseY, accountListX, accountListY, accountListWidth, accountListHeight)) { return false; } float cardWidth = (accountListWidth - 5) / 2f; float cardHeight = 40; float cardGap = 5; List<AccountEntry> sortedAccounts = accountConfig.getSortedAccounts(); for (int i = 0; i < sortedAccounts.size(); i++) { int col = i % 2; int row = i / 2; float cardX = accountListX + col * (cardWidth + cardGap); float cardY = accountListY + row * (cardHeight + cardGap) - scrollOffset; if (cardY + cardHeight < accountListY || cardY > accountListY + accountListHeight) { continue; } float btnSize = 12; float buttonYPos = cardY + cardHeight - btnSize - 5; float pinButtonX = cardX + cardWidth - btnSize * 2 - 8; float deleteButtonX = cardX + cardWidth - btnSize - 5; if (accountRenderer.isMouseOver(mouseX, mouseY, pinButtonX, buttonYPos, btnSize, btnSize)) { AccountEntry entry = sortedAccounts.get(i); entry.togglePinned(); if (entry.isPinned()) { setActiveAccount(entry); } accountConfig.save(); return true; } if (accountRenderer.isMouseOver(mouseX, mouseY, deleteButtonX, buttonYPos, btnSize, btnSize)) { accountConfig.removeAccountByIndex(i); return true; } if (accountRenderer.isMouseOver(mouseX, mouseY, cardX, cardY, cardWidth, cardHeight)) { setActiveAccount(sortedAccounts.get(i)); return true; } } return false; } @Override public boolean mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { if (currentView != View.ALT_SCREEN) return false; float scaledMouseX = toFixedCoord(mouseX); float scaledMouseY = toFixedCoord(mouseY); int screenWidth = getFixedScaledWidth(); int screenHeight = getFixedScaledHeight(); float totalWidth = 100 + 5 + 300; float totalHeight = 100 + 5 + 58; float centerX = screenWidth / 2f; float centerY = screenHeight / 2f; float startX = centerX - totalWidth / 2f; float startY = centerY - totalHeight / 2f; float rightPanelX = startX + 100 + 5; float rightPanelY = startY; if (accountRenderer.isMouseOver(scaledMouseX, scaledMouseY, rightPanelX, rightPanelY, 300, 165)) { float cardHeight = 40; float cardGap = 5; float accountListHeight = 165 - 31; int rows = (int) Math.ceil(accountConfig.getSortedAccounts().size() / 2.0); float maxScroll = Math.max(0, rows * (cardHeight + cardGap) - accountListHeight); targetScrollOffset -= (float) verticalAmount * 25; targetScrollOffset = MathHelper.clamp(targetScrollOffset, 0, maxScroll); float scrollSpeed = 12f; float deltaTime = 0.016f; float scrollDiff = targetScrollOffset - scrollOffset; scrollOffset += scrollDiff * Math.min(1f, deltaTime * scrollSpeed); return true; } return super.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount); } @Override public boolean keyPressed(KeyInput input) { if (currentView == View.ALT_SCREEN) { if (nicknameFieldFocused) { int keyCode = input.key(); if (keyCode == 259) { if (!nicknameText.isEmpty()) { nicknameText = nicknameText.substring(0, nicknameText.length() - 1); } return true; } if (keyCode == 256) { nicknameFieldFocused = false; return true; } if (keyCode == 257 || keyCode == 335) { if (!nicknameText.isEmpty()) { addAccount(nicknameText); nicknameText = ""; } nicknameFieldFocused = false; return true; } } if (input.key() == 256) { currentView = View.MAIN_MENU; accountConfig.save(); return true; } } return super.keyPressed(input); } @Override public boolean charTyped(CharInput input) { if (currentView == View.ALT_SCREEN && nicknameFieldFocused) { int codepoint = input.codepoint(); if (Character.isLetterOrDigit(codepoint) || codepoint == '_') { if (nicknameText.length() < 16) { nicknameText += Character.toString(codepoint); } return true; } } return super.charTyped(input); } private void setActiveAccount(AccountEntry account) { accountConfig.setActiveAccount(account.getName(), account.getDate(), account.getSkin()); SessionChanger.changeUsername(account.getName()); } private void addAccount(String nickname) { LocalDateTime now = LocalDateTime.now(); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm"); String date = now.format(formatter); AccountEntry entry = new AccountEntry(nickname, date, null); accountConfig.addAccount(entry); setActiveAccount(entry); SessionChanger.changeUsername(nickname); } private String generateRandomNickname() { Random random = new Random(); StringBuilder username = new StringBuilder(); char[] vowels = {'a', 'e', 'i', 'o', 'u'}; char[] consonants = {'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z'}; String finalUsername = null; int attempts = 0; final int MAX_ATTEMPTS = 10; List<AccountEntry> existingAccounts = accountConfig.getAccounts(); do { username.setLength(0); int length = 6 + random.nextInt(5); boolean startWithVowel = random.nextBoolean(); for (int i = 0; i < length; i++) { if (i % 2 == 0) { username.append(startWithVowel ? vowels[random.nextInt(vowels.length)] : consonants[random.nextInt(consonants.length)]); } else { username.append(startWithVowel ? consonants[random.nextInt(consonants.length)] : vowels[random.nextInt(vowels.length)]); } } if (random.nextInt(100) < 30) { username.append(random.nextInt(100)); } String tempUsername = username.substring(0, 1).toUpperCase() + username.substring(1); attempts++; boolean exists = false; for (AccountEntry account : existingAccounts) { if (account.getName().equalsIgnoreCase(tempUsername)) { exists = true; break; } } if (!exists) { finalUsername = tempUsername; break; } } while (attempts < MAX_ATTEMPTS); if (finalUsername == null) { finalUsername = username.substring(0, 1).toUpperCase() + username.substring(1) + (System.currentTimeMillis() % 1000); } return finalUsername; } @Override public void renderBackground(DrawContext context, int mouseX, int mouseY, float delta) { drawBackground(); } @Override public boolean shouldCloseOnEsc() { return false; } @Override public boolean shouldPause() { return false; } private int withAlpha(int color, int alpha) { return (color & 0x00FFFFFF) | (MathHelper.clamp(alpha, 0, 255) << 24); } } }
Посмотреть вложение 327281
мое:Посмотреть вложение 327344
upd: добавил обводку
где фонт этот взять
ну мне нрав, да и вроде повторил как у вексаврод похоже хз
фонты думаю сами найдете
векса:код:package rich.screens.menu; import net.minecraft.client.gui.Click; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen; import net.minecraft.client.gui.screen.multiplayer.MultiplayerWarningScreen; import net.minecraft.client.gui.screen.option.OptionsScreen; import net.minecraft.client.gui.screen.world.SelectWorldScreen; import net.minecraft.client.input.KeyInput; import net.minecraft.client.input.CharInput; import net.minecraft.text.Text; import net.minecraft.util.Identifier; import net.minecraft.util.Util; import net.minecraft.util.math.MathHelper; import rich.Initialization; import rich.screens.account.AccountEntry; import rich.screens.account.AccountRenderer; import rich.util.config.impl.account.AccountConfig; import rich.util.render.Render2D; import rich.util.render.font.Fonts; import rich.util.session.SessionChanger; import rich.util.sounds.SoundManager; import antidaunleak.api.UserProfile; import java.awt.*; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.List; import java.util.Random; public class MainMenuScreen extends Screen { private static final Identifier BACKGROUND_TEXTURE = Identifier.of("rich", "textures/menu/backmenu.png"); private static final float FIXED_GUI_SCALE = 2.0f; private static final int PARTICLE_COUNT = 50; private static final float PARTICLE_FADE_THRESHOLD = 0.8f; private static class Particle { float x, y; float vx, vy; float size; float alpha; float lifetime; float maxLifetime; boolean isDead = false; Particle(float x, float y) { this.x = x; this.y = y; Random rand = new Random(); this.vx = (rand.nextFloat() - 0.5f) * 0.2f; this.vy = (rand.nextFloat() - 0.5f) * 0.2f; this.size = 0.5f + rand.nextFloat() * 1f; this.alpha = 0.2f + rand.nextFloat() * 0.3f; this.maxLifetime = 10f + rand.nextFloat() * 10f; this.lifetime = 0f; } void update(float delta, int width, int height) { lifetime += delta / 60f; if (lifetime > maxLifetime * PARTICLE_FADE_THRESHOLD) { float fadeProgress = (lifetime - maxLifetime * PARTICLE_FADE_THRESHOLD) / (maxLifetime * (1f - PARTICLE_FADE_THRESHOLD)); alpha = Math.max(0, alpha * (1f - fadeProgress)); } if (lifetime >= maxLifetime) { isDead = true; return; } x += vx * delta; y += vy * delta; if (x < -10 || x > width + 10 || y < -10 || y > height + 10) { isDead = true; } } } private final List<Particle> particles = new java.util.ArrayList<>(); private boolean particlesInitialized = false; private int lastWindowWidth = 0; private int lastWindowHeight = 0; private enum View { MAIN_MENU, ALT_SCREEN } private View currentView = View.MAIN_MENU; private long screenStartTime = 0L; private boolean initialized = false; private long lastRenderTime = 0L; private int hoveredButton = -1; private float[] buttonHoverProgress = new float[6]; private final AccountRenderer accountRenderer; private final AccountConfig accountConfig; private String nicknameText = ""; private boolean nicknameFieldFocused = false; private float scrollOffset = 0f; private float targetScrollOffset = 0f; public MainMenuScreen() { super(Text.literal("Main Menu")); for (int i = 0; i < 6; i++) { buttonHoverProgress[i] = 0f; } this.accountRenderer = new AccountRenderer(); this.accountConfig = AccountConfig.getInstance(); this.accountConfig.load(); } @Override protected void init() { initialized = false; particlesInitialized = false; } private int getFixedScaledWidth() { return (int) Math.ceil((double) client.getWindow().getFramebufferWidth() / FIXED_GUI_SCALE); } private int getFixedScaledHeight() { return (int) Math.ceil((double) client.getWindow().getFramebufferHeight() / FIXED_GUI_SCALE); } private float toFixedCoord(double coord) { float currentScale = (float) client.getWindow().getScaleFactor(); return (float) (coord * currentScale / FIXED_GUI_SCALE); } private void initParticles(int width, int height) { if (particlesInitialized) return; Random rand = new Random(); for (int i = 0; i < PARTICLE_COUNT; i++) { particles.add(new Particle(rand.nextFloat() * width, rand.nextFloat() * height)); } particlesInitialized = true; } private void drawBackground() { int screenWidth = getFixedScaledWidth(); int screenHeight = getFixedScaledHeight(); Render2D.rect(0, 0, screenWidth, screenHeight, new Color(12, 15, 18).getRGB()); initParticles(screenWidth, screenHeight); for (Particle p : particles) { if (!p.isDead && p.alpha > 0.01f) { int alpha = (int) (p.alpha * 255); Render2D.rect(p.x, p.y, p.size, p.size, new Color(255, 255, 255, alpha).getRGB()); } } } @Override public void render(DrawContext context, int mouseX, int mouseY, float delta) { long currentTime = Util.getMeasuringTimeMs(); if (!initialized) { screenStartTime = currentTime; lastRenderTime = currentTime; initialized = true; } float deltaTime = Math.min(delta, 0.05f); lastRenderTime = currentTime; int fixedWidth = getFixedScaledWidth(); int fixedHeight = getFixedScaledHeight(); if (lastWindowWidth != fixedWidth || lastWindowHeight != fixedHeight) { particles.clear(); particlesInitialized = false; lastWindowWidth = fixedWidth; lastWindowHeight = fixedHeight; } for (Particle p : particles) { p.update(deltaTime * 60f, fixedWidth, fixedHeight); } particles.removeIf(p -> p.isDead); Random rand = new Random(); while (particles.size() < PARTICLE_COUNT) { particles.add(new Particle(rand.nextFloat() * fixedWidth, rand.nextFloat() * fixedHeight)); } float scaledMouseX = toFixedCoord(mouseX); float scaledMouseY = toFixedCoord(mouseY); updateButtonAnimations(deltaTime, scaledMouseX, scaledMouseY, fixedWidth, fixedHeight); Render2D.beginOverlay(); drawBackground(); if (currentView == View.MAIN_MENU) { renderMainMenu(fixedWidth, fixedHeight, scaledMouseX, scaledMouseY); } else { renderAltScreen(fixedWidth, fixedHeight, scaledMouseX, scaledMouseY, currentTime); } Render2D.endOverlay(); } private void renderMainMenu(int screenWidth, int screenHeight, float mouseX, float mouseY) { float centerX = screenWidth / 2f; float centerY = screenHeight / 2f; String username = "user"; float avatarSize = 20; float avatarX = 8; float avatarY = 10; Fonts.INTER_MEDIUM.draw("Logged in as", avatarX + avatarSize + 5, avatarY, 7f, new Color(150, 150, 150).getRGB()); Fonts.INTER_MEDIUM.draw(username, avatarX + avatarSize + 5, avatarY + 9, 8f, new Color(255, 255, 255).getRGB()); Render2D.rect(avatarX, avatarY, avatarSize, avatarSize, new Color(40, 45, 55).getRGB(), avatarSize / 2f); Identifier userAvatar = Identifier.of("rich", "user.png"); int[] avatarColors = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}; float[] avatarRadii = {avatarSize / 2f, avatarSize / 2f, avatarSize / 2f, avatarSize / 2f}; Initialization.getInstance().getManager().getRenderCore().getTexturePipeline() .drawTexture(userAvatar, avatarX, avatarY, avatarSize, avatarSize, 0, 0, 1, 1, avatarColors, avatarRadii, 1f); float logoSize = 35; float logoY = centerY - 90; Identifier logoTexture = Identifier.of("rich", "images/logo.png"); int[] logoColors = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}; float[] logoRadii = {0, 0, 0, 0}; Initialization.getInstance().getManager().getRenderCore().getTexturePipeline() .drawTexture(logoTexture, centerX - logoSize / 2f, logoY, logoSize, logoSize, 0, 0, 1, 1, logoColors, logoRadii, 1f); String timeOfDay = getTimeOfDay(); String greeting = "Good " + timeOfDay + ", "; String usernameColored = username; float greetingWidth = Fonts.INTER_SEMIBOLD.getWidth(greeting, 14f); float usernameWidth = Fonts.INTER_SEMIBOLD.getWidth(usernameColored, 14f); float totalGreetingWidth = greetingWidth + usernameWidth; float greetingStartX = centerX - totalGreetingWidth / 2f; float greetingY = centerY - 38; Fonts.INTER_SEMIBOLD.draw(greeting, greetingStartX, greetingY, 14f, new Color(255, 255, 255).getRGB()); Fonts.INTER_SEMIBOLD.draw(usernameColored, greetingStartX + greetingWidth, greetingY, 14f, new Color(100, 180, 255).getRGB()); String welcomeText = "Welcome to "; String clientName = "WexSide. The best client."; String restText = ""; float welcomeWidth = Fonts.INTER_MEDIUM.getWidth(welcomeText, 9f); float clientWidth = Fonts.INTER_MEDIUM.getWidth(clientName, 9f); float restWidth = Fonts.INTER_MEDIUM.getWidth(restText, 9f); float totalWidth = welcomeWidth + clientWidth + restWidth; float startX = centerX - totalWidth / 2f; float textY = centerY - 20; Fonts.INTER_MEDIUM.draw(welcomeText, startX, textY, 9f, new Color(180, 180, 180).getRGB()); Fonts.INTER_SEMIBOLD.draw(clientName, startX + welcomeWidth, textY, 9f, new Color(90, 22, 134).getRGB()); Fonts.INTER_MEDIUM.draw(restText, startX + welcomeWidth + clientWidth, textY, 9f, new Color(180, 180, 180).getRGB()); float buttonWidth = 220; float buttonHeight = 30; float buttonSpacing = 7; float buttonStartY = centerY + 3; drawButton(centerX - buttonWidth / 2f, buttonStartY, buttonWidth, buttonHeight, "Singleplayer", 0, mouseX, mouseY, new Color(30, 35, 45), false); drawButton(centerX - buttonWidth / 2f, buttonStartY + buttonHeight + buttonSpacing, buttonWidth, buttonHeight, "Multiplayer", 1, mouseX, mouseY, new Color(30, 35, 45), false); float swapAccountsY = buttonStartY + (buttonHeight + buttonSpacing) * 2 + 5; drawButton(centerX - buttonWidth / 2f, swapAccountsY, buttonWidth, buttonHeight, "Swap Accounts", 2, mouseX, mouseY, new Color(90, 22, 134), true); float bottomY = swapAccountsY + buttonHeight + 5; float bottomButtonWidth = 65; float bottomButtonHeight = 20; float bottomSpacing = 10; float totalBottomWidth = bottomButtonWidth * 3 + bottomSpacing * 2; float bottomStartX = centerX - totalBottomWidth / 2f; drawSmallButton(bottomStartX, bottomY, bottomButtonWidth, bottomButtonHeight, "Options", 3, mouseX, mouseY); drawSmallButton(bottomStartX + bottomButtonWidth + bottomSpacing, bottomY, bottomButtonWidth, bottomButtonHeight, "Proxies", 4, mouseX, mouseY); drawSmallButton(bottomStartX + (bottomButtonWidth + bottomSpacing) * 2, bottomY, bottomButtonWidth, bottomButtonHeight, "Exit", 5, mouseX, mouseY); String footerText = "By logging into your account, you agree to all of our policies,"; String policyLinks = "including our Privacy Policy and Terms of Service"; Fonts.INTER_MEDIUM.drawCentered(footerText, centerX, screenHeight - 17, 6.5f, new Color(100, 100, 100).getRGB()); Fonts.INTER_MEDIUM.drawCentered(policyLinks, centerX, screenHeight - 8, 6.5f, new Color(100, 100, 100).getRGB()); } private String getTimeOfDay() { int hour = java.time.LocalTime.now().getHour(); if (hour >= 5 && hour < 12) return "morning"; if (hour >= 12 && hour < 17) return "afternoon"; if (hour >= 17 && hour < 21) return "evening"; return "night"; } private void drawButton(float x, float y, float width, float height, String text, int index, float mouseX, float mouseY, Color baseColor, boolean isPurple) { boolean hovered = isMouseOver(mouseX, mouseY, x, y, width, height); float hoverProgress = buttonHoverProgress[index]; Color bgColor = baseColor; if (isPurple) { int brightness = (int) (hoverProgress * 20); bgColor = new Color( Math.min(255, baseColor.getRed() + brightness), Math.min(255, baseColor.getGreen() + brightness), Math.min(255, baseColor.getBlue() + brightness) ); } else { int brightness = (int) (hoverProgress * 15); bgColor = new Color( Math.min(255, baseColor.getRed() + brightness), Math.min(255, baseColor.getGreen() + brightness), Math.min(255, baseColor.getBlue() + brightness) ); } Render2D.rect(x, y, width, height, bgColor.getRGB(), 8); if (!isPurple) { Render2D.outline(x, y, width, height, 1f, new Color(50, 55, 65, 80).getRGB(), 8); } if (hoverProgress > 0.01f) { int borderAlpha = (int) (hoverProgress * 100); Color borderColor = isPurple ? new Color(138, 43, 226, borderAlpha) : new Color(100, 110, 130, borderAlpha); Render2D.outline(x, y, width, height, 1f, borderColor.getRGB(), 8); } float fontSize = 9f; float textHeight = Fonts.INTER_MEDIUM.getHeight(fontSize); Color textColor = isPurple ? new Color(255, 255, 255) : new Color(160, 160, 160); Fonts.INTER_MEDIUM.drawCentered(text, x + width / 2f, y + (height - textHeight) / 2f, fontSize, textColor.getRGB()); } private void drawSmallButton(float x, float y, float width, float height, String text, int index, float mouseX, float mouseY) { float hoverProgress = buttonHoverProgress[index]; int baseAlpha = 150; int hoverAlpha = (int) (baseAlpha + hoverProgress * 50); float fontSize = 8f; float textHeight = Fonts.INTER_MEDIUM.getHeight(fontSize); Fonts.INTER_MEDIUM.drawCentered(text, x + width / 2f, y + (height - textHeight) / 2f, fontSize, new Color(180, 180, 180, hoverAlpha).getRGB()); } private boolean isMouseOver(float mouseX, float mouseY, float x, float y, float width, float height) { return mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height; } private void updateButtonAnimations(float deltaTime, float mouseX, float mouseY, int screenWidth, int screenHeight) { float centerX = screenWidth / 2f; float centerY = screenHeight / 2f; float lerpSpeed = 1f - (float) Math.pow(0.001f, deltaTime); if (currentView == View.MAIN_MENU) { float buttonWidth = 220; float buttonHeight = 30; float buttonSpacing = 7; float buttonStartY = centerY + 3; for (int i = 0; i < 2; i++) { float y = buttonStartY + i * (buttonHeight + buttonSpacing); boolean hovered = isMouseOver(mouseX, mouseY, centerX - buttonWidth / 2f, y, buttonWidth, buttonHeight); float target = hovered ? 1f : 0f; buttonHoverProgress[i] = MathHelper.lerp(lerpSpeed, buttonHoverProgress[i], target); } float swapAccountsY = buttonStartY + (buttonHeight + buttonSpacing) * 2 + 5; boolean swapHovered = isMouseOver(mouseX, mouseY, centerX - buttonWidth / 2f, swapAccountsY, buttonWidth, buttonHeight); buttonHoverProgress[2] = MathHelper.lerp(lerpSpeed, buttonHoverProgress[2], swapHovered ? 1f : 0f); float bottomY = swapAccountsY + buttonHeight + 5; float bottomButtonWidth = 65; float bottomButtonHeight = 20; float bottomSpacing = 10; float totalBottomWidth = bottomButtonWidth * 3 + bottomSpacing * 2; float bottomStartX = centerX - totalBottomWidth / 2f; for (int i = 0; i < 3; i++) { float x = bottomStartX + i * (bottomButtonWidth + bottomSpacing); boolean hovered = isMouseOver(mouseX, mouseY, x, bottomY, bottomButtonWidth, bottomButtonHeight); float target = hovered ? 1f : 0f; buttonHoverProgress[i + 3] = MathHelper.lerp(lerpSpeed, buttonHoverProgress[i + 3], target); } } else { for (int i = 0; i < 6; i++) { buttonHoverProgress[i] = MathHelper.lerp(lerpSpeed, buttonHoverProgress[i], 0f); } } } private void renderAltScreen(int screenWidth, int screenHeight, float mouseX, float mouseY, long currentTime) { float totalWidth = 405; float totalHeight = 163; float centerX = screenWidth / 2f; float centerY = screenHeight / 2f; float startX = centerX - totalWidth / 2f; float startY = centerY - totalHeight / 2f; float leftPanelX = startX; float leftPanelTopY = startY; accountRenderer.renderLeftPanelTop(leftPanelX, leftPanelTopY, 100, 100, 1f, nicknameText, nicknameFieldFocused, mouseX, mouseY, currentTime); float leftPanelBottomY = startY + 100 + 5; accountRenderer.renderLeftPanelBottom(leftPanelX, leftPanelBottomY, 100, 58, 1f, accountConfig.getActiveAccountName(), accountConfig.getActiveAccountDate(), accountConfig.getActiveAccountSkin()); float rightPanelX = startX + 100 + 5; float rightPanelY = startY; List<AccountEntry> sortedAccounts = accountConfig.getSortedAccounts(); accountRenderer.renderRightPanel(rightPanelX, rightPanelY, 300, 165, 1f, sortedAccounts, scrollOffset, mouseX, mouseY, 1f, (int) FIXED_GUI_SCALE); } @Override public boolean mouseClicked(Click click, boolean doubled) { float scaledMouseX = toFixedCoord(click.x()); float scaledMouseY = toFixedCoord(click.y()); if (currentView == View.MAIN_MENU) { if (click.button() == 0) { int fixedWidth = getFixedScaledWidth(); int fixedHeight = getFixedScaledHeight(); float centerX = fixedWidth / 2f; float centerY = fixedHeight / 2f; float buttonWidth = 220; float buttonHeight = 30; float buttonSpacing = 7; float buttonStartY = centerY + 3; for (int i = 0; i < 2; i++) { float y = buttonStartY + i * (buttonHeight + buttonSpacing); if (isMouseOver(scaledMouseX, scaledMouseY, centerX - buttonWidth / 2f, y, buttonWidth, buttonHeight)) { handleMainMenuButtonClick(i); return true; } } float swapAccountsY = buttonStartY + (buttonHeight + buttonSpacing) * 2 + 5; if (isMouseOver(scaledMouseX, scaledMouseY, centerX - buttonWidth / 2f, swapAccountsY, buttonWidth, buttonHeight)) { handleMainMenuButtonClick(2); return true; } float bottomY = swapAccountsY + buttonHeight + 5; float bottomButtonWidth = 65; float bottomButtonHeight = 20; float bottomSpacing = 10; float totalBottomWidth = bottomButtonWidth * 3 + bottomSpacing * 2; float bottomStartX = centerX - totalBottomWidth / 2f; for (int i = 0; i < 3; i++) { float x = bottomStartX + i * (bottomButtonWidth + bottomSpacing); if (isMouseOver(scaledMouseX, scaledMouseY, x, bottomY, bottomButtonWidth, bottomButtonHeight)) { handleMainMenuButtonClick(i + 3); return true; } } } } else if (currentView == View.ALT_SCREEN) { return handleAltScreenClick(scaledMouseX, scaledMouseY, click); } return super.mouseClicked(click, doubled); } private void handleMainMenuButtonClick(int index) { switch (index) { case 0 -> this.client.setScreen(new SelectWorldScreen(this)); case 1 -> { Screen screen = this.client.options.skipMultiplayerWarning ? new MultiplayerScreen(this) : new MultiplayerWarningScreen(this); this.client.setScreen(screen); } case 2 -> currentView = View.ALT_SCREEN; case 3 -> this.client.setScreen(new OptionsScreen(this, this.client.options)); case 4 -> {} case 5 -> this.client.scheduleStop(); } } private boolean handleAltScreenClick(float mouseX, float mouseY, Click click) { int screenWidth = getFixedScaledWidth(); int screenHeight = getFixedScaledHeight(); float totalWidth = 100 + 5 + 300; float totalHeight = 100 + 5 + 58; float centerX = screenWidth / 2f; float centerY = screenHeight / 2f; float startX = centerX - totalWidth / 2f; float startY = centerY - totalHeight / 2f; float leftPanelX = startX; float leftPanelTopY = startY; float fieldX = leftPanelX + 5; float fieldY = leftPanelTopY + 38; float fieldHeight = 14; float addButtonSize = 14; float buttonGap = 3; float fieldWidth = 100 - 10 - addButtonSize - buttonGap; if (accountRenderer.isMouseOver(mouseX, mouseY, fieldX, fieldY, fieldWidth, fieldHeight)) { nicknameFieldFocused = true; return true; } else { nicknameFieldFocused = false; } float addButtonX = fieldX + fieldWidth + buttonGap; float addButtonY = fieldY; if (accountRenderer.isMouseOver(mouseX, mouseY, addButtonX, addButtonY, addButtonSize, addButtonSize)) { if (!nicknameText.isEmpty()) { addAccount(nicknameText); nicknameText = ""; } return true; } float buttonWidth = 100 - 10; float buttonHeight = 16; float randomButtonX = leftPanelX + 5; float randomButtonY = fieldY + fieldHeight + 6; if (accountRenderer.isMouseOver(mouseX, mouseY, randomButtonX, randomButtonY, buttonWidth, buttonHeight)) { String randomNick = generateRandomNickname(); addAccount(randomNick); nicknameText = ""; return true; } float clearButtonX = leftPanelX + 5; float clearButtonY = randomButtonY + buttonHeight + 5; if (accountRenderer.isMouseOver(mouseX, mouseY, clearButtonX, clearButtonY, buttonWidth, buttonHeight)) { accountConfig.clearAllAccounts(); targetScrollOffset = 0f; scrollOffset = 0f; return true; } float rightPanelX = startX + 100 + 5; float rightPanelY = startY; float accountListX = rightPanelX + 5; float accountListY = rightPanelY + 26; float accountListWidth = 300 - 10; float accountListHeight = 165 - 31; if (!accountRenderer.isMouseOver(mouseX, mouseY, accountListX, accountListY, accountListWidth, accountListHeight)) { return false; } float cardWidth = (accountListWidth - 5) / 2f; float cardHeight = 40; float cardGap = 5; List<AccountEntry> sortedAccounts = accountConfig.getSortedAccounts(); for (int i = 0; i < sortedAccounts.size(); i++) { int col = i % 2; int row = i / 2; float cardX = accountListX + col * (cardWidth + cardGap); float cardY = accountListY + row * (cardHeight + cardGap) - scrollOffset; if (cardY + cardHeight < accountListY || cardY > accountListY + accountListHeight) { continue; } float btnSize = 12; float buttonYPos = cardY + cardHeight - btnSize - 5; float pinButtonX = cardX + cardWidth - btnSize * 2 - 8; float deleteButtonX = cardX + cardWidth - btnSize - 5; if (accountRenderer.isMouseOver(mouseX, mouseY, pinButtonX, buttonYPos, btnSize, btnSize)) { AccountEntry entry = sortedAccounts.get(i); entry.togglePinned(); if (entry.isPinned()) { setActiveAccount(entry); } accountConfig.save(); return true; } if (accountRenderer.isMouseOver(mouseX, mouseY, deleteButtonX, buttonYPos, btnSize, btnSize)) { accountConfig.removeAccountByIndex(i); return true; } if (accountRenderer.isMouseOver(mouseX, mouseY, cardX, cardY, cardWidth, cardHeight)) { setActiveAccount(sortedAccounts.get(i)); return true; } } return false; } @Override public boolean mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { if (currentView != View.ALT_SCREEN) return false; float scaledMouseX = toFixedCoord(mouseX); float scaledMouseY = toFixedCoord(mouseY); int screenWidth = getFixedScaledWidth(); int screenHeight = getFixedScaledHeight(); float totalWidth = 100 + 5 + 300; float totalHeight = 100 + 5 + 58; float centerX = screenWidth / 2f; float centerY = screenHeight / 2f; float startX = centerX - totalWidth / 2f; float startY = centerY - totalHeight / 2f; float rightPanelX = startX + 100 + 5; float rightPanelY = startY; if (accountRenderer.isMouseOver(scaledMouseX, scaledMouseY, rightPanelX, rightPanelY, 300, 165)) { float cardHeight = 40; float cardGap = 5; float accountListHeight = 165 - 31; int rows = (int) Math.ceil(accountConfig.getSortedAccounts().size() / 2.0); float maxScroll = Math.max(0, rows * (cardHeight + cardGap) - accountListHeight); targetScrollOffset -= (float) verticalAmount * 25; targetScrollOffset = MathHelper.clamp(targetScrollOffset, 0, maxScroll); float scrollSpeed = 12f; float deltaTime = 0.016f; float scrollDiff = targetScrollOffset - scrollOffset; scrollOffset += scrollDiff * Math.min(1f, deltaTime * scrollSpeed); return true; } return super.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount); } @Override public boolean keyPressed(KeyInput input) { if (currentView == View.ALT_SCREEN) { if (nicknameFieldFocused) { int keyCode = input.key(); if (keyCode == 259) { if (!nicknameText.isEmpty()) { nicknameText = nicknameText.substring(0, nicknameText.length() - 1); } return true; } if (keyCode == 256) { nicknameFieldFocused = false; return true; } if (keyCode == 257 || keyCode == 335) { if (!nicknameText.isEmpty()) { addAccount(nicknameText); nicknameText = ""; } nicknameFieldFocused = false; return true; } } if (input.key() == 256) { currentView = View.MAIN_MENU; accountConfig.save(); return true; } } return super.keyPressed(input); } @Override public boolean charTyped(CharInput input) { if (currentView == View.ALT_SCREEN && nicknameFieldFocused) { int codepoint = input.codepoint(); if (Character.isLetterOrDigit(codepoint) || codepoint == '_') { if (nicknameText.length() < 16) { nicknameText += Character.toString(codepoint); } return true; } } return super.charTyped(input); } private void setActiveAccount(AccountEntry account) { accountConfig.setActiveAccount(account.getName(), account.getDate(), account.getSkin()); SessionChanger.changeUsername(account.getName()); } private void addAccount(String nickname) { LocalDateTime now = LocalDateTime.now(); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm"); String date = now.format(formatter); AccountEntry entry = new AccountEntry(nickname, date, null); accountConfig.addAccount(entry); setActiveAccount(entry); SessionChanger.changeUsername(nickname); } private String generateRandomNickname() { Random random = new Random(); StringBuilder username = new StringBuilder(); char[] vowels = {'a', 'e', 'i', 'o', 'u'}; char[] consonants = {'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z'}; String finalUsername = null; int attempts = 0; final int MAX_ATTEMPTS = 10; List<AccountEntry> existingAccounts = accountConfig.getAccounts(); do { username.setLength(0); int length = 6 + random.nextInt(5); boolean startWithVowel = random.nextBoolean(); for (int i = 0; i < length; i++) { if (i % 2 == 0) { username.append(startWithVowel ? vowels[random.nextInt(vowels.length)] : consonants[random.nextInt(consonants.length)]); } else { username.append(startWithVowel ? consonants[random.nextInt(consonants.length)] : vowels[random.nextInt(vowels.length)]); } } if (random.nextInt(100) < 30) { username.append(random.nextInt(100)); } String tempUsername = username.substring(0, 1).toUpperCase() + username.substring(1); attempts++; boolean exists = false; for (AccountEntry account : existingAccounts) { if (account.getName().equalsIgnoreCase(tempUsername)) { exists = true; break; } } if (!exists) { finalUsername = tempUsername; break; } } while (attempts < MAX_ATTEMPTS); if (finalUsername == null) { finalUsername = username.substring(0, 1).toUpperCase() + username.substring(1) + (System.currentTimeMillis() % 1000); } return finalUsername; } @Override public void renderBackground(DrawContext context, int mouseX, int mouseY, float delta) { drawBackground(); } @Override public boolean shouldCloseOnEsc() { return false; } @Override public boolean shouldPause() { return false; } private int withAlpha(int color, int alpha) { return (color & 0x00FFFFFF) | (MathHelper.clamp(alpha, 0, 255) << 24); } } }
Посмотреть вложение 327281
мое:Посмотреть вложение 327344
upd: добавил обводку
+repврод похоже хз
фонты думаю сами найдете
векса:код:package rich.screens.menu; import net.minecraft.client.gui.Click; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen; import net.minecraft.client.gui.screen.multiplayer.MultiplayerWarningScreen; import net.minecraft.client.gui.screen.option.OptionsScreen; import net.minecraft.client.gui.screen.world.SelectWorldScreen; import net.minecraft.client.input.KeyInput; import net.minecraft.client.input.CharInput; import net.minecraft.text.Text; import net.minecraft.util.Identifier; import net.minecraft.util.Util; import net.minecraft.util.math.MathHelper; import rich.Initialization; import rich.screens.account.AccountEntry; import rich.screens.account.AccountRenderer; import rich.util.config.impl.account.AccountConfig; import rich.util.render.Render2D; import rich.util.render.font.Fonts; import rich.util.session.SessionChanger; import rich.util.sounds.SoundManager; import antidaunleak.api.UserProfile; import java.awt.*; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.List; import java.util.Random; public class MainMenuScreen extends Screen { private static final Identifier BACKGROUND_TEXTURE = Identifier.of("rich", "textures/menu/backmenu.png"); private static final float FIXED_GUI_SCALE = 2.0f; private static final int PARTICLE_COUNT = 50; private static final float PARTICLE_FADE_THRESHOLD = 0.8f; private static class Particle { float x, y; float vx, vy; float size; float alpha; float lifetime; float maxLifetime; boolean isDead = false; Particle(float x, float y) { this.x = x; this.y = y; Random rand = new Random(); this.vx = (rand.nextFloat() - 0.5f) * 0.2f; this.vy = (rand.nextFloat() - 0.5f) * 0.2f; this.size = 0.5f + rand.nextFloat() * 1f; this.alpha = 0.2f + rand.nextFloat() * 0.3f; this.maxLifetime = 10f + rand.nextFloat() * 10f; this.lifetime = 0f; } void update(float delta, int width, int height) { lifetime += delta / 60f; if (lifetime > maxLifetime * PARTICLE_FADE_THRESHOLD) { float fadeProgress = (lifetime - maxLifetime * PARTICLE_FADE_THRESHOLD) / (maxLifetime * (1f - PARTICLE_FADE_THRESHOLD)); alpha = Math.max(0, alpha * (1f - fadeProgress)); } if (lifetime >= maxLifetime) { isDead = true; return; } x += vx * delta; y += vy * delta; if (x < -10 || x > width + 10 || y < -10 || y > height + 10) { isDead = true; } } } private final List<Particle> particles = new java.util.ArrayList<>(); private boolean particlesInitialized = false; private int lastWindowWidth = 0; private int lastWindowHeight = 0; private enum View { MAIN_MENU, ALT_SCREEN } private View currentView = View.MAIN_MENU; private long screenStartTime = 0L; private boolean initialized = false; private long lastRenderTime = 0L; private int hoveredButton = -1; private float[] buttonHoverProgress = new float[6]; private final AccountRenderer accountRenderer; private final AccountConfig accountConfig; private String nicknameText = ""; private boolean nicknameFieldFocused = false; private float scrollOffset = 0f; private float targetScrollOffset = 0f; public MainMenuScreen() { super(Text.literal("Main Menu")); for (int i = 0; i < 6; i++) { buttonHoverProgress[i] = 0f; } this.accountRenderer = new AccountRenderer(); this.accountConfig = AccountConfig.getInstance(); this.accountConfig.load(); } @Override protected void init() { initialized = false; particlesInitialized = false; } private int getFixedScaledWidth() { return (int) Math.ceil((double) client.getWindow().getFramebufferWidth() / FIXED_GUI_SCALE); } private int getFixedScaledHeight() { return (int) Math.ceil((double) client.getWindow().getFramebufferHeight() / FIXED_GUI_SCALE); } private float toFixedCoord(double coord) { float currentScale = (float) client.getWindow().getScaleFactor(); return (float) (coord * currentScale / FIXED_GUI_SCALE); } private void initParticles(int width, int height) { if (particlesInitialized) return; Random rand = new Random(); for (int i = 0; i < PARTICLE_COUNT; i++) { particles.add(new Particle(rand.nextFloat() * width, rand.nextFloat() * height)); } particlesInitialized = true; } private void drawBackground() { int screenWidth = getFixedScaledWidth(); int screenHeight = getFixedScaledHeight(); Render2D.rect(0, 0, screenWidth, screenHeight, new Color(12, 15, 18).getRGB()); initParticles(screenWidth, screenHeight); for (Particle p : particles) { if (!p.isDead && p.alpha > 0.01f) { int alpha = (int) (p.alpha * 255); Render2D.rect(p.x, p.y, p.size, p.size, new Color(255, 255, 255, alpha).getRGB()); } } } @Override public void render(DrawContext context, int mouseX, int mouseY, float delta) { long currentTime = Util.getMeasuringTimeMs(); if (!initialized) { screenStartTime = currentTime; lastRenderTime = currentTime; initialized = true; } float deltaTime = Math.min(delta, 0.05f); lastRenderTime = currentTime; int fixedWidth = getFixedScaledWidth(); int fixedHeight = getFixedScaledHeight(); if (lastWindowWidth != fixedWidth || lastWindowHeight != fixedHeight) { particles.clear(); particlesInitialized = false; lastWindowWidth = fixedWidth; lastWindowHeight = fixedHeight; } for (Particle p : particles) { p.update(deltaTime * 60f, fixedWidth, fixedHeight); } particles.removeIf(p -> p.isDead); Random rand = new Random(); while (particles.size() < PARTICLE_COUNT) { particles.add(new Particle(rand.nextFloat() * fixedWidth, rand.nextFloat() * fixedHeight)); } float scaledMouseX = toFixedCoord(mouseX); float scaledMouseY = toFixedCoord(mouseY); updateButtonAnimations(deltaTime, scaledMouseX, scaledMouseY, fixedWidth, fixedHeight); Render2D.beginOverlay(); drawBackground(); if (currentView == View.MAIN_MENU) { renderMainMenu(fixedWidth, fixedHeight, scaledMouseX, scaledMouseY); } else { renderAltScreen(fixedWidth, fixedHeight, scaledMouseX, scaledMouseY, currentTime); } Render2D.endOverlay(); } private void renderMainMenu(int screenWidth, int screenHeight, float mouseX, float mouseY) { float centerX = screenWidth / 2f; float centerY = screenHeight / 2f; String username = "user"; float avatarSize = 20; float avatarX = 8; float avatarY = 10; Fonts.INTER_MEDIUM.draw("Logged in as", avatarX + avatarSize + 5, avatarY, 7f, new Color(150, 150, 150).getRGB()); Fonts.INTER_MEDIUM.draw(username, avatarX + avatarSize + 5, avatarY + 9, 8f, new Color(255, 255, 255).getRGB()); Render2D.rect(avatarX, avatarY, avatarSize, avatarSize, new Color(40, 45, 55).getRGB(), avatarSize / 2f); Identifier userAvatar = Identifier.of("rich", "user.png"); int[] avatarColors = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}; float[] avatarRadii = {avatarSize / 2f, avatarSize / 2f, avatarSize / 2f, avatarSize / 2f}; Initialization.getInstance().getManager().getRenderCore().getTexturePipeline() .drawTexture(userAvatar, avatarX, avatarY, avatarSize, avatarSize, 0, 0, 1, 1, avatarColors, avatarRadii, 1f); float logoSize = 35; float logoY = centerY - 90; Identifier logoTexture = Identifier.of("rich", "images/logo.png"); int[] logoColors = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}; float[] logoRadii = {0, 0, 0, 0}; Initialization.getInstance().getManager().getRenderCore().getTexturePipeline() .drawTexture(logoTexture, centerX - logoSize / 2f, logoY, logoSize, logoSize, 0, 0, 1, 1, logoColors, logoRadii, 1f); String timeOfDay = getTimeOfDay(); String greeting = "Good " + timeOfDay + ", "; String usernameColored = username; float greetingWidth = Fonts.INTER_SEMIBOLD.getWidth(greeting, 14f); float usernameWidth = Fonts.INTER_SEMIBOLD.getWidth(usernameColored, 14f); float totalGreetingWidth = greetingWidth + usernameWidth; float greetingStartX = centerX - totalGreetingWidth / 2f; float greetingY = centerY - 38; Fonts.INTER_SEMIBOLD.draw(greeting, greetingStartX, greetingY, 14f, new Color(255, 255, 255).getRGB()); Fonts.INTER_SEMIBOLD.draw(usernameColored, greetingStartX + greetingWidth, greetingY, 14f, new Color(100, 180, 255).getRGB()); String welcomeText = "Welcome to "; String clientName = "WexSide. The best client."; String restText = ""; float welcomeWidth = Fonts.INTER_MEDIUM.getWidth(welcomeText, 9f); float clientWidth = Fonts.INTER_MEDIUM.getWidth(clientName, 9f); float restWidth = Fonts.INTER_MEDIUM.getWidth(restText, 9f); float totalWidth = welcomeWidth + clientWidth + restWidth; float startX = centerX - totalWidth / 2f; float textY = centerY - 20; Fonts.INTER_MEDIUM.draw(welcomeText, startX, textY, 9f, new Color(180, 180, 180).getRGB()); Fonts.INTER_SEMIBOLD.draw(clientName, startX + welcomeWidth, textY, 9f, new Color(90, 22, 134).getRGB()); Fonts.INTER_MEDIUM.draw(restText, startX + welcomeWidth + clientWidth, textY, 9f, new Color(180, 180, 180).getRGB()); float buttonWidth = 220; float buttonHeight = 30; float buttonSpacing = 7; float buttonStartY = centerY + 3; drawButton(centerX - buttonWidth / 2f, buttonStartY, buttonWidth, buttonHeight, "Singleplayer", 0, mouseX, mouseY, new Color(30, 35, 45), false); drawButton(centerX - buttonWidth / 2f, buttonStartY + buttonHeight + buttonSpacing, buttonWidth, buttonHeight, "Multiplayer", 1, mouseX, mouseY, new Color(30, 35, 45), false); float swapAccountsY = buttonStartY + (buttonHeight + buttonSpacing) * 2 + 5; drawButton(centerX - buttonWidth / 2f, swapAccountsY, buttonWidth, buttonHeight, "Swap Accounts", 2, mouseX, mouseY, new Color(90, 22, 134), true); float bottomY = swapAccountsY + buttonHeight + 5; float bottomButtonWidth = 65; float bottomButtonHeight = 20; float bottomSpacing = 10; float totalBottomWidth = bottomButtonWidth * 3 + bottomSpacing * 2; float bottomStartX = centerX - totalBottomWidth / 2f; drawSmallButton(bottomStartX, bottomY, bottomButtonWidth, bottomButtonHeight, "Options", 3, mouseX, mouseY); drawSmallButton(bottomStartX + bottomButtonWidth + bottomSpacing, bottomY, bottomButtonWidth, bottomButtonHeight, "Proxies", 4, mouseX, mouseY); drawSmallButton(bottomStartX + (bottomButtonWidth + bottomSpacing) * 2, bottomY, bottomButtonWidth, bottomButtonHeight, "Exit", 5, mouseX, mouseY); String footerText = "By logging into your account, you agree to all of our policies,"; String policyLinks = "including our Privacy Policy and Terms of Service"; Fonts.INTER_MEDIUM.drawCentered(footerText, centerX, screenHeight - 17, 6.5f, new Color(100, 100, 100).getRGB()); Fonts.INTER_MEDIUM.drawCentered(policyLinks, centerX, screenHeight - 8, 6.5f, new Color(100, 100, 100).getRGB()); } private String getTimeOfDay() { int hour = java.time.LocalTime.now().getHour(); if (hour >= 5 && hour < 12) return "morning"; if (hour >= 12 && hour < 17) return "afternoon"; if (hour >= 17 && hour < 21) return "evening"; return "night"; } private void drawButton(float x, float y, float width, float height, String text, int index, float mouseX, float mouseY, Color baseColor, boolean isPurple) { boolean hovered = isMouseOver(mouseX, mouseY, x, y, width, height); float hoverProgress = buttonHoverProgress[index]; Color bgColor = baseColor; if (isPurple) { int brightness = (int) (hoverProgress * 20); bgColor = new Color( Math.min(255, baseColor.getRed() + brightness), Math.min(255, baseColor.getGreen() + brightness), Math.min(255, baseColor.getBlue() + brightness) ); } else { int brightness = (int) (hoverProgress * 15); bgColor = new Color( Math.min(255, baseColor.getRed() + brightness), Math.min(255, baseColor.getGreen() + brightness), Math.min(255, baseColor.getBlue() + brightness) ); } Render2D.rect(x, y, width, height, bgColor.getRGB(), 8); if (!isPurple) { Render2D.outline(x, y, width, height, 1f, new Color(50, 55, 65, 80).getRGB(), 8); } if (hoverProgress > 0.01f) { int borderAlpha = (int) (hoverProgress * 100); Color borderColor = isPurple ? new Color(138, 43, 226, borderAlpha) : new Color(100, 110, 130, borderAlpha); Render2D.outline(x, y, width, height, 1f, borderColor.getRGB(), 8); } float fontSize = 9f; float textHeight = Fonts.INTER_MEDIUM.getHeight(fontSize); Color textColor = isPurple ? new Color(255, 255, 255) : new Color(160, 160, 160); Fonts.INTER_MEDIUM.drawCentered(text, x + width / 2f, y + (height - textHeight) / 2f, fontSize, textColor.getRGB()); } private void drawSmallButton(float x, float y, float width, float height, String text, int index, float mouseX, float mouseY) { float hoverProgress = buttonHoverProgress[index]; int baseAlpha = 150; int hoverAlpha = (int) (baseAlpha + hoverProgress * 50); float fontSize = 8f; float textHeight = Fonts.INTER_MEDIUM.getHeight(fontSize); Fonts.INTER_MEDIUM.drawCentered(text, x + width / 2f, y + (height - textHeight) / 2f, fontSize, new Color(180, 180, 180, hoverAlpha).getRGB()); } private boolean isMouseOver(float mouseX, float mouseY, float x, float y, float width, float height) { return mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height; } private void updateButtonAnimations(float deltaTime, float mouseX, float mouseY, int screenWidth, int screenHeight) { float centerX = screenWidth / 2f; float centerY = screenHeight / 2f; float lerpSpeed = 1f - (float) Math.pow(0.001f, deltaTime); if (currentView == View.MAIN_MENU) { float buttonWidth = 220; float buttonHeight = 30; float buttonSpacing = 7; float buttonStartY = centerY + 3; for (int i = 0; i < 2; i++) { float y = buttonStartY + i * (buttonHeight + buttonSpacing); boolean hovered = isMouseOver(mouseX, mouseY, centerX - buttonWidth / 2f, y, buttonWidth, buttonHeight); float target = hovered ? 1f : 0f; buttonHoverProgress[i] = MathHelper.lerp(lerpSpeed, buttonHoverProgress[i], target); } float swapAccountsY = buttonStartY + (buttonHeight + buttonSpacing) * 2 + 5; boolean swapHovered = isMouseOver(mouseX, mouseY, centerX - buttonWidth / 2f, swapAccountsY, buttonWidth, buttonHeight); buttonHoverProgress[2] = MathHelper.lerp(lerpSpeed, buttonHoverProgress[2], swapHovered ? 1f : 0f); float bottomY = swapAccountsY + buttonHeight + 5; float bottomButtonWidth = 65; float bottomButtonHeight = 20; float bottomSpacing = 10; float totalBottomWidth = bottomButtonWidth * 3 + bottomSpacing * 2; float bottomStartX = centerX - totalBottomWidth / 2f; for (int i = 0; i < 3; i++) { float x = bottomStartX + i * (bottomButtonWidth + bottomSpacing); boolean hovered = isMouseOver(mouseX, mouseY, x, bottomY, bottomButtonWidth, bottomButtonHeight); float target = hovered ? 1f : 0f; buttonHoverProgress[i + 3] = MathHelper.lerp(lerpSpeed, buttonHoverProgress[i + 3], target); } } else { for (int i = 0; i < 6; i++) { buttonHoverProgress[i] = MathHelper.lerp(lerpSpeed, buttonHoverProgress[i], 0f); } } } private void renderAltScreen(int screenWidth, int screenHeight, float mouseX, float mouseY, long currentTime) { float totalWidth = 405; float totalHeight = 163; float centerX = screenWidth / 2f; float centerY = screenHeight / 2f; float startX = centerX - totalWidth / 2f; float startY = centerY - totalHeight / 2f; float leftPanelX = startX; float leftPanelTopY = startY; accountRenderer.renderLeftPanelTop(leftPanelX, leftPanelTopY, 100, 100, 1f, nicknameText, nicknameFieldFocused, mouseX, mouseY, currentTime); float leftPanelBottomY = startY + 100 + 5; accountRenderer.renderLeftPanelBottom(leftPanelX, leftPanelBottomY, 100, 58, 1f, accountConfig.getActiveAccountName(), accountConfig.getActiveAccountDate(), accountConfig.getActiveAccountSkin()); float rightPanelX = startX + 100 + 5; float rightPanelY = startY; List<AccountEntry> sortedAccounts = accountConfig.getSortedAccounts(); accountRenderer.renderRightPanel(rightPanelX, rightPanelY, 300, 165, 1f, sortedAccounts, scrollOffset, mouseX, mouseY, 1f, (int) FIXED_GUI_SCALE); } @Override public boolean mouseClicked(Click click, boolean doubled) { float scaledMouseX = toFixedCoord(click.x()); float scaledMouseY = toFixedCoord(click.y()); if (currentView == View.MAIN_MENU) { if (click.button() == 0) { int fixedWidth = getFixedScaledWidth(); int fixedHeight = getFixedScaledHeight(); float centerX = fixedWidth / 2f; float centerY = fixedHeight / 2f; float buttonWidth = 220; float buttonHeight = 30; float buttonSpacing = 7; float buttonStartY = centerY + 3; for (int i = 0; i < 2; i++) { float y = buttonStartY + i * (buttonHeight + buttonSpacing); if (isMouseOver(scaledMouseX, scaledMouseY, centerX - buttonWidth / 2f, y, buttonWidth, buttonHeight)) { handleMainMenuButtonClick(i); return true; } } float swapAccountsY = buttonStartY + (buttonHeight + buttonSpacing) * 2 + 5; if (isMouseOver(scaledMouseX, scaledMouseY, centerX - buttonWidth / 2f, swapAccountsY, buttonWidth, buttonHeight)) { handleMainMenuButtonClick(2); return true; } float bottomY = swapAccountsY + buttonHeight + 5; float bottomButtonWidth = 65; float bottomButtonHeight = 20; float bottomSpacing = 10; float totalBottomWidth = bottomButtonWidth * 3 + bottomSpacing * 2; float bottomStartX = centerX - totalBottomWidth / 2f; for (int i = 0; i < 3; i++) { float x = bottomStartX + i * (bottomButtonWidth + bottomSpacing); if (isMouseOver(scaledMouseX, scaledMouseY, x, bottomY, bottomButtonWidth, bottomButtonHeight)) { handleMainMenuButtonClick(i + 3); return true; } } } } else if (currentView == View.ALT_SCREEN) { return handleAltScreenClick(scaledMouseX, scaledMouseY, click); } return super.mouseClicked(click, doubled); } private void handleMainMenuButtonClick(int index) { switch (index) { case 0 -> this.client.setScreen(new SelectWorldScreen(this)); case 1 -> { Screen screen = this.client.options.skipMultiplayerWarning ? new MultiplayerScreen(this) : new MultiplayerWarningScreen(this); this.client.setScreen(screen); } case 2 -> currentView = View.ALT_SCREEN; case 3 -> this.client.setScreen(new OptionsScreen(this, this.client.options)); case 4 -> {} case 5 -> this.client.scheduleStop(); } } private boolean handleAltScreenClick(float mouseX, float mouseY, Click click) { int screenWidth = getFixedScaledWidth(); int screenHeight = getFixedScaledHeight(); float totalWidth = 100 + 5 + 300; float totalHeight = 100 + 5 + 58; float centerX = screenWidth / 2f; float centerY = screenHeight / 2f; float startX = centerX - totalWidth / 2f; float startY = centerY - totalHeight / 2f; float leftPanelX = startX; float leftPanelTopY = startY; float fieldX = leftPanelX + 5; float fieldY = leftPanelTopY + 38; float fieldHeight = 14; float addButtonSize = 14; float buttonGap = 3; float fieldWidth = 100 - 10 - addButtonSize - buttonGap; if (accountRenderer.isMouseOver(mouseX, mouseY, fieldX, fieldY, fieldWidth, fieldHeight)) { nicknameFieldFocused = true; return true; } else { nicknameFieldFocused = false; } float addButtonX = fieldX + fieldWidth + buttonGap; float addButtonY = fieldY; if (accountRenderer.isMouseOver(mouseX, mouseY, addButtonX, addButtonY, addButtonSize, addButtonSize)) { if (!nicknameText.isEmpty()) { addAccount(nicknameText); nicknameText = ""; } return true; } float buttonWidth = 100 - 10; float buttonHeight = 16; float randomButtonX = leftPanelX + 5; float randomButtonY = fieldY + fieldHeight + 6; if (accountRenderer.isMouseOver(mouseX, mouseY, randomButtonX, randomButtonY, buttonWidth, buttonHeight)) { String randomNick = generateRandomNickname(); addAccount(randomNick); nicknameText = ""; return true; } float clearButtonX = leftPanelX + 5; float clearButtonY = randomButtonY + buttonHeight + 5; if (accountRenderer.isMouseOver(mouseX, mouseY, clearButtonX, clearButtonY, buttonWidth, buttonHeight)) { accountConfig.clearAllAccounts(); targetScrollOffset = 0f; scrollOffset = 0f; return true; } float rightPanelX = startX + 100 + 5; float rightPanelY = startY; float accountListX = rightPanelX + 5; float accountListY = rightPanelY + 26; float accountListWidth = 300 - 10; float accountListHeight = 165 - 31; if (!accountRenderer.isMouseOver(mouseX, mouseY, accountListX, accountListY, accountListWidth, accountListHeight)) { return false; } float cardWidth = (accountListWidth - 5) / 2f; float cardHeight = 40; float cardGap = 5; List<AccountEntry> sortedAccounts = accountConfig.getSortedAccounts(); for (int i = 0; i < sortedAccounts.size(); i++) { int col = i % 2; int row = i / 2; float cardX = accountListX + col * (cardWidth + cardGap); float cardY = accountListY + row * (cardHeight + cardGap) - scrollOffset; if (cardY + cardHeight < accountListY || cardY > accountListY + accountListHeight) { continue; } float btnSize = 12; float buttonYPos = cardY + cardHeight - btnSize - 5; float pinButtonX = cardX + cardWidth - btnSize * 2 - 8; float deleteButtonX = cardX + cardWidth - btnSize - 5; if (accountRenderer.isMouseOver(mouseX, mouseY, pinButtonX, buttonYPos, btnSize, btnSize)) { AccountEntry entry = sortedAccounts.get(i); entry.togglePinned(); if (entry.isPinned()) { setActiveAccount(entry); } accountConfig.save(); return true; } if (accountRenderer.isMouseOver(mouseX, mouseY, deleteButtonX, buttonYPos, btnSize, btnSize)) { accountConfig.removeAccountByIndex(i); return true; } if (accountRenderer.isMouseOver(mouseX, mouseY, cardX, cardY, cardWidth, cardHeight)) { setActiveAccount(sortedAccounts.get(i)); return true; } } return false; } @Override public boolean mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { if (currentView != View.ALT_SCREEN) return false; float scaledMouseX = toFixedCoord(mouseX); float scaledMouseY = toFixedCoord(mouseY); int screenWidth = getFixedScaledWidth(); int screenHeight = getFixedScaledHeight(); float totalWidth = 100 + 5 + 300; float totalHeight = 100 + 5 + 58; float centerX = screenWidth / 2f; float centerY = screenHeight / 2f; float startX = centerX - totalWidth / 2f; float startY = centerY - totalHeight / 2f; float rightPanelX = startX + 100 + 5; float rightPanelY = startY; if (accountRenderer.isMouseOver(scaledMouseX, scaledMouseY, rightPanelX, rightPanelY, 300, 165)) { float cardHeight = 40; float cardGap = 5; float accountListHeight = 165 - 31; int rows = (int) Math.ceil(accountConfig.getSortedAccounts().size() / 2.0); float maxScroll = Math.max(0, rows * (cardHeight + cardGap) - accountListHeight); targetScrollOffset -= (float) verticalAmount * 25; targetScrollOffset = MathHelper.clamp(targetScrollOffset, 0, maxScroll); float scrollSpeed = 12f; float deltaTime = 0.016f; float scrollDiff = targetScrollOffset - scrollOffset; scrollOffset += scrollDiff * Math.min(1f, deltaTime * scrollSpeed); return true; } return super.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount); } @Override public boolean keyPressed(KeyInput input) { if (currentView == View.ALT_SCREEN) { if (nicknameFieldFocused) { int keyCode = input.key(); if (keyCode == 259) { if (!nicknameText.isEmpty()) { nicknameText = nicknameText.substring(0, nicknameText.length() - 1); } return true; } if (keyCode == 256) { nicknameFieldFocused = false; return true; } if (keyCode == 257 || keyCode == 335) { if (!nicknameText.isEmpty()) { addAccount(nicknameText); nicknameText = ""; } nicknameFieldFocused = false; return true; } } if (input.key() == 256) { currentView = View.MAIN_MENU; accountConfig.save(); return true; } } return super.keyPressed(input); } @Override public boolean charTyped(CharInput input) { if (currentView == View.ALT_SCREEN && nicknameFieldFocused) { int codepoint = input.codepoint(); if (Character.isLetterOrDigit(codepoint) || codepoint == '_') { if (nicknameText.length() < 16) { nicknameText += Character.toString(codepoint); } return true; } } return super.charTyped(input); } private void setActiveAccount(AccountEntry account) { accountConfig.setActiveAccount(account.getName(), account.getDate(), account.getSkin()); SessionChanger.changeUsername(account.getName()); } private void addAccount(String nickname) { LocalDateTime now = LocalDateTime.now(); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm"); String date = now.format(formatter); AccountEntry entry = new AccountEntry(nickname, date, null); accountConfig.addAccount(entry); setActiveAccount(entry); SessionChanger.changeUsername(nickname); } private String generateRandomNickname() { Random random = new Random(); StringBuilder username = new StringBuilder(); char[] vowels = {'a', 'e', 'i', 'o', 'u'}; char[] consonants = {'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z'}; String finalUsername = null; int attempts = 0; final int MAX_ATTEMPTS = 10; List<AccountEntry> existingAccounts = accountConfig.getAccounts(); do { username.setLength(0); int length = 6 + random.nextInt(5); boolean startWithVowel = random.nextBoolean(); for (int i = 0; i < length; i++) { if (i % 2 == 0) { username.append(startWithVowel ? vowels[random.nextInt(vowels.length)] : consonants[random.nextInt(consonants.length)]); } else { username.append(startWithVowel ? consonants[random.nextInt(consonants.length)] : vowels[random.nextInt(vowels.length)]); } } if (random.nextInt(100) < 30) { username.append(random.nextInt(100)); } String tempUsername = username.substring(0, 1).toUpperCase() + username.substring(1); attempts++; boolean exists = false; for (AccountEntry account : existingAccounts) { if (account.getName().equalsIgnoreCase(tempUsername)) { exists = true; break; } } if (!exists) { finalUsername = tempUsername; break; } } while (attempts < MAX_ATTEMPTS); if (finalUsername == null) { finalUsername = username.substring(0, 1).toUpperCase() + username.substring(1) + (System.currentTimeMillis() % 1000); } return finalUsername; } @Override public void renderBackground(DrawContext context, int mouseX, int mouseY, float delta) { drawBackground(); } @Override public boolean shouldCloseOnEsc() { return false; } @Override public boolean shouldPause() { return false; } private int withAlpha(int color, int alpha) { return (color & 0x00FFFFFF) | (MathHelper.clamp(alpha, 0, 255) << 24); } } }
Посмотреть вложение 327281
мое:Посмотреть вложение 327344
upd: добавил обводку
где найти именно етот фонтПожалуйста, авторизуйтесь для просмотра ссылки.и потом https://yougame.biz/threads/362210/
подумай логическигде найти именно етот фонт
в конце кода удали один } опечатка случайнокак фиксить?
20:50:07: Executing ':net.fabricmc.devlaunchinjector.Main.main()'…
> Configure project :
Fabric Loom: 1.15.3
> Task :compileJava FAILED
[Incubating] Problems report is available at: file:///C:/Users/Mykola/Downloads/Rich-Modern/build/reports/problems/problems-report.html
Deprecated Gradle features were used in this build, making it incompatible with Gradle 10.
You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.
For more on this, please refer toПожалуйста, авторизуйтесь для просмотра ссылки.in the Gradle documentation.
1 actionable task: 1 executed
C:\Users\Mykola\Downloads\Rich-Modern\src\main\java\rich\screens\menu\MainMenuScreen.java:820: error: class, interface, enum, or record expected
}
^
1 error
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':compileJava'.
> Compilation failed; see the compiler output below.
C:\Users\Mykola\Downloads\Rich-Modern\src\main\java\rich\screens\menu\MainMenuScreen.java:820: error: class, interface, enum, or record expected
}
^
1 error
* Try:
> Check your code and dependencies to fix the compilation error(s)
> Run with --scan to generate a Build Scan (powered by Develocity).
BUILD FAILED in 595ms
20:50:07: Execution finished ':net.fabricmc.devlaunchinjector.Main.main()'.
Прям похоже,возможно на 1.21.4 перенести?врод похоже хз
фонты думаю сами найдете
векса:код:package rich.screens.menu; import net.minecraft.client.gui.Click; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen; import net.minecraft.client.gui.screen.multiplayer.MultiplayerWarningScreen; import net.minecraft.client.gui.screen.option.OptionsScreen; import net.minecraft.client.gui.screen.world.SelectWorldScreen; import net.minecraft.client.input.KeyInput; import net.minecraft.client.input.CharInput; import net.minecraft.text.Text; import net.minecraft.util.Identifier; import net.minecraft.util.Util; import net.minecraft.util.math.MathHelper; import rich.Initialization; import rich.screens.account.AccountEntry; import rich.screens.account.AccountRenderer; import rich.util.config.impl.account.AccountConfig; import rich.util.render.Render2D; import rich.util.render.font.Fonts; import rich.util.session.SessionChanger; import rich.util.sounds.SoundManager; import antidaunleak.api.UserProfile; import java.awt.*; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.List; import java.util.Random; public class MainMenuScreen extends Screen { private static final Identifier BACKGROUND_TEXTURE = Identifier.of("rich", "textures/menu/backmenu.png"); private static final float FIXED_GUI_SCALE = 2.0f; private static final int PARTICLE_COUNT = 50; private static final float PARTICLE_FADE_THRESHOLD = 0.8f; private static class Particle { float x, y; float vx, vy; float size; float alpha; float lifetime; float maxLifetime; boolean isDead = false; Particle(float x, float y) { this.x = x; this.y = y; Random rand = new Random(); this.vx = (rand.nextFloat() - 0.5f) * 0.2f; this.vy = (rand.nextFloat() - 0.5f) * 0.2f; this.size = 0.5f + rand.nextFloat() * 1f; this.alpha = 0.2f + rand.nextFloat() * 0.3f; this.maxLifetime = 10f + rand.nextFloat() * 10f; this.lifetime = 0f; } void update(float delta, int width, int height) { lifetime += delta / 60f; if (lifetime > maxLifetime * PARTICLE_FADE_THRESHOLD) { float fadeProgress = (lifetime - maxLifetime * PARTICLE_FADE_THRESHOLD) / (maxLifetime * (1f - PARTICLE_FADE_THRESHOLD)); alpha = Math.max(0, alpha * (1f - fadeProgress)); } if (lifetime >= maxLifetime) { isDead = true; return; } x += vx * delta; y += vy * delta; if (x < -10 || x > width + 10 || y < -10 || y > height + 10) { isDead = true; } } } private final List<Particle> particles = new java.util.ArrayList<>(); private boolean particlesInitialized = false; private int lastWindowWidth = 0; private int lastWindowHeight = 0; private enum View { MAIN_MENU, ALT_SCREEN } private View currentView = View.MAIN_MENU; private long screenStartTime = 0L; private boolean initialized = false; private long lastRenderTime = 0L; private int hoveredButton = -1; private float[] buttonHoverProgress = new float[6]; private final AccountRenderer accountRenderer; private final AccountConfig accountConfig; private String nicknameText = ""; private boolean nicknameFieldFocused = false; private float scrollOffset = 0f; private float targetScrollOffset = 0f; public MainMenuScreen() { super(Text.literal("Main Menu")); for (int i = 0; i < 6; i++) { buttonHoverProgress[i] = 0f; } this.accountRenderer = new AccountRenderer(); this.accountConfig = AccountConfig.getInstance(); this.accountConfig.load(); } @Override protected void init() { initialized = false; particlesInitialized = false; } private int getFixedScaledWidth() { return (int) Math.ceil((double) client.getWindow().getFramebufferWidth() / FIXED_GUI_SCALE); } private int getFixedScaledHeight() { return (int) Math.ceil((double) client.getWindow().getFramebufferHeight() / FIXED_GUI_SCALE); } private float toFixedCoord(double coord) { float currentScale = (float) client.getWindow().getScaleFactor(); return (float) (coord * currentScale / FIXED_GUI_SCALE); } private void initParticles(int width, int height) { if (particlesInitialized) return; Random rand = new Random(); for (int i = 0; i < PARTICLE_COUNT; i++) { particles.add(new Particle(rand.nextFloat() * width, rand.nextFloat() * height)); } particlesInitialized = true; } private void drawBackground() { int screenWidth = getFixedScaledWidth(); int screenHeight = getFixedScaledHeight(); Render2D.rect(0, 0, screenWidth, screenHeight, new Color(12, 15, 18).getRGB()); initParticles(screenWidth, screenHeight); for (Particle p : particles) { if (!p.isDead && p.alpha > 0.01f) { int alpha = (int) (p.alpha * 255); Render2D.rect(p.x, p.y, p.size, p.size, new Color(255, 255, 255, alpha).getRGB()); } } } @Override public void render(DrawContext context, int mouseX, int mouseY, float delta) { long currentTime = Util.getMeasuringTimeMs(); if (!initialized) { screenStartTime = currentTime; lastRenderTime = currentTime; initialized = true; } float deltaTime = Math.min(delta, 0.05f); lastRenderTime = currentTime; int fixedWidth = getFixedScaledWidth(); int fixedHeight = getFixedScaledHeight(); if (lastWindowWidth != fixedWidth || lastWindowHeight != fixedHeight) { particles.clear(); particlesInitialized = false; lastWindowWidth = fixedWidth; lastWindowHeight = fixedHeight; } for (Particle p : particles) { p.update(deltaTime * 60f, fixedWidth, fixedHeight); } particles.removeIf(p -> p.isDead); Random rand = new Random(); while (particles.size() < PARTICLE_COUNT) { particles.add(new Particle(rand.nextFloat() * fixedWidth, rand.nextFloat() * fixedHeight)); } float scaledMouseX = toFixedCoord(mouseX); float scaledMouseY = toFixedCoord(mouseY); updateButtonAnimations(deltaTime, scaledMouseX, scaledMouseY, fixedWidth, fixedHeight); Render2D.beginOverlay(); drawBackground(); if (currentView == View.MAIN_MENU) { renderMainMenu(fixedWidth, fixedHeight, scaledMouseX, scaledMouseY); } else { renderAltScreen(fixedWidth, fixedHeight, scaledMouseX, scaledMouseY, currentTime); } Render2D.endOverlay(); } private void renderMainMenu(int screenWidth, int screenHeight, float mouseX, float mouseY) { float centerX = screenWidth / 2f; float centerY = screenHeight / 2f; String username = "user"; float avatarSize = 20; float avatarX = 8; float avatarY = 10; Fonts.INTER_MEDIUM.draw("Logged in as", avatarX + avatarSize + 5, avatarY, 7f, new Color(150, 150, 150).getRGB()); Fonts.INTER_MEDIUM.draw(username, avatarX + avatarSize + 5, avatarY + 9, 8f, new Color(255, 255, 255).getRGB()); Render2D.rect(avatarX, avatarY, avatarSize, avatarSize, new Color(40, 45, 55).getRGB(), avatarSize / 2f); Identifier userAvatar = Identifier.of("rich", "user.png"); int[] avatarColors = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}; float[] avatarRadii = {avatarSize / 2f, avatarSize / 2f, avatarSize / 2f, avatarSize / 2f}; Initialization.getInstance().getManager().getRenderCore().getTexturePipeline() .drawTexture(userAvatar, avatarX, avatarY, avatarSize, avatarSize, 0, 0, 1, 1, avatarColors, avatarRadii, 1f); float logoSize = 35; float logoY = centerY - 90; Identifier logoTexture = Identifier.of("rich", "images/logo.png"); int[] logoColors = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}; float[] logoRadii = {0, 0, 0, 0}; Initialization.getInstance().getManager().getRenderCore().getTexturePipeline() .drawTexture(logoTexture, centerX - logoSize / 2f, logoY, logoSize, logoSize, 0, 0, 1, 1, logoColors, logoRadii, 1f); String timeOfDay = getTimeOfDay(); String greeting = "Good " + timeOfDay + ", "; String usernameColored = username; float greetingWidth = Fonts.INTER_SEMIBOLD.getWidth(greeting, 14f); float usernameWidth = Fonts.INTER_SEMIBOLD.getWidth(usernameColored, 14f); float totalGreetingWidth = greetingWidth + usernameWidth; float greetingStartX = centerX - totalGreetingWidth / 2f; float greetingY = centerY - 38; Fonts.INTER_SEMIBOLD.draw(greeting, greetingStartX, greetingY, 14f, new Color(255, 255, 255).getRGB()); Fonts.INTER_SEMIBOLD.draw(usernameColored, greetingStartX + greetingWidth, greetingY, 14f, new Color(100, 180, 255).getRGB()); String welcomeText = "Welcome to "; String clientName = "WexSide. The best client."; String restText = ""; float welcomeWidth = Fonts.INTER_MEDIUM.getWidth(welcomeText, 9f); float clientWidth = Fonts.INTER_MEDIUM.getWidth(clientName, 9f); float restWidth = Fonts.INTER_MEDIUM.getWidth(restText, 9f); float totalWidth = welcomeWidth + clientWidth + restWidth; float startX = centerX - totalWidth / 2f; float textY = centerY - 20; Fonts.INTER_MEDIUM.draw(welcomeText, startX, textY, 9f, new Color(180, 180, 180).getRGB()); Fonts.INTER_SEMIBOLD.draw(clientName, startX + welcomeWidth, textY, 9f, new Color(90, 22, 134).getRGB()); Fonts.INTER_MEDIUM.draw(restText, startX + welcomeWidth + clientWidth, textY, 9f, new Color(180, 180, 180).getRGB()); float buttonWidth = 220; float buttonHeight = 30; float buttonSpacing = 7; float buttonStartY = centerY + 3; drawButton(centerX - buttonWidth / 2f, buttonStartY, buttonWidth, buttonHeight, "Singleplayer", 0, mouseX, mouseY, new Color(30, 35, 45), false); drawButton(centerX - buttonWidth / 2f, buttonStartY + buttonHeight + buttonSpacing, buttonWidth, buttonHeight, "Multiplayer", 1, mouseX, mouseY, new Color(30, 35, 45), false); float swapAccountsY = buttonStartY + (buttonHeight + buttonSpacing) * 2 + 5; drawButton(centerX - buttonWidth / 2f, swapAccountsY, buttonWidth, buttonHeight, "Swap Accounts", 2, mouseX, mouseY, new Color(90, 22, 134), true); float bottomY = swapAccountsY + buttonHeight + 5; float bottomButtonWidth = 65; float bottomButtonHeight = 20; float bottomSpacing = 10; float totalBottomWidth = bottomButtonWidth * 3 + bottomSpacing * 2; float bottomStartX = centerX - totalBottomWidth / 2f; drawSmallButton(bottomStartX, bottomY, bottomButtonWidth, bottomButtonHeight, "Options", 3, mouseX, mouseY); drawSmallButton(bottomStartX + bottomButtonWidth + bottomSpacing, bottomY, bottomButtonWidth, bottomButtonHeight, "Proxies", 4, mouseX, mouseY); drawSmallButton(bottomStartX + (bottomButtonWidth + bottomSpacing) * 2, bottomY, bottomButtonWidth, bottomButtonHeight, "Exit", 5, mouseX, mouseY); String footerText = "By logging into your account, you agree to all of our policies,"; String policyLinks = "including our Privacy Policy and Terms of Service"; Fonts.INTER_MEDIUM.drawCentered(footerText, centerX, screenHeight - 17, 6.5f, new Color(100, 100, 100).getRGB()); Fonts.INTER_MEDIUM.drawCentered(policyLinks, centerX, screenHeight - 8, 6.5f, new Color(100, 100, 100).getRGB()); } private String getTimeOfDay() { int hour = java.time.LocalTime.now().getHour(); if (hour >= 5 && hour < 12) return "morning"; if (hour >= 12 && hour < 17) return "afternoon"; if (hour >= 17 && hour < 21) return "evening"; return "night"; } private void drawButton(float x, float y, float width, float height, String text, int index, float mouseX, float mouseY, Color baseColor, boolean isPurple) { boolean hovered = isMouseOver(mouseX, mouseY, x, y, width, height); float hoverProgress = buttonHoverProgress[index]; Color bgColor = baseColor; if (isPurple) { int brightness = (int) (hoverProgress * 20); bgColor = new Color( Math.min(255, baseColor.getRed() + brightness), Math.min(255, baseColor.getGreen() + brightness), Math.min(255, baseColor.getBlue() + brightness) ); } else { int brightness = (int) (hoverProgress * 15); bgColor = new Color( Math.min(255, baseColor.getRed() + brightness), Math.min(255, baseColor.getGreen() + brightness), Math.min(255, baseColor.getBlue() + brightness) ); } Render2D.rect(x, y, width, height, bgColor.getRGB(), 8); if (!isPurple) { Render2D.outline(x, y, width, height, 1f, new Color(50, 55, 65, 80).getRGB(), 8); } if (hoverProgress > 0.01f) { int borderAlpha = (int) (hoverProgress * 100); Color borderColor = isPurple ? new Color(138, 43, 226, borderAlpha) : new Color(100, 110, 130, borderAlpha); Render2D.outline(x, y, width, height, 1f, borderColor.getRGB(), 8); } float fontSize = 9f; float textHeight = Fonts.INTER_MEDIUM.getHeight(fontSize); Color textColor = isPurple ? new Color(255, 255, 255) : new Color(160, 160, 160); Fonts.INTER_MEDIUM.drawCentered(text, x + width / 2f, y + (height - textHeight) / 2f, fontSize, textColor.getRGB()); } private void drawSmallButton(float x, float y, float width, float height, String text, int index, float mouseX, float mouseY) { float hoverProgress = buttonHoverProgress[index]; int baseAlpha = 150; int hoverAlpha = (int) (baseAlpha + hoverProgress * 50); float fontSize = 8f; float textHeight = Fonts.INTER_MEDIUM.getHeight(fontSize); Fonts.INTER_MEDIUM.drawCentered(text, x + width / 2f, y + (height - textHeight) / 2f, fontSize, new Color(180, 180, 180, hoverAlpha).getRGB()); } private boolean isMouseOver(float mouseX, float mouseY, float x, float y, float width, float height) { return mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height; } private void updateButtonAnimations(float deltaTime, float mouseX, float mouseY, int screenWidth, int screenHeight) { float centerX = screenWidth / 2f; float centerY = screenHeight / 2f; float lerpSpeed = 1f - (float) Math.pow(0.001f, deltaTime); if (currentView == View.MAIN_MENU) { float buttonWidth = 220; float buttonHeight = 30; float buttonSpacing = 7; float buttonStartY = centerY + 3; for (int i = 0; i < 2; i++) { float y = buttonStartY + i * (buttonHeight + buttonSpacing); boolean hovered = isMouseOver(mouseX, mouseY, centerX - buttonWidth / 2f, y, buttonWidth, buttonHeight); float target = hovered ? 1f : 0f; buttonHoverProgress[i] = MathHelper.lerp(lerpSpeed, buttonHoverProgress[i], target); } float swapAccountsY = buttonStartY + (buttonHeight + buttonSpacing) * 2 + 5; boolean swapHovered = isMouseOver(mouseX, mouseY, centerX - buttonWidth / 2f, swapAccountsY, buttonWidth, buttonHeight); buttonHoverProgress[2] = MathHelper.lerp(lerpSpeed, buttonHoverProgress[2], swapHovered ? 1f : 0f); float bottomY = swapAccountsY + buttonHeight + 5; float bottomButtonWidth = 65; float bottomButtonHeight = 20; float bottomSpacing = 10; float totalBottomWidth = bottomButtonWidth * 3 + bottomSpacing * 2; float bottomStartX = centerX - totalBottomWidth / 2f; for (int i = 0; i < 3; i++) { float x = bottomStartX + i * (bottomButtonWidth + bottomSpacing); boolean hovered = isMouseOver(mouseX, mouseY, x, bottomY, bottomButtonWidth, bottomButtonHeight); float target = hovered ? 1f : 0f; buttonHoverProgress[i + 3] = MathHelper.lerp(lerpSpeed, buttonHoverProgress[i + 3], target); } } else { for (int i = 0; i < 6; i++) { buttonHoverProgress[i] = MathHelper.lerp(lerpSpeed, buttonHoverProgress[i], 0f); } } } private void renderAltScreen(int screenWidth, int screenHeight, float mouseX, float mouseY, long currentTime) { float totalWidth = 405; float totalHeight = 163; float centerX = screenWidth / 2f; float centerY = screenHeight / 2f; float startX = centerX - totalWidth / 2f; float startY = centerY - totalHeight / 2f; float leftPanelX = startX; float leftPanelTopY = startY; accountRenderer.renderLeftPanelTop(leftPanelX, leftPanelTopY, 100, 100, 1f, nicknameText, nicknameFieldFocused, mouseX, mouseY, currentTime); float leftPanelBottomY = startY + 100 + 5; accountRenderer.renderLeftPanelBottom(leftPanelX, leftPanelBottomY, 100, 58, 1f, accountConfig.getActiveAccountName(), accountConfig.getActiveAccountDate(), accountConfig.getActiveAccountSkin()); float rightPanelX = startX + 100 + 5; float rightPanelY = startY; List<AccountEntry> sortedAccounts = accountConfig.getSortedAccounts(); accountRenderer.renderRightPanel(rightPanelX, rightPanelY, 300, 165, 1f, sortedAccounts, scrollOffset, mouseX, mouseY, 1f, (int) FIXED_GUI_SCALE); } @Override public boolean mouseClicked(Click click, boolean doubled) { float scaledMouseX = toFixedCoord(click.x()); float scaledMouseY = toFixedCoord(click.y()); if (currentView == View.MAIN_MENU) { if (click.button() == 0) { int fixedWidth = getFixedScaledWidth(); int fixedHeight = getFixedScaledHeight(); float centerX = fixedWidth / 2f; float centerY = fixedHeight / 2f; float buttonWidth = 220; float buttonHeight = 30; float buttonSpacing = 7; float buttonStartY = centerY + 3; for (int i = 0; i < 2; i++) { float y = buttonStartY + i * (buttonHeight + buttonSpacing); if (isMouseOver(scaledMouseX, scaledMouseY, centerX - buttonWidth / 2f, y, buttonWidth, buttonHeight)) { handleMainMenuButtonClick(i); return true; } } float swapAccountsY = buttonStartY + (buttonHeight + buttonSpacing) * 2 + 5; if (isMouseOver(scaledMouseX, scaledMouseY, centerX - buttonWidth / 2f, swapAccountsY, buttonWidth, buttonHeight)) { handleMainMenuButtonClick(2); return true; } float bottomY = swapAccountsY + buttonHeight + 5; float bottomButtonWidth = 65; float bottomButtonHeight = 20; float bottomSpacing = 10; float totalBottomWidth = bottomButtonWidth * 3 + bottomSpacing * 2; float bottomStartX = centerX - totalBottomWidth / 2f; for (int i = 0; i < 3; i++) { float x = bottomStartX + i * (bottomButtonWidth + bottomSpacing); if (isMouseOver(scaledMouseX, scaledMouseY, x, bottomY, bottomButtonWidth, bottomButtonHeight)) { handleMainMenuButtonClick(i + 3); return true; } } } } else if (currentView == View.ALT_SCREEN) { return handleAltScreenClick(scaledMouseX, scaledMouseY, click); } return super.mouseClicked(click, doubled); } private void handleMainMenuButtonClick(int index) { switch (index) { case 0 -> this.client.setScreen(new SelectWorldScreen(this)); case 1 -> { Screen screen = this.client.options.skipMultiplayerWarning ? new MultiplayerScreen(this) : new MultiplayerWarningScreen(this); this.client.setScreen(screen); } case 2 -> currentView = View.ALT_SCREEN; case 3 -> this.client.setScreen(new OptionsScreen(this, this.client.options)); case 4 -> {} case 5 -> this.client.scheduleStop(); } } private boolean handleAltScreenClick(float mouseX, float mouseY, Click click) { int screenWidth = getFixedScaledWidth(); int screenHeight = getFixedScaledHeight(); float totalWidth = 100 + 5 + 300; float totalHeight = 100 + 5 + 58; float centerX = screenWidth / 2f; float centerY = screenHeight / 2f; float startX = centerX - totalWidth / 2f; float startY = centerY - totalHeight / 2f; float leftPanelX = startX; float leftPanelTopY = startY; float fieldX = leftPanelX + 5; float fieldY = leftPanelTopY + 38; float fieldHeight = 14; float addButtonSize = 14; float buttonGap = 3; float fieldWidth = 100 - 10 - addButtonSize - buttonGap; if (accountRenderer.isMouseOver(mouseX, mouseY, fieldX, fieldY, fieldWidth, fieldHeight)) { nicknameFieldFocused = true; return true; } else { nicknameFieldFocused = false; } float addButtonX = fieldX + fieldWidth + buttonGap; float addButtonY = fieldY; if (accountRenderer.isMouseOver(mouseX, mouseY, addButtonX, addButtonY, addButtonSize, addButtonSize)) { if (!nicknameText.isEmpty()) { addAccount(nicknameText); nicknameText = ""; } return true; } float buttonWidth = 100 - 10; float buttonHeight = 16; float randomButtonX = leftPanelX + 5; float randomButtonY = fieldY + fieldHeight + 6; if (accountRenderer.isMouseOver(mouseX, mouseY, randomButtonX, randomButtonY, buttonWidth, buttonHeight)) { String randomNick = generateRandomNickname(); addAccount(randomNick); nicknameText = ""; return true; } float clearButtonX = leftPanelX + 5; float clearButtonY = randomButtonY + buttonHeight + 5; if (accountRenderer.isMouseOver(mouseX, mouseY, clearButtonX, clearButtonY, buttonWidth, buttonHeight)) { accountConfig.clearAllAccounts(); targetScrollOffset = 0f; scrollOffset = 0f; return true; } float rightPanelX = startX + 100 + 5; float rightPanelY = startY; float accountListX = rightPanelX + 5; float accountListY = rightPanelY + 26; float accountListWidth = 300 - 10; float accountListHeight = 165 - 31; if (!accountRenderer.isMouseOver(mouseX, mouseY, accountListX, accountListY, accountListWidth, accountListHeight)) { return false; } float cardWidth = (accountListWidth - 5) / 2f; float cardHeight = 40; float cardGap = 5; List<AccountEntry> sortedAccounts = accountConfig.getSortedAccounts(); for (int i = 0; i < sortedAccounts.size(); i++) { int col = i % 2; int row = i / 2; float cardX = accountListX + col * (cardWidth + cardGap); float cardY = accountListY + row * (cardHeight + cardGap) - scrollOffset; if (cardY + cardHeight < accountListY || cardY > accountListY + accountListHeight) { continue; } float btnSize = 12; float buttonYPos = cardY + cardHeight - btnSize - 5; float pinButtonX = cardX + cardWidth - btnSize * 2 - 8; float deleteButtonX = cardX + cardWidth - btnSize - 5; if (accountRenderer.isMouseOver(mouseX, mouseY, pinButtonX, buttonYPos, btnSize, btnSize)) { AccountEntry entry = sortedAccounts.get(i); entry.togglePinned(); if (entry.isPinned()) { setActiveAccount(entry); } accountConfig.save(); return true; } if (accountRenderer.isMouseOver(mouseX, mouseY, deleteButtonX, buttonYPos, btnSize, btnSize)) { accountConfig.removeAccountByIndex(i); return true; } if (accountRenderer.isMouseOver(mouseX, mouseY, cardX, cardY, cardWidth, cardHeight)) { setActiveAccount(sortedAccounts.get(i)); return true; } } return false; } @Override public boolean mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { if (currentView != View.ALT_SCREEN) return false; float scaledMouseX = toFixedCoord(mouseX); float scaledMouseY = toFixedCoord(mouseY); int screenWidth = getFixedScaledWidth(); int screenHeight = getFixedScaledHeight(); float totalWidth = 100 + 5 + 300; float totalHeight = 100 + 5 + 58; float centerX = screenWidth / 2f; float centerY = screenHeight / 2f; float startX = centerX - totalWidth / 2f; float startY = centerY - totalHeight / 2f; float rightPanelX = startX + 100 + 5; float rightPanelY = startY; if (accountRenderer.isMouseOver(scaledMouseX, scaledMouseY, rightPanelX, rightPanelY, 300, 165)) { float cardHeight = 40; float cardGap = 5; float accountListHeight = 165 - 31; int rows = (int) Math.ceil(accountConfig.getSortedAccounts().size() / 2.0); float maxScroll = Math.max(0, rows * (cardHeight + cardGap) - accountListHeight); targetScrollOffset -= (float) verticalAmount * 25; targetScrollOffset = MathHelper.clamp(targetScrollOffset, 0, maxScroll); float scrollSpeed = 12f; float deltaTime = 0.016f; float scrollDiff = targetScrollOffset - scrollOffset; scrollOffset += scrollDiff * Math.min(1f, deltaTime * scrollSpeed); return true; } return super.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount); } @Override public boolean keyPressed(KeyInput input) { if (currentView == View.ALT_SCREEN) { if (nicknameFieldFocused) { int keyCode = input.key(); if (keyCode == 259) { if (!nicknameText.isEmpty()) { nicknameText = nicknameText.substring(0, nicknameText.length() - 1); } return true; } if (keyCode == 256) { nicknameFieldFocused = false; return true; } if (keyCode == 257 || keyCode == 335) { if (!nicknameText.isEmpty()) { addAccount(nicknameText); nicknameText = ""; } nicknameFieldFocused = false; return true; } } if (input.key() == 256) { currentView = View.MAIN_MENU; accountConfig.save(); return true; } } return super.keyPressed(input); } @Override public boolean charTyped(CharInput input) { if (currentView == View.ALT_SCREEN && nicknameFieldFocused) { int codepoint = input.codepoint(); if (Character.isLetterOrDigit(codepoint) || codepoint == '_') { if (nicknameText.length() < 16) { nicknameText += Character.toString(codepoint); } return true; } } return super.charTyped(input); } private void setActiveAccount(AccountEntry account) { accountConfig.setActiveAccount(account.getName(), account.getDate(), account.getSkin()); SessionChanger.changeUsername(account.getName()); } private void addAccount(String nickname) { LocalDateTime now = LocalDateTime.now(); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm"); String date = now.format(formatter); AccountEntry entry = new AccountEntry(nickname, date, null); accountConfig.addAccount(entry); setActiveAccount(entry); SessionChanger.changeUsername(nickname); } private String generateRandomNickname() { Random random = new Random(); StringBuilder username = new StringBuilder(); char[] vowels = {'a', 'e', 'i', 'o', 'u'}; char[] consonants = {'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z'}; String finalUsername = null; int attempts = 0; final int MAX_ATTEMPTS = 10; List<AccountEntry> existingAccounts = accountConfig.getAccounts(); do { username.setLength(0); int length = 6 + random.nextInt(5); boolean startWithVowel = random.nextBoolean(); for (int i = 0; i < length; i++) { if (i % 2 == 0) { username.append(startWithVowel ? vowels[random.nextInt(vowels.length)] : consonants[random.nextInt(consonants.length)]); } else { username.append(startWithVowel ? consonants[random.nextInt(consonants.length)] : vowels[random.nextInt(vowels.length)]); } } if (random.nextInt(100) < 30) { username.append(random.nextInt(100)); } String tempUsername = username.substring(0, 1).toUpperCase() + username.substring(1); attempts++; boolean exists = false; for (AccountEntry account : existingAccounts) { if (account.getName().equalsIgnoreCase(tempUsername)) { exists = true; break; } } if (!exists) { finalUsername = tempUsername; break; } } while (attempts < MAX_ATTEMPTS); if (finalUsername == null) { finalUsername = username.substring(0, 1).toUpperCase() + username.substring(1) + (System.currentTimeMillis() % 1000); } return finalUsername; } @Override public void renderBackground(DrawContext context, int mouseX, int mouseY, float delta) { drawBackground(); } @Override public boolean shouldCloseOnEsc() { return false; } @Override public boolean shouldPause() { return false; } private int withAlpha(int color, int alpha) { return (color & 0x00FFFFFF) | (MathHelper.clamp(alpha, 0, 255) << 24); } } }
Посмотреть вложение 327281
мое:Посмотреть вложение 327344
upd: добавил обводку
да легкоПрям похоже,возможно на 1.21.4 перенести?
нахуя ты все делаешь чтоб сливатЬ, сделай для себя что-то крутое. Это глупо, каждый день тебя вижу xDврод похоже хз
фонты думаю сами найдете
векса:код:package rich.screens.menu; import net.minecraft.client.gui.Click; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen; import net.minecraft.client.gui.screen.multiplayer.MultiplayerWarningScreen; import net.minecraft.client.gui.screen.option.OptionsScreen; import net.minecraft.client.gui.screen.world.SelectWorldScreen; import net.minecraft.client.input.KeyInput; import net.minecraft.client.input.CharInput; import net.minecraft.text.Text; import net.minecraft.util.Identifier; import net.minecraft.util.Util; import net.minecraft.util.math.MathHelper; import rich.Initialization; import rich.screens.account.AccountEntry; import rich.screens.account.AccountRenderer; import rich.util.config.impl.account.AccountConfig; import rich.util.render.Render2D; import rich.util.render.font.Fonts; import rich.util.session.SessionChanger; import rich.util.sounds.SoundManager; import antidaunleak.api.UserProfile; import java.awt.*; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.List; import java.util.Random; public class MainMenuScreen extends Screen { private static final Identifier BACKGROUND_TEXTURE = Identifier.of("rich", "textures/menu/backmenu.png"); private static final float FIXED_GUI_SCALE = 2.0f; private static final int PARTICLE_COUNT = 50; private static final float PARTICLE_FADE_THRESHOLD = 0.8f; private static class Particle { float x, y; float vx, vy; float size; float alpha; float lifetime; float maxLifetime; boolean isDead = false; Particle(float x, float y) { this.x = x; this.y = y; Random rand = new Random(); this.vx = (rand.nextFloat() - 0.5f) * 0.2f; this.vy = (rand.nextFloat() - 0.5f) * 0.2f; this.size = 0.5f + rand.nextFloat() * 1f; this.alpha = 0.2f + rand.nextFloat() * 0.3f; this.maxLifetime = 10f + rand.nextFloat() * 10f; this.lifetime = 0f; } void update(float delta, int width, int height) { lifetime += delta / 60f; if (lifetime > maxLifetime * PARTICLE_FADE_THRESHOLD) { float fadeProgress = (lifetime - maxLifetime * PARTICLE_FADE_THRESHOLD) / (maxLifetime * (1f - PARTICLE_FADE_THRESHOLD)); alpha = Math.max(0, alpha * (1f - fadeProgress)); } if (lifetime >= maxLifetime) { isDead = true; return; } x += vx * delta; y += vy * delta; if (x < -10 || x > width + 10 || y < -10 || y > height + 10) { isDead = true; } } } private final List<Particle> particles = new java.util.ArrayList<>(); private boolean particlesInitialized = false; private int lastWindowWidth = 0; private int lastWindowHeight = 0; private enum View { MAIN_MENU, ALT_SCREEN } private View currentView = View.MAIN_MENU; private long screenStartTime = 0L; private boolean initialized = false; private long lastRenderTime = 0L; private int hoveredButton = -1; private float[] buttonHoverProgress = new float[6]; private final AccountRenderer accountRenderer; private final AccountConfig accountConfig; private String nicknameText = ""; private boolean nicknameFieldFocused = false; private float scrollOffset = 0f; private float targetScrollOffset = 0f; public MainMenuScreen() { super(Text.literal("Main Menu")); for (int i = 0; i < 6; i++) { buttonHoverProgress[i] = 0f; } this.accountRenderer = new AccountRenderer(); this.accountConfig = AccountConfig.getInstance(); this.accountConfig.load(); } @Override protected void init() { initialized = false; particlesInitialized = false; } private int getFixedScaledWidth() { return (int) Math.ceil((double) client.getWindow().getFramebufferWidth() / FIXED_GUI_SCALE); } private int getFixedScaledHeight() { return (int) Math.ceil((double) client.getWindow().getFramebufferHeight() / FIXED_GUI_SCALE); } private float toFixedCoord(double coord) { float currentScale = (float) client.getWindow().getScaleFactor(); return (float) (coord * currentScale / FIXED_GUI_SCALE); } private void initParticles(int width, int height) { if (particlesInitialized) return; Random rand = new Random(); for (int i = 0; i < PARTICLE_COUNT; i++) { particles.add(new Particle(rand.nextFloat() * width, rand.nextFloat() * height)); } particlesInitialized = true; } private void drawBackground() { int screenWidth = getFixedScaledWidth(); int screenHeight = getFixedScaledHeight(); Render2D.rect(0, 0, screenWidth, screenHeight, new Color(12, 15, 18).getRGB()); initParticles(screenWidth, screenHeight); for (Particle p : particles) { if (!p.isDead && p.alpha > 0.01f) { int alpha = (int) (p.alpha * 255); Render2D.rect(p.x, p.y, p.size, p.size, new Color(255, 255, 255, alpha).getRGB()); } } } @Override public void render(DrawContext context, int mouseX, int mouseY, float delta) { long currentTime = Util.getMeasuringTimeMs(); if (!initialized) { screenStartTime = currentTime; lastRenderTime = currentTime; initialized = true; } float deltaTime = Math.min(delta, 0.05f); lastRenderTime = currentTime; int fixedWidth = getFixedScaledWidth(); int fixedHeight = getFixedScaledHeight(); if (lastWindowWidth != fixedWidth || lastWindowHeight != fixedHeight) { particles.clear(); particlesInitialized = false; lastWindowWidth = fixedWidth; lastWindowHeight = fixedHeight; } for (Particle p : particles) { p.update(deltaTime * 60f, fixedWidth, fixedHeight); } particles.removeIf(p -> p.isDead); Random rand = new Random(); while (particles.size() < PARTICLE_COUNT) { particles.add(new Particle(rand.nextFloat() * fixedWidth, rand.nextFloat() * fixedHeight)); } float scaledMouseX = toFixedCoord(mouseX); float scaledMouseY = toFixedCoord(mouseY); updateButtonAnimations(deltaTime, scaledMouseX, scaledMouseY, fixedWidth, fixedHeight); Render2D.beginOverlay(); drawBackground(); if (currentView == View.MAIN_MENU) { renderMainMenu(fixedWidth, fixedHeight, scaledMouseX, scaledMouseY); } else { renderAltScreen(fixedWidth, fixedHeight, scaledMouseX, scaledMouseY, currentTime); } Render2D.endOverlay(); } private void renderMainMenu(int screenWidth, int screenHeight, float mouseX, float mouseY) { float centerX = screenWidth / 2f; float centerY = screenHeight / 2f; String username = "user"; float avatarSize = 20; float avatarX = 8; float avatarY = 10; Fonts.INTER_MEDIUM.draw("Logged in as", avatarX + avatarSize + 5, avatarY, 7f, new Color(150, 150, 150).getRGB()); Fonts.INTER_MEDIUM.draw(username, avatarX + avatarSize + 5, avatarY + 9, 8f, new Color(255, 255, 255).getRGB()); Render2D.rect(avatarX, avatarY, avatarSize, avatarSize, new Color(40, 45, 55).getRGB(), avatarSize / 2f); Identifier userAvatar = Identifier.of("rich", "user.png"); int[] avatarColors = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}; float[] avatarRadii = {avatarSize / 2f, avatarSize / 2f, avatarSize / 2f, avatarSize / 2f}; Initialization.getInstance().getManager().getRenderCore().getTexturePipeline() .drawTexture(userAvatar, avatarX, avatarY, avatarSize, avatarSize, 0, 0, 1, 1, avatarColors, avatarRadii, 1f); float logoSize = 35; float logoY = centerY - 90; Identifier logoTexture = Identifier.of("rich", "images/logo.png"); int[] logoColors = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}; float[] logoRadii = {0, 0, 0, 0}; Initialization.getInstance().getManager().getRenderCore().getTexturePipeline() .drawTexture(logoTexture, centerX - logoSize / 2f, logoY, logoSize, logoSize, 0, 0, 1, 1, logoColors, logoRadii, 1f); String timeOfDay = getTimeOfDay(); String greeting = "Good " + timeOfDay + ", "; String usernameColored = username; float greetingWidth = Fonts.INTER_SEMIBOLD.getWidth(greeting, 14f); float usernameWidth = Fonts.INTER_SEMIBOLD.getWidth(usernameColored, 14f); float totalGreetingWidth = greetingWidth + usernameWidth; float greetingStartX = centerX - totalGreetingWidth / 2f; float greetingY = centerY - 38; Fonts.INTER_SEMIBOLD.draw(greeting, greetingStartX, greetingY, 14f, new Color(255, 255, 255).getRGB()); Fonts.INTER_SEMIBOLD.draw(usernameColored, greetingStartX + greetingWidth, greetingY, 14f, new Color(100, 180, 255).getRGB()); String welcomeText = "Welcome to "; String clientName = "WexSide. The best client."; String restText = ""; float welcomeWidth = Fonts.INTER_MEDIUM.getWidth(welcomeText, 9f); float clientWidth = Fonts.INTER_MEDIUM.getWidth(clientName, 9f); float restWidth = Fonts.INTER_MEDIUM.getWidth(restText, 9f); float totalWidth = welcomeWidth + clientWidth + restWidth; float startX = centerX - totalWidth / 2f; float textY = centerY - 20; Fonts.INTER_MEDIUM.draw(welcomeText, startX, textY, 9f, new Color(180, 180, 180).getRGB()); Fonts.INTER_SEMIBOLD.draw(clientName, startX + welcomeWidth, textY, 9f, new Color(90, 22, 134).getRGB()); Fonts.INTER_MEDIUM.draw(restText, startX + welcomeWidth + clientWidth, textY, 9f, new Color(180, 180, 180).getRGB()); float buttonWidth = 220; float buttonHeight = 30; float buttonSpacing = 7; float buttonStartY = centerY + 3; drawButton(centerX - buttonWidth / 2f, buttonStartY, buttonWidth, buttonHeight, "Singleplayer", 0, mouseX, mouseY, new Color(30, 35, 45), false); drawButton(centerX - buttonWidth / 2f, buttonStartY + buttonHeight + buttonSpacing, buttonWidth, buttonHeight, "Multiplayer", 1, mouseX, mouseY, new Color(30, 35, 45), false); float swapAccountsY = buttonStartY + (buttonHeight + buttonSpacing) * 2 + 5; drawButton(centerX - buttonWidth / 2f, swapAccountsY, buttonWidth, buttonHeight, "Swap Accounts", 2, mouseX, mouseY, new Color(90, 22, 134), true); float bottomY = swapAccountsY + buttonHeight + 5; float bottomButtonWidth = 65; float bottomButtonHeight = 20; float bottomSpacing = 10; float totalBottomWidth = bottomButtonWidth * 3 + bottomSpacing * 2; float bottomStartX = centerX - totalBottomWidth / 2f; drawSmallButton(bottomStartX, bottomY, bottomButtonWidth, bottomButtonHeight, "Options", 3, mouseX, mouseY); drawSmallButton(bottomStartX + bottomButtonWidth + bottomSpacing, bottomY, bottomButtonWidth, bottomButtonHeight, "Proxies", 4, mouseX, mouseY); drawSmallButton(bottomStartX + (bottomButtonWidth + bottomSpacing) * 2, bottomY, bottomButtonWidth, bottomButtonHeight, "Exit", 5, mouseX, mouseY); String footerText = "By logging into your account, you agree to all of our policies,"; String policyLinks = "including our Privacy Policy and Terms of Service"; Fonts.INTER_MEDIUM.drawCentered(footerText, centerX, screenHeight - 17, 6.5f, new Color(100, 100, 100).getRGB()); Fonts.INTER_MEDIUM.drawCentered(policyLinks, centerX, screenHeight - 8, 6.5f, new Color(100, 100, 100).getRGB()); } private String getTimeOfDay() { int hour = java.time.LocalTime.now().getHour(); if (hour >= 5 && hour < 12) return "morning"; if (hour >= 12 && hour < 17) return "afternoon"; if (hour >= 17 && hour < 21) return "evening"; return "night"; } private void drawButton(float x, float y, float width, float height, String text, int index, float mouseX, float mouseY, Color baseColor, boolean isPurple) { boolean hovered = isMouseOver(mouseX, mouseY, x, y, width, height); float hoverProgress = buttonHoverProgress[index]; Color bgColor = baseColor; if (isPurple) { int brightness = (int) (hoverProgress * 20); bgColor = new Color( Math.min(255, baseColor.getRed() + brightness), Math.min(255, baseColor.getGreen() + brightness), Math.min(255, baseColor.getBlue() + brightness) ); } else { int brightness = (int) (hoverProgress * 15); bgColor = new Color( Math.min(255, baseColor.getRed() + brightness), Math.min(255, baseColor.getGreen() + brightness), Math.min(255, baseColor.getBlue() + brightness) ); } Render2D.rect(x, y, width, height, bgColor.getRGB(), 8); if (!isPurple) { Render2D.outline(x, y, width, height, 1f, new Color(50, 55, 65, 80).getRGB(), 8); } if (hoverProgress > 0.01f) { int borderAlpha = (int) (hoverProgress * 100); Color borderColor = isPurple ? new Color(138, 43, 226, borderAlpha) : new Color(100, 110, 130, borderAlpha); Render2D.outline(x, y, width, height, 1f, borderColor.getRGB(), 8); } float fontSize = 9f; float textHeight = Fonts.INTER_MEDIUM.getHeight(fontSize); Color textColor = isPurple ? new Color(255, 255, 255) : new Color(160, 160, 160); Fonts.INTER_MEDIUM.drawCentered(text, x + width / 2f, y + (height - textHeight) / 2f, fontSize, textColor.getRGB()); } private void drawSmallButton(float x, float y, float width, float height, String text, int index, float mouseX, float mouseY) { float hoverProgress = buttonHoverProgress[index]; int baseAlpha = 150; int hoverAlpha = (int) (baseAlpha + hoverProgress * 50); float fontSize = 8f; float textHeight = Fonts.INTER_MEDIUM.getHeight(fontSize); Fonts.INTER_MEDIUM.drawCentered(text, x + width / 2f, y + (height - textHeight) / 2f, fontSize, new Color(180, 180, 180, hoverAlpha).getRGB()); } private boolean isMouseOver(float mouseX, float mouseY, float x, float y, float width, float height) { return mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height; } private void updateButtonAnimations(float deltaTime, float mouseX, float mouseY, int screenWidth, int screenHeight) { float centerX = screenWidth / 2f; float centerY = screenHeight / 2f; float lerpSpeed = 1f - (float) Math.pow(0.001f, deltaTime); if (currentView == View.MAIN_MENU) { float buttonWidth = 220; float buttonHeight = 30; float buttonSpacing = 7; float buttonStartY = centerY + 3; for (int i = 0; i < 2; i++) { float y = buttonStartY + i * (buttonHeight + buttonSpacing); boolean hovered = isMouseOver(mouseX, mouseY, centerX - buttonWidth / 2f, y, buttonWidth, buttonHeight); float target = hovered ? 1f : 0f; buttonHoverProgress[i] = MathHelper.lerp(lerpSpeed, buttonHoverProgress[i], target); } float swapAccountsY = buttonStartY + (buttonHeight + buttonSpacing) * 2 + 5; boolean swapHovered = isMouseOver(mouseX, mouseY, centerX - buttonWidth / 2f, swapAccountsY, buttonWidth, buttonHeight); buttonHoverProgress[2] = MathHelper.lerp(lerpSpeed, buttonHoverProgress[2], swapHovered ? 1f : 0f); float bottomY = swapAccountsY + buttonHeight + 5; float bottomButtonWidth = 65; float bottomButtonHeight = 20; float bottomSpacing = 10; float totalBottomWidth = bottomButtonWidth * 3 + bottomSpacing * 2; float bottomStartX = centerX - totalBottomWidth / 2f; for (int i = 0; i < 3; i++) { float x = bottomStartX + i * (bottomButtonWidth + bottomSpacing); boolean hovered = isMouseOver(mouseX, mouseY, x, bottomY, bottomButtonWidth, bottomButtonHeight); float target = hovered ? 1f : 0f; buttonHoverProgress[i + 3] = MathHelper.lerp(lerpSpeed, buttonHoverProgress[i + 3], target); } } else { for (int i = 0; i < 6; i++) { buttonHoverProgress[i] = MathHelper.lerp(lerpSpeed, buttonHoverProgress[i], 0f); } } } private void renderAltScreen(int screenWidth, int screenHeight, float mouseX, float mouseY, long currentTime) { float totalWidth = 405; float totalHeight = 163; float centerX = screenWidth / 2f; float centerY = screenHeight / 2f; float startX = centerX - totalWidth / 2f; float startY = centerY - totalHeight / 2f; float leftPanelX = startX; float leftPanelTopY = startY; accountRenderer.renderLeftPanelTop(leftPanelX, leftPanelTopY, 100, 100, 1f, nicknameText, nicknameFieldFocused, mouseX, mouseY, currentTime); float leftPanelBottomY = startY + 100 + 5; accountRenderer.renderLeftPanelBottom(leftPanelX, leftPanelBottomY, 100, 58, 1f, accountConfig.getActiveAccountName(), accountConfig.getActiveAccountDate(), accountConfig.getActiveAccountSkin()); float rightPanelX = startX + 100 + 5; float rightPanelY = startY; List<AccountEntry> sortedAccounts = accountConfig.getSortedAccounts(); accountRenderer.renderRightPanel(rightPanelX, rightPanelY, 300, 165, 1f, sortedAccounts, scrollOffset, mouseX, mouseY, 1f, (int) FIXED_GUI_SCALE); } @Override public boolean mouseClicked(Click click, boolean doubled) { float scaledMouseX = toFixedCoord(click.x()); float scaledMouseY = toFixedCoord(click.y()); if (currentView == View.MAIN_MENU) { if (click.button() == 0) { int fixedWidth = getFixedScaledWidth(); int fixedHeight = getFixedScaledHeight(); float centerX = fixedWidth / 2f; float centerY = fixedHeight / 2f; float buttonWidth = 220; float buttonHeight = 30; float buttonSpacing = 7; float buttonStartY = centerY + 3; for (int i = 0; i < 2; i++) { float y = buttonStartY + i * (buttonHeight + buttonSpacing); if (isMouseOver(scaledMouseX, scaledMouseY, centerX - buttonWidth / 2f, y, buttonWidth, buttonHeight)) { handleMainMenuButtonClick(i); return true; } } float swapAccountsY = buttonStartY + (buttonHeight + buttonSpacing) * 2 + 5; if (isMouseOver(scaledMouseX, scaledMouseY, centerX - buttonWidth / 2f, swapAccountsY, buttonWidth, buttonHeight)) { handleMainMenuButtonClick(2); return true; } float bottomY = swapAccountsY + buttonHeight + 5; float bottomButtonWidth = 65; float bottomButtonHeight = 20; float bottomSpacing = 10; float totalBottomWidth = bottomButtonWidth * 3 + bottomSpacing * 2; float bottomStartX = centerX - totalBottomWidth / 2f; for (int i = 0; i < 3; i++) { float x = bottomStartX + i * (bottomButtonWidth + bottomSpacing); if (isMouseOver(scaledMouseX, scaledMouseY, x, bottomY, bottomButtonWidth, bottomButtonHeight)) { handleMainMenuButtonClick(i + 3); return true; } } } } else if (currentView == View.ALT_SCREEN) { return handleAltScreenClick(scaledMouseX, scaledMouseY, click); } return super.mouseClicked(click, doubled); } private void handleMainMenuButtonClick(int index) { switch (index) { case 0 -> this.client.setScreen(new SelectWorldScreen(this)); case 1 -> { Screen screen = this.client.options.skipMultiplayerWarning ? new MultiplayerScreen(this) : new MultiplayerWarningScreen(this); this.client.setScreen(screen); } case 2 -> currentView = View.ALT_SCREEN; case 3 -> this.client.setScreen(new OptionsScreen(this, this.client.options)); case 4 -> {} case 5 -> this.client.scheduleStop(); } } private boolean handleAltScreenClick(float mouseX, float mouseY, Click click) { int screenWidth = getFixedScaledWidth(); int screenHeight = getFixedScaledHeight(); float totalWidth = 100 + 5 + 300; float totalHeight = 100 + 5 + 58; float centerX = screenWidth / 2f; float centerY = screenHeight / 2f; float startX = centerX - totalWidth / 2f; float startY = centerY - totalHeight / 2f; float leftPanelX = startX; float leftPanelTopY = startY; float fieldX = leftPanelX + 5; float fieldY = leftPanelTopY + 38; float fieldHeight = 14; float addButtonSize = 14; float buttonGap = 3; float fieldWidth = 100 - 10 - addButtonSize - buttonGap; if (accountRenderer.isMouseOver(mouseX, mouseY, fieldX, fieldY, fieldWidth, fieldHeight)) { nicknameFieldFocused = true; return true; } else { nicknameFieldFocused = false; } float addButtonX = fieldX + fieldWidth + buttonGap; float addButtonY = fieldY; if (accountRenderer.isMouseOver(mouseX, mouseY, addButtonX, addButtonY, addButtonSize, addButtonSize)) { if (!nicknameText.isEmpty()) { addAccount(nicknameText); nicknameText = ""; } return true; } float buttonWidth = 100 - 10; float buttonHeight = 16; float randomButtonX = leftPanelX + 5; float randomButtonY = fieldY + fieldHeight + 6; if (accountRenderer.isMouseOver(mouseX, mouseY, randomButtonX, randomButtonY, buttonWidth, buttonHeight)) { String randomNick = generateRandomNickname(); addAccount(randomNick); nicknameText = ""; return true; } float clearButtonX = leftPanelX + 5; float clearButtonY = randomButtonY + buttonHeight + 5; if (accountRenderer.isMouseOver(mouseX, mouseY, clearButtonX, clearButtonY, buttonWidth, buttonHeight)) { accountConfig.clearAllAccounts(); targetScrollOffset = 0f; scrollOffset = 0f; return true; } float rightPanelX = startX + 100 + 5; float rightPanelY = startY; float accountListX = rightPanelX + 5; float accountListY = rightPanelY + 26; float accountListWidth = 300 - 10; float accountListHeight = 165 - 31; if (!accountRenderer.isMouseOver(mouseX, mouseY, accountListX, accountListY, accountListWidth, accountListHeight)) { return false; } float cardWidth = (accountListWidth - 5) / 2f; float cardHeight = 40; float cardGap = 5; List<AccountEntry> sortedAccounts = accountConfig.getSortedAccounts(); for (int i = 0; i < sortedAccounts.size(); i++) { int col = i % 2; int row = i / 2; float cardX = accountListX + col * (cardWidth + cardGap); float cardY = accountListY + row * (cardHeight + cardGap) - scrollOffset; if (cardY + cardHeight < accountListY || cardY > accountListY + accountListHeight) { continue; } float btnSize = 12; float buttonYPos = cardY + cardHeight - btnSize - 5; float pinButtonX = cardX + cardWidth - btnSize * 2 - 8; float deleteButtonX = cardX + cardWidth - btnSize - 5; if (accountRenderer.isMouseOver(mouseX, mouseY, pinButtonX, buttonYPos, btnSize, btnSize)) { AccountEntry entry = sortedAccounts.get(i); entry.togglePinned(); if (entry.isPinned()) { setActiveAccount(entry); } accountConfig.save(); return true; } if (accountRenderer.isMouseOver(mouseX, mouseY, deleteButtonX, buttonYPos, btnSize, btnSize)) { accountConfig.removeAccountByIndex(i); return true; } if (accountRenderer.isMouseOver(mouseX, mouseY, cardX, cardY, cardWidth, cardHeight)) { setActiveAccount(sortedAccounts.get(i)); return true; } } return false; } @Override public boolean mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { if (currentView != View.ALT_SCREEN) return false; float scaledMouseX = toFixedCoord(mouseX); float scaledMouseY = toFixedCoord(mouseY); int screenWidth = getFixedScaledWidth(); int screenHeight = getFixedScaledHeight(); float totalWidth = 100 + 5 + 300; float totalHeight = 100 + 5 + 58; float centerX = screenWidth / 2f; float centerY = screenHeight / 2f; float startX = centerX - totalWidth / 2f; float startY = centerY - totalHeight / 2f; float rightPanelX = startX + 100 + 5; float rightPanelY = startY; if (accountRenderer.isMouseOver(scaledMouseX, scaledMouseY, rightPanelX, rightPanelY, 300, 165)) { float cardHeight = 40; float cardGap = 5; float accountListHeight = 165 - 31; int rows = (int) Math.ceil(accountConfig.getSortedAccounts().size() / 2.0); float maxScroll = Math.max(0, rows * (cardHeight + cardGap) - accountListHeight); targetScrollOffset -= (float) verticalAmount * 25; targetScrollOffset = MathHelper.clamp(targetScrollOffset, 0, maxScroll); float scrollSpeed = 12f; float deltaTime = 0.016f; float scrollDiff = targetScrollOffset - scrollOffset; scrollOffset += scrollDiff * Math.min(1f, deltaTime * scrollSpeed); return true; } return super.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount); } @Override public boolean keyPressed(KeyInput input) { if (currentView == View.ALT_SCREEN) { if (nicknameFieldFocused) { int keyCode = input.key(); if (keyCode == 259) { if (!nicknameText.isEmpty()) { nicknameText = nicknameText.substring(0, nicknameText.length() - 1); } return true; } if (keyCode == 256) { nicknameFieldFocused = false; return true; } if (keyCode == 257 || keyCode == 335) { if (!nicknameText.isEmpty()) { addAccount(nicknameText); nicknameText = ""; } nicknameFieldFocused = false; return true; } } if (input.key() == 256) { currentView = View.MAIN_MENU; accountConfig.save(); return true; } } return super.keyPressed(input); } @Override public boolean charTyped(CharInput input) { if (currentView == View.ALT_SCREEN && nicknameFieldFocused) { int codepoint = input.codepoint(); if (Character.isLetterOrDigit(codepoint) || codepoint == '_') { if (nicknameText.length() < 16) { nicknameText += Character.toString(codepoint); } return true; } } return super.charTyped(input); } private void setActiveAccount(AccountEntry account) { accountConfig.setActiveAccount(account.getName(), account.getDate(), account.getSkin()); SessionChanger.changeUsername(account.getName()); } private void addAccount(String nickname) { LocalDateTime now = LocalDateTime.now(); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm"); String date = now.format(formatter); AccountEntry entry = new AccountEntry(nickname, date, null); accountConfig.addAccount(entry); setActiveAccount(entry); SessionChanger.changeUsername(nickname); } private String generateRandomNickname() { Random random = new Random(); StringBuilder username = new StringBuilder(); char[] vowels = {'a', 'e', 'i', 'o', 'u'}; char[] consonants = {'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z'}; String finalUsername = null; int attempts = 0; final int MAX_ATTEMPTS = 10; List<AccountEntry> existingAccounts = accountConfig.getAccounts(); do { username.setLength(0); int length = 6 + random.nextInt(5); boolean startWithVowel = random.nextBoolean(); for (int i = 0; i < length; i++) { if (i % 2 == 0) { username.append(startWithVowel ? vowels[random.nextInt(vowels.length)] : consonants[random.nextInt(consonants.length)]); } else { username.append(startWithVowel ? consonants[random.nextInt(consonants.length)] : vowels[random.nextInt(vowels.length)]); } } if (random.nextInt(100) < 30) { username.append(random.nextInt(100)); } String tempUsername = username.substring(0, 1).toUpperCase() + username.substring(1); attempts++; boolean exists = false; for (AccountEntry account : existingAccounts) { if (account.getName().equalsIgnoreCase(tempUsername)) { exists = true; break; } } if (!exists) { finalUsername = tempUsername; break; } } while (attempts < MAX_ATTEMPTS); if (finalUsername == null) { finalUsername = username.substring(0, 1).toUpperCase() + username.substring(1) + (System.currentTimeMillis() % 1000); } return finalUsername; } @Override public void renderBackground(DrawContext context, int mouseX, int mouseY, float delta) { drawBackground(); } @Override public boolean shouldCloseOnEsc() { return false; } @Override public boolean shouldPause() { return false; } private int withAlpha(int color, int alpha) { return (color & 0x00FFFFFF) | (MathHelper.clamp(alpha, 0, 255) << 24); } } }
Посмотреть вложение 327281
мое:Посмотреть вложение 327344
upd: добавил обводку
нубез слов братблин ребята только начал пастить куда мне logo.png кидать? расскажите ток без хейта плиз
хз я так то это 1 раз слил когда людям понравилосьнахуя ты все делаешь чтоб сливатЬ, сделай для себя что-то крутое. Это глупо, каждый день тебя вижу xD
нубез слов брат
брат код почитай плзблин ребята только начал пастить куда мне logo.png кидать? расскажите ток без хейта плиз
мыколкакак фиксить?
20:50:07: Executing ':net.fabricmc.devlaunchinjector.Main.main()'…
> Configure project :
Fabric Loom: 1.15.3
> Task :compileJava FAILED
[Incubating] Problems report is available at: file:///C:/Users/Mykola/Downloads/Rich-Modern/build/reports/problems/problems-report.html
Deprecated Gradle features were used in this build, making it incompatible with Gradle 10.
You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.
For more on this, please refer toПожалуйста, авторизуйтесь для просмотра ссылки.in the Gradle documentation.
1 actionable task: 1 executed
C:\Users\Mykola\Downloads\Rich-Modern\src\main\java\rich\screens\menu\MainMenuScreen.java:820: error: class, interface, enum, or record expected
}
^
1 error
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':compileJava'.
> Compilation failed; see the compiler output below.
C:\Users\Mykola\Downloads\Rich-Modern\src\main\java\rich\screens\menu\MainMenuScreen.java:820: error: class, interface, enum, or record expected
}
^
1 error
* Try:
> Check your code and dependencies to fix the compilation error(s)
> Run with --scan to generate a Build Scan (powered by Develocity).
BUILD FAILED in 595ms
20:50:07: Execution finished ':net.fabricmc.devlaunchinjector.Main.main()'.
images/logo.pngблин ребята только начал пастить куда мне logo.png кидать? расскажите ток без хейта плиз
package rich.screens.menu;где фонт этот взять
17:03:25: Executing ':net.fabricmc.devlaunchinjector.Main.main()'…package rich.screens.menu;
import net.minecraft.client.gui.Click;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen;
import net.minecraft.client.gui.screen.multiplayer.MultiplayerWarningScreen;
import net.minecraft.client.gui.screen.option.OptionsScreen;
import net.minecraft.client.gui.screen.world.SelectWorldScreen;
import net.minecraft.client.input.KeyInput;
import net.minecraft.client.input.CharInput;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import net.minecraft.util.Util;
import net.minecraft.util.math.MathHelper;
import rich.Initialization;
import rich.screens.account.AccountEntry;
import rich.screens.account.AccountRenderer;
import rich.util.config.impl.account.AccountConfig;
import rich.util.render.Render2D;
import rich.util.render.font.Fonts;
import rich.util.session.SessionChanger;
import rich.util.sounds.SoundManager;
import antidaunleak.api.UserProfile;
import java.awt.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Random;
public class MainMenuScreen extends Screen {
private static final Identifier BACKGROUND_TEXTURE = Identifier.of("rich", "textures/menu/backmenu.png");
private static final float FIXED_GUI_SCALE = 2.0f;
private static final int PARTICLE_COUNT = 50;
private static final float PARTICLE_FADE_THRESHOLD = 0.8f;
private static class Particle {
float x, y;
float vx, vy;
float size;
float alpha;
float lifetime;
float maxLifetime;
boolean isDead = false;
Particle(float x, float y) {
this.x = x;
this.y = y;
Random rand = new Random();
this.vx = (rand.nextFloat() - 0.5f) * 0.2f;
this.vy = (rand.nextFloat() - 0.5f) * 0.2f;
this.size = 0.5f + rand.nextFloat() * 1f;
this.alpha = 0.2f + rand.nextFloat() * 0.3f;
this.maxLifetime = 10f + rand.nextFloat() * 10f;
this.lifetime = 0f;
}
void update(float delta, int width, int height) {
lifetime += delta / 60f;
if (lifetime > maxLifetime * PARTICLE_FADE_THRESHOLD) {
float fadeProgress = (lifetime - maxLifetime * PARTICLE_FADE_THRESHOLD) / (maxLifetime * (1f - PARTICLE_FADE_THRESHOLD));
alpha = Math.max(0, alpha * (1f - fadeProgress));
}
if (lifetime >= maxLifetime) {
isDead = true;
return;
}
x += vx * delta;
y += vy * delta;
if (x < -10 || x > width + 10 || y < -10 || y > height + 10) {
isDead = true;
}
}
}
private final List<Particle> particles = new java.util.ArrayList<>();
private boolean particlesInitialized = false;
private int lastWindowWidth = 0;
private int lastWindowHeight = 0;
private enum View { MAIN_MENU, ALT_SCREEN }
private View currentView = View.MAIN_MENU;
private long screenStartTime = 0L;
private boolean initialized = false;
private long lastRenderTime = 0L;
private int hoveredButton = -1;
private float[] buttonHoverProgress = new float[6];
private final AccountRenderer accountRenderer;
private final AccountConfig accountConfig;
private String nicknameText = "";
private boolean nicknameFieldFocused = false;
private float scrollOffset = 0f;
private float targetScrollOffset = 0f;
public MainMenuScreen() {
super(Text.literal("Main Menu"));
for (int i = 0; i < 6; i++) {
buttonHoverProgress = 0f;
}
this.accountRenderer = new AccountRenderer();
this.accountConfig = AccountConfig.getInstance();
this.accountConfig.load();
}
@override
protected void init() {
initialized = false;
particlesInitialized = false;
}
private int getFixedScaledWidth() {
return (int) Math.ceil((double) client.getWindow().getFramebufferWidth() / FIXED_GUI_SCALE);
}
private int getFixedScaledHeight() {
return (int) Math.ceil((double) client.getWindow().getFramebufferHeight() / FIXED_GUI_SCALE);
}
private float toFixedCoord(double coord) {
float currentScale = (float) client.getWindow().getScaleFactor();
return (float) (coord * currentScale / FIXED_GUI_SCALE);
}
private void initParticles(int width, int height) {
if (particlesInitialized) return;
Random rand = new Random();
for (int i = 0; i < PARTICLE_COUNT; i++) {
particles.add(new Particle(rand.nextFloat() * width, rand.nextFloat() * height));
}
particlesInitialized = true;
}
private void drawBackground() {
int screenWidth = getFixedScaledWidth();
int screenHeight = getFixedScaledHeight();
Render2D.rect(0, 0, screenWidth, screenHeight, new Color(12, 15, 18).getRGB());
initParticles(screenWidth, screenHeight);
for (Particle p : particles) {
if (!p.isDead && p.alpha > 0.01f) {
int alpha = (int) (p.alpha * 255);
Render2D.rect(p.x, p.y, p.size, p.size, new Color(255, 255, 255, alpha).getRGB());
}
}
}
@override
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
long currentTime = Util.getMeasuringTimeMs();
if (!initialized) {
screenStartTime = currentTime;
lastRenderTime = currentTime;
initialized = true;
}
float deltaTime = Math.min(delta, 0.05f);
lastRenderTime = currentTime;
int fixedWidth = getFixedScaledWidth();
int fixedHeight = getFixedScaledHeight();
if (lastWindowWidth != fixedWidth || lastWindowHeight != fixedHeight) {
particles.clear();
particlesInitialized = false;
lastWindowWidth = fixedWidth;
lastWindowHeight = fixedHeight;
}
for (Particle p : particles) {
p.update(deltaTime * 60f, fixedWidth, fixedHeight);
}
particles.removeIf(p -> p.isDead);
Random rand = new Random();
while (particles.size() < PARTICLE_COUNT) {
particles.add(new Particle(rand.nextFloat() * fixedWidth, rand.nextFloat() * fixedHeight));
}
float scaledMouseX = toFixedCoord(mouseX);
float scaledMouseY = toFixedCoord(mouseY);
updateButtonAnimations(deltaTime, scaledMouseX, scaledMouseY, fixedWidth, fixedHeight);
Render2D.beginOverlay();
drawBackground();
if (currentView == View.MAIN_MENU) {
renderMainMenu(fixedWidth, fixedHeight, scaledMouseX, scaledMouseY);
} else {
renderAltScreen(fixedWidth, fixedHeight, scaledMouseX, scaledMouseY, currentTime);
}
Render2D.endOverlay();
}
private void renderMainMenu(int screenWidth, int screenHeight, float mouseX, float mouseY) {
float centerX = screenWidth / 2f;
float centerY = screenHeight / 2f;
String username = "user";
float avatarSize = 20;
float avatarX = 8;
float avatarY = 10;
Fonts.INTER.draw("Logged in as", avatarX + avatarSize + 5, avatarY, 7f, new Color(150, 150, 150).getRGB());
Fonts.INTER.draw(username, avatarX + avatarSize + 5, avatarY + 9, 8f, new Color(255, 255, 255).getRGB());
Render2D.rect(avatarX, avatarY, avatarSize, avatarSize, new Color(40, 45, 55).getRGB(), avatarSize / 2f);
Identifier userAvatar = Identifier.of("rich", "steve.png");
int[] avatarColors = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF};
float[] avatarRadii = {avatarSize / 2f, avatarSize / 2f, avatarSize / 2f, avatarSize / 2f};
Initialization.getInstance().getManager().getRenderCore().getTexturePipeline()
.drawTexture(userAvatar, avatarX, avatarY, avatarSize, avatarSize,
0, 0, 1, 1, avatarColors, avatarRadii, 1f);
float logoSize = 35;
float logoY = centerY - 90;
Identifier logoTexture = Identifier.of("rich", "images/logo.png");
int[] logoColors = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF};
float[] logoRadii = {0, 0, 0, 0};
Initialization.getInstance().getManager().getRenderCore().getTexturePipeline()
.drawTexture(logoTexture, centerX - logoSize / 2f, logoY, logoSize, logoSize,
0, 0, 1, 1, logoColors, logoRadii, 1f);
String timeOfDay = getTimeOfDay();
String greeting = "Good " + timeOfDay + ", ";
String usernameColored = username;
float greetingWidth = Fonts.BOLD.getWidth(greeting, 14f);
float usernameWidth = Fonts.BOLD.getWidth(usernameColored, 14f);
float totalGreetingWidth = greetingWidth + usernameWidth;
float greetingStartX = centerX - totalGreetingWidth / 2f;
float greetingY = centerY - 38;
Fonts.BOLD.draw(greeting, greetingStartX, greetingY, 14f, new Color(255, 255, 255).getRGB());
Fonts.BOLD.draw(usernameColored, greetingStartX + greetingWidth, greetingY, 14f, new Color(100, 180, 255).getRGB());
String welcomeText = "Welcome to ";
String clientName = "RedDlc. The best client.";
String restText = "";
float welcomeWidth = Fonts.REGULARNEW.getWidth(welcomeText, 9f);
float clientWidth = Fonts.REGULARNEW.getWidth(clientName, 9f);
float restWidth = Fonts.REGULARNEW.getWidth(restText, 9f);
float totalWidth = welcomeWidth + clientWidth + restWidth;
float startX = centerX - totalWidth / 2f;
float textY = centerY - 20;
Fonts.REGULARNEW.draw(welcomeText, startX, textY, 9f, new Color(180, 180, 180).getRGB());
Fonts.REGULARNEW.draw(clientName, startX + welcomeWidth, textY, 9f, new Color(90, 22, 134).getRGB());
Fonts.REGULARNEW.draw(restText, startX + welcomeWidth + clientWidth, textY, 9f, new Color(180, 180, 180).getRGB());
float buttonWidth = 220;
float buttonHeight = 30;
float buttonSpacing = 7;
float buttonStartY = centerY + 3;
drawButton(centerX - buttonWidth / 2f, buttonStartY, buttonWidth, buttonHeight,
"Singleplayer", 0, mouseX, mouseY, new Color(30, 35, 45), false);
drawButton(centerX - buttonWidth / 2f, buttonStartY + buttonHeight + buttonSpacing, buttonWidth, buttonHeight,
"Multiplayer", 1, mouseX, mouseY, new Color(30, 35, 45), false);
float swapAccountsY = buttonStartY + (buttonHeight + buttonSpacing) * 2 + 5;
drawButton(centerX - buttonWidth / 2f, swapAccountsY, buttonWidth, buttonHeight,
"Swap Accounts", 2, mouseX, mouseY, new Color(90, 22, 134), true);
float bottomY = swapAccountsY + buttonHeight + 5;
float bottomButtonWidth = 65;
float bottomButtonHeight = 20;
float bottomSpacing = 10;
float totalBottomWidth = bottomButtonWidth * 3 + bottomSpacing * 2;
float bottomStartX = centerX - totalBottomWidth / 2f;
drawSmallButton(bottomStartX, bottomY, bottomButtonWidth, bottomButtonHeight,
"Options", 3, mouseX, mouseY);
drawSmallButton(bottomStartX + bottomButtonWidth + bottomSpacing, bottomY, bottomButtonWidth, bottomButtonHeight,
"Proxies", 4, mouseX, mouseY);
drawSmallButton(bottomStartX + (bottomButtonWidth + bottomSpacing) * 2, bottomY, bottomButtonWidth, bottomButtonHeight,
"Exit", 5, mouseX, mouseY);
String footerText = "By logging into your account, you agree to all of our policies,";
String policyLinks = "including our Privacy Policy and Terms of Service";
Fonts.SYSTEM.drawCentered(footerText, centerX, screenHeight - 17, 6.5f, new Color(100, 100, 100).getRGB());
Fonts.SYSTEM.drawCentered(policyLinks, centerX, screenHeight - 8, 6.5f, new Color(100, 100, 100).getRGB());
}
private String getTimeOfDay() {
int hour = java.time.LocalTime.now().getHour();
if (hour >= 5 && hour < 12) return "morning";
if (hour >= 12 && hour < 17) return "afternoon";
if (hour >= 17 && hour < 21) return "evening";
return "night";
}
private void drawButton(float x, float y, float width, float height, String text, int index,
float mouseX, float mouseY, Color baseColor, boolean isPurple) {
boolean hovered = isMouseOver(mouseX, mouseY, x, y, width, height);
float hoverProgress = buttonHoverProgress[index];
Color bgColor = baseColor;
if (isPurple) {
int brightness = (int) (hoverProgress * 20);
bgColor = new Color(
Math.min(255, baseColor.getRed() + brightness),
Math.min(255, baseColor.getGreen() + brightness),
Math.min(255, baseColor.getBlue() + brightness)
);
} else {
int brightness = (int) (hoverProgress * 15);
bgColor = new Color(
Math.min(255, baseColor.getRed() + brightness),
Math.min(255, baseColor.getGreen() + brightness),
Math.min(255, baseColor.getBlue() + brightness)
);
}
Render2D.rect(x, y, width, height, bgColor.getRGB(), 8);
if (!isPurple) {
Render2D.outline(x, y, width, height, 1f, new Color(50, 55, 65, 80).getRGB(), 8);
}
if (hoverProgress > 0.01f) {
int borderAlpha = (int) (hoverProgress * 100);
Color borderColor = isPurple
? new Color(138, 43, 226, borderAlpha)
: new Color(100, 110, 130, borderAlpha);
Render2D.outline(x, y, width, height, 1f, borderColor.getRGB(), 8);
}
float fontSize = 9f;
// ВЫБИРАЕМ ШРИФТ В ЗАВИСИМОСТИ ОТ КНОПКИ
rich.util.render.font.Font fontToUse;
// Индексы: 0 - Singleplayer, 1 - Multiplayer, 2 - Swap Accounts
if (index == 0 || index == 1) {
// Для Singleplayer и Multiplayer используем BOLD
fontToUse = Fonts.BOLD;
} else if (index == 2) {
// Для Swap Accounts используем REGULARNEW
fontToUse = Fonts.REGULARNEW;
} else {
// Для остальных кнопок (Options, Proxies, Exit) оставляем INTER
fontToUse = Fonts.INTER;
}
Color textColor;
if (isPurple) {
textColor = new Color(255, 255, 255);
} else {
textColor = new Color(220, 220, 220);
}
float textHeight = fontToUse.getHeight(fontSize);
float textWidth = fontToUse.getWidth(text, fontSize);
float textX = x + (width - textWidth) / 2f;
float textY = y + (height - textHeight) / 2f;
fontToUse.draw(text, textX, textY, fontSize, textColor.getRGB());
}
private void drawSmallButton(float x, float y, float width, float height, String text, int index,
float mouseX, float mouseY) {
float hoverProgress = buttonHoverProgress[index];
int baseAlpha = 220;
int hoverAlpha = (int) (baseAlpha + hoverProgress * 35);
float fontSize = 8f;
// Для маленьких кнопок используем INTER
float textHeight = Fonts.INTER.getHeight(fontSize);
float textWidth = Fonts.INTER.getWidth(text, fontSize);
float textX = x + (width - textWidth) / 2f;
float textY = y + (height - textHeight) / 2f;
Fonts.INTER.draw(text, textX, textY, fontSize, new Color(255, 255, 255, hoverAlpha).getRGB());
}
private boolean isMouseOver(float mouseX, float mouseY, float x, float y, float width, float height) {
return mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height;
}
private void updateButtonAnimations(float deltaTime, float mouseX, float mouseY, int screenWidth, int screenHeight) {
float centerX = screenWidth / 2f;
float centerY = screenHeight / 2f;
float lerpSpeed = 1f - (float) Math.pow(0.001f, deltaTime);
if (currentView == View.MAIN_MENU) {
float buttonWidth = 220;
float buttonHeight = 30;
float buttonSpacing = 7;
float buttonStartY = centerY + 3;
for (int i = 0; i < 2; i++) {
float y = buttonStartY + i * (buttonHeight + buttonSpacing);
boolean hovered = isMouseOver(mouseX, mouseY, centerX - buttonWidth / 2f, y, buttonWidth, buttonHeight);
float target = hovered ? 1f : 0f;
buttonHoverProgress = MathHelper.lerp(lerpSpeed, buttonHoverProgress, target);
}
float swapAccountsY = buttonStartY + (buttonHeight + buttonSpacing) * 2 + 5;
boolean swapHovered = isMouseOver(mouseX, mouseY, centerX - buttonWidth / 2f, swapAccountsY, buttonWidth, buttonHeight);
buttonHoverProgress[2] = MathHelper.lerp(lerpSpeed, buttonHoverProgress[2], swapHovered ? 1f : 0f);
float bottomY = swapAccountsY + buttonHeight + 5;
float bottomButtonWidth = 65;
float bottomButtonHeight = 20;
float bottomSpacing = 10;
float totalBottomWidth = bottomButtonWidth * 3 + bottomSpacing * 2;
float bottomStartX = centerX - totalBottomWidth / 2f;
for (int i = 0; i < 3; i++) {
float x = bottomStartX + i * (bottomButtonWidth + bottomSpacing);
boolean hovered = isMouseOver(mouseX, mouseY, x, bottomY, bottomButtonWidth, bottomButtonHeight);
float target = hovered ? 1f : 0f;
buttonHoverProgress[i + 3] = MathHelper.lerp(lerpSpeed, buttonHoverProgress[i + 3], target);
}
} else {
for (int i = 0; i < 6; i++) {
buttonHoverProgress = MathHelper.lerp(lerpSpeed, buttonHoverProgress, 0f);
}
}
}
private void renderAltScreen(int screenWidth, int screenHeight, float mouseX, float mouseY, long currentTime) {
float totalWidth = 405;
float totalHeight = 163;
float centerX = screenWidth / 2f;
float centerY = screenHeight / 2f;
float startX = centerX - totalWidth / 2f;
float startY = centerY - totalHeight / 2f;
float leftPanelX = startX;
float leftPanelTopY = startY;
accountRenderer.renderLeftPanelTop(leftPanelX, leftPanelTopY, 100, 100,
1f, nicknameText, nicknameFieldFocused, mouseX, mouseY, currentTime);
float leftPanelBottomY = startY + 100 + 5;
accountRenderer.renderLeftPanelBottom(leftPanelX, leftPanelBottomY, 100, 58,
1f, accountConfig.getActiveAccountName(), accountConfig.getActiveAccountDate(), accountConfig.getActiveAccountSkin());
float rightPanelX = startX + 100 + 5;
float rightPanelY = startY;
List<AccountEntry> sortedAccounts = accountConfig.getSortedAccounts();
accountRenderer.renderRightPanel(rightPanelX, rightPanelY, 300, 165,
1f, sortedAccounts, scrollOffset, mouseX, mouseY, 1f, (int) FIXED_GUI_SCALE);
}
@override
public boolean mouseClicked(Click click, boolean doubled) {
float scaledMouseX = toFixedCoord(click.x());
float scaledMouseY = toFixedCoord(click.y());
if (currentView == View.MAIN_MENU) {
if (click.button() == 0) {
int fixedWidth = getFixedScaledWidth();
int fixedHeight = getFixedScaledHeight();
float centerX = fixedWidth / 2f;
float centerY = fixedHeight / 2f;
float buttonWidth = 220;
float buttonHeight = 30;
float buttonSpacing = 7;
float buttonStartY = centerY + 3;
for (int i = 0; i < 2; i++) {
float y = buttonStartY + i * (buttonHeight + buttonSpacing);
if (isMouseOver(scaledMouseX, scaledMouseY, centerX - buttonWidth / 2f, y, buttonWidth, buttonHeight)) {
handleMainMenuButtonClick(i);
return true;
}
}
float swapAccountsY = buttonStartY + (buttonHeight + buttonSpacing) * 2 + 5;
if (isMouseOver(scaledMouseX, scaledMouseY, centerX - buttonWidth / 2f, swapAccountsY, buttonWidth, buttonHeight)) {
handleMainMenuButtonClick(2);
return true;
}
float bottomY = swapAccountsY + buttonHeight + 5;
float bottomButtonWidth = 65;
float bottomButtonHeight = 20;
float bottomSpacing = 10;
float totalBottomWidth = bottomButtonWidth * 3 + bottomSpacing * 2;
float bottomStartX = centerX - totalBottomWidth / 2f;
for (int i = 0; i < 3; i++) {
float x = bottomStartX + i * (bottomButtonWidth + bottomSpacing);
if (isMouseOver(scaledMouseX, scaledMouseY, x, bottomY, bottomButtonWidth, bottomButtonHeight)) {
handleMainMenuButtonClick(i + 3);
return true;
}
}
}
} else if (currentView == View.ALT_SCREEN) {
return handleAltScreenClick(scaledMouseX, scaledMouseY, click);
}
return super.mouseClicked(click, doubled);
}
private void handleMainMenuButtonClick(int index) {
switch (index) {
case 0 -> this.client.setScreen(new SelectWorldScreen(this));
case 1 -> {
Screen screen = this.client.options.skipMultiplayerWarning
? new MultiplayerScreen(this)
: new MultiplayerWarningScreen(this);
this.client.setScreen(screen);
}
case 2 -> currentView = View.ALT_SCREEN;
case 3 -> this.client.setScreen(new OptionsScreen(this, this.client.options));
case 4 -> {}
case 5 -> this.client.scheduleStop();
}
}
private boolean handleAltScreenClick(float mouseX, float mouseY, Click click) {
int screenWidth = getFixedScaledWidth();
int screenHeight = getFixedScaledHeight();
float totalWidth = 100 + 5 + 300;
float totalHeight = 100 + 5 + 58;
float centerX = screenWidth / 2f;
float centerY = screenHeight / 2f;
float startX = centerX - totalWidth / 2f;
float startY = centerY - totalHeight / 2f;
float leftPanelX = startX;
float leftPanelTopY = startY;
float fieldX = leftPanelX + 5;
float fieldY = leftPanelTopY + 38;
float fieldHeight = 14;
float addButtonSize = 14;
float buttonGap = 3;
float fieldWidth = 100 - 10 - addButtonSize - buttonGap;
if (accountRenderer.isMouseOver(mouseX, mouseY, fieldX, fieldY, fieldWidth, fieldHeight)) {
nicknameFieldFocused = true;
return true;
} else {
nicknameFieldFocused = false;
}
float addButtonX = fieldX + fieldWidth + buttonGap;
float addButtonY = fieldY;
if (accountRenderer.isMouseOver(mouseX, mouseY, addButtonX, addButtonY, addButtonSize, addButtonSize)) {
if (!nicknameText.isEmpty()) {
addAccount(nicknameText);
nicknameText = "";
}
return true;
}
float buttonWidth = 100 - 10;
float buttonHeight = 16;
float randomButtonX = leftPanelX + 5;
float randomButtonY = fieldY + fieldHeight + 6;
if (accountRenderer.isMouseOver(mouseX, mouseY, randomButtonX, randomButtonY, buttonWidth, buttonHeight)) {
String randomNick = generateRandomNickname();
addAccount(randomNick);
nicknameText = "";
return true;
}
float clearButtonX = leftPanelX + 5;
float clearButtonY = randomButtonY + buttonHeight + 5;
if (accountRenderer.isMouseOver(mouseX, mouseY, clearButtonX, clearButtonY, buttonWidth, buttonHeight)) {
accountConfig.clearAllAccounts();
targetScrollOffset = 0f;
scrollOffset = 0f;
return true;
}
float rightPanelX = startX + 100 + 5;
float rightPanelY = startY;
float accountListX = rightPanelX + 5;
float accountListY = rightPanelY + 26;
float accountListWidth = 300 - 10;
float accountListHeight = 165 - 31;
if (!accountRenderer.isMouseOver(mouseX, mouseY, accountListX, accountListY, accountListWidth, accountListHeight)) {
return false;
}
float cardWidth = (accountListWidth - 5) / 2f;
float cardHeight = 40;
float cardGap = 5;
List<AccountEntry> sortedAccounts = accountConfig.getSortedAccounts();
for (int i = 0; i < sortedAccounts.size(); i++) {
int col = i % 2;
int row = i / 2;
float cardX = accountListX + col * (cardWidth + cardGap);
float cardY = accountListY + row * (cardHeight + cardGap) - scrollOffset;
if (cardY + cardHeight < accountListY || cardY > accountListY + accountListHeight) {
continue;
}
float btnSize = 12;
float buttonYPos = cardY + cardHeight - btnSize - 5;
float pinButtonX = cardX + cardWidth - btnSize * 2 - 8;
float deleteButtonX = cardX + cardWidth - btnSize - 5;
if (accountRenderer.isMouseOver(mouseX, mouseY, pinButtonX, buttonYPos, btnSize, btnSize)) {
AccountEntry entry = sortedAccounts.get(i);
entry.togglePinned();
if (entry.isPinned()) {
setActiveAccount(entry);
}
accountConfig.save();
return true;
}
if (accountRenderer.isMouseOver(mouseX, mouseY, deleteButtonX, buttonYPos, btnSize, btnSize)) {
accountConfig.removeAccountByIndex(i);
return true;
}
if (accountRenderer.isMouseOver(mouseX, mouseY, cardX, cardY, cardWidth, cardHeight)) {
setActiveAccount(sortedAccounts.get(i));
return true;
}
}
return false;
}
@override
public boolean mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) {
if (currentView != View.ALT_SCREEN) return false;
float scaledMouseX = toFixedCoord(mouseX);
float scaledMouseY = toFixedCoord(mouseY);
int screenWidth = getFixedScaledWidth();
int screenHeight = getFixedScaledHeight();
float totalWidth = 100 + 5 + 300;
float totalHeight = 100 + 5 + 58;
float centerX = screenWidth / 2f;
float centerY = screenHeight / 2f;
float startX = centerX - totalWidth / 2f;
float startY = centerY - totalHeight / 2f;
float rightPanelX = startX + 100 + 5;
float rightPanelY = startY;
if (accountRenderer.isMouseOver(scaledMouseX, scaledMouseY, rightPanelX, rightPanelY, 300, 165)) {
float cardHeight = 40;
float cardGap = 5;
float accountListHeight = 165 - 31;
int rows = (int) Math.ceil(accountConfig.getSortedAccounts().size() / 2.0);
float maxScroll = Math.max(0, rows * (cardHeight + cardGap) - accountListHeight);
targetScrollOffset -= (float) verticalAmount * 25;
targetScrollOffset = MathHelper.clamp(targetScrollOffset, 0, maxScroll);
float scrollSpeed = 12f;
float deltaTime = 0.016f;
float scrollDiff = targetScrollOffset - scrollOffset;
scrollOffset += scrollDiff * Math.min(1f, deltaTime * scrollSpeed);
return true;
}
return super.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount);
}
@override
public boolean keyPressed(KeyInput input) {
if (currentView == View.ALT_SCREEN) {
if (nicknameFieldFocused) {
int keyCode = input.key();
if (keyCode == 259) {
if (!nicknameText.isEmpty()) {
nicknameText = nicknameText.substring(0, nicknameText.length() - 1);
}
return true;
}
if (keyCode == 256) {
nicknameFieldFocused = false;
return true;
}
if (keyCode == 257 || keyCode == 335) {
if (!nicknameText.isEmpty()) {
addAccount(nicknameText);
nicknameText = "";
}
nicknameFieldFocused = false;
return true;
}
}
if (input.key() == 256) {
currentView = View.MAIN_MENU;
accountConfig.save();
return true;
}
}
return super.keyPressed(input);
}
@override
public boolean charTyped(CharInput input) {
if (currentView == View.ALT_SCREEN && nicknameFieldFocused) {
int codepoint = input.codepoint();
if (Character.isLetterOrDigit(codepoint) || codepoint == '_') {
if (nicknameText.length() < 16) {
nicknameText += Character.toString(codepoint);
}
return true;
}
}
return super.charTyped(input);
}
private void setActiveAccount(AccountEntry account) {
accountConfig.setActiveAccount(account.getName(), account.getDate(), account.getSkin());
SessionChanger.changeUsername(account.getName());
}
private void addAccount(String nickname) {
LocalDateTime now = LocalDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm");
String date = now.format(formatter);
AccountEntry entry = new AccountEntry(nickname, date, null);
accountConfig.addAccount(entry);
setActiveAccount(entry);
SessionChanger.changeUsername(nickname);
}
private String generateRandomNickname() {
Random random = new Random();
StringBuilder username = new StringBuilder();
char[] vowels = {'a', 'e', 'i', 'o', 'u'};
char[] consonants = {'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z'};
String finalUsername = null;
int attempts = 0;
final int MAX_ATTEMPTS = 10;
List<AccountEntry> existingAccounts = accountConfig.getAccounts();
do {
username.setLength(0);
int length = 6 + random.nextInt(5);
boolean startWithVowel = random.nextBoolean();
for (int i = 0; i < length; i++) {
if (i % 2 == 0) {
username.append(startWithVowel ? vowels[random.nextInt(vowels.length)] : consonants[random.nextInt(consonants.length)]);
} else {
username.append(startWithVowel ? consonants[random.nextInt(consonants.length)] : vowels[random.nextInt(vowels.length)]);
}
}
if (random.nextInt(100) < 30) {
username.append(random.nextInt(100));
}
String tempUsername = username.substring(0, 1).toUpperCase() + username.substring(1);
attempts++;
boolean exists = false;
for (AccountEntry account : existingAccounts) {
if (account.getName().equalsIgnoreCase(tempUsername)) {
exists = true;
break;
}
}
if (!exists) {
finalUsername = tempUsername;
break;
}
} while (attempts < MAX_ATTEMPTS);
if (finalUsername == null) {
finalUsername = username.substring(0, 1).toUpperCase() + username.substring(1) + (System.currentTimeMillis() % 1000);
}
return finalUsername;
}
@override
public void renderBackground(DrawContext context, int mouseX, int mouseY, float delta) {
drawBackground();
}
@override
public boolean shouldCloseOnEsc() {
return false;
}
@override
public boolean shouldPause() {
return false;
}
private int withAlpha(int color, int alpha) {
return (color & 0x00FFFFFF) | (MathHelper.clamp(alpha, 0, 255) << 24);
}
} Вот тут шрифты все
хз ты чет с фонтами сделал не моя проблема17:03:25: Executing ':net.fabricmc.devlaunchinjector.Main.main()'…
> Configure project :
Fabric Loom: 1.15.3
> Task :compileJava FAILED
[Incubating] Problems report is available at: file:///C:/Users/Mykola/Downloads/Rich-Modern/build/reports/problems/problems-report.html
Deprecated Gradle features were used in this build, making it incompatible with Gradle 10.
You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.
For more on this, please refer toПожалуйста, авторизуйтесь для просмотра ссылки.in the Gradle documentation.
1 actionable task: 1 executed
C:\Users\Mykola\Downloads\Rich-Modern\src\main\java\rich\screens\menu\MainMenuScreen.java:107: error: incompatible types: float cannot be converted to float[]
buttonHoverProgress = 0f;
^
C:\Users\Mykola\Downloads\Rich-Modern\src\main\java\rich\screens\menu\MainMenuScreen.java:307: error: cannot find symbol
Fonts.SYSTEM.drawCentered(footerText, centerX, screenHeight - 17, 6.5f, new Color(100, 100, 100).getRGB());
^
symbol: variable SYSTEM
location: class Fonts
C:\Users\Mykola\Downloads\Rich-Modern\src\main\java\rich\screens\menu\MainMenuScreen.java:308: error: cannot find symbol
Fonts.SYSTEM.drawCentered(policyLinks, centerX, screenHeight - 8, 6.5f, new Color(100, 100, 100).getRGB());
^
symbol: variable SYSTEM
location: class Fonts
C:\Users\Mykola\Downloads\Rich-Modern\src\main\java\rich\screens\menu\MainMenuScreen.java:421: error: no suitable method found for lerp(float,float[],float)
buttonHoverProgress = MathHelper.lerp(lerpSpeed, buttonHoverProgress, target);
^
method MathHelper.lerp(float,int,int) is not applicable
(argument mismatch; float[] cannot be converted to int)
method MathHelper.lerp(float,float,float) is not applicable
(argument mismatch; float[] cannot be converted to float)
method MathHelper.lerp(double,Vec3d,Vec3d) is not applicable
(argument mismatch; float[] cannot be converted to Vec3d)
method MathHelper.lerp(double,double,double) is not applicable
(argument mismatch; float[] cannot be converted to double)
C:\Users\Mykola\Downloads\Rich-Modern\src\main\java\rich\screens\menu\MainMenuScreen.java:443: error: no suitable method found for lerp(float,float[],float)
buttonHoverProgress = MathHelper.lerp(lerpSpeed, buttonHoverProgress, 0f);
^
method MathHelper.lerp(float,int,int) is not applicable
(argument mismatch; float[] cannot be converted to int)
method MathHelper.lerp(float,float,float) is not applicable
(argument mismatch; float[] cannot be converted to float)
method MathHelper.lerp(double,Vec3d,Vec3d) is not applicable
(argument mismatch; float[] cannot be converted to Vec3d)
method MathHelper.lerp(double,double,double) is not applicable
(argument mismatch; float[] cannot be converted to double)
5 errors
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':compileJava'.
> Compilation failed; see the compiler output below.
C:\Users\Mykola\Downloads\Rich-Modern\src\main\java\rich\screens\menu\MainMenuScreen.java:421: error: no suitable method found for lerp(float,float[],float)
buttonHoverProgress = MathHelper.lerp(lerpSpeed, buttonHoverProgress, target);
^
method MathHelper.lerp(float,int,int) is not applicable
(argument mismatch; float[] cannot be converted to int)
method MathHelper.lerp(float,float,float) is not applicable
(argument mismatch; float[] cannot be converted to float)
method MathHelper.lerp(double,Vec3d,Vec3d) is not applicable
(argument mismatch; float[] cannot be converted to Vec3d)
method MathHelper.lerp(double,double,double) is not applicable
(argument mismatch; float[] cannot be converted to double)
C:\Users\Mykola\Downloads\Rich-Modern\src\main\java\rich\screens\menu\MainMenuScreen.java:443: error: no suitable method found for lerp(float,float[],float)
buttonHoverProgress = MathHelper.lerp(lerpSpeed, buttonHoverProgress, 0f);
^
method MathHelper.lerp(float,int,int) is not applicable
(argument mismatch; float[] cannot be converted to int)
method MathHelper.lerp(float,float,float) is not applicable
(argument mismatch; float[] cannot be converted to float)
method MathHelper.lerp(double,Vec3d,Vec3d) is not applicable
(argument mismatch; float[] cannot be converted to Vec3d)
method MathHelper.lerp(double,double,double) is not applicable
(argument mismatch; float[] cannot be converted to double)
C:\Users\Mykola\Downloads\Rich-Modern\src\main\java\rich\screens\menu\MainMenuScreen.java:107: error: incompatible types: float cannot be converted to float[]
buttonHoverProgress = 0f;
^
C:\Users\Mykola\Downloads\Rich-Modern\src\main\java\rich\screens\menu\MainMenuScreen.java:307: error: cannot find symbol
Fonts.SYSTEM.drawCentered(footerText, centerX, screenHeight - 17, 6.5f, new Color(100, 100, 100).getRGB());
^
symbol: variable SYSTEM
location: class Fonts
C:\Users\Mykola\Downloads\Rich-Modern\src\main\java\rich\screens\menu\MainMenuScreen.java:308: error: cannot find symbol
Fonts.SYSTEM.drawCentered(policyLinks, centerX, screenHeight - 8, 6.5f, new Color(100, 100, 100).getRGB());
^
symbol: variable SYSTEM
location: class Fonts
5 errors
* Try:
> Check your code and dependencies to fix the compilation error(s)
> Run with --scan to generate a Build Scan (powered by Develocity).
BUILD FAILED in 1s
17:03:27: Execution finished ':net.fabricmc.devlaunchinjector.Main.main()'.
нихуя, это рил годно /topврод похоже хз
фонты думаю сами найдете
векса:код:package rich.screens.menu; import net.minecraft.client.gui.Click; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen; import net.minecraft.client.gui.screen.multiplayer.MultiplayerWarningScreen; import net.minecraft.client.gui.screen.option.OptionsScreen; import net.minecraft.client.gui.screen.world.SelectWorldScreen; import net.minecraft.client.input.KeyInput; import net.minecraft.client.input.CharInput; import net.minecraft.text.Text; import net.minecraft.util.Identifier; import net.minecraft.util.Util; import net.minecraft.util.math.MathHelper; import rich.Initialization; import rich.screens.account.AccountEntry; import rich.screens.account.AccountRenderer; import rich.util.config.impl.account.AccountConfig; import rich.util.render.Render2D; import rich.util.render.font.Fonts; import rich.util.session.SessionChanger; import rich.util.sounds.SoundManager; import antidaunleak.api.UserProfile; import java.awt.*; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.List; import java.util.Random; public class MainMenuScreen extends Screen { private static final Identifier BACKGROUND_TEXTURE = Identifier.of("rich", "textures/menu/backmenu.png"); private static final float FIXED_GUI_SCALE = 2.0f; private static final int PARTICLE_COUNT = 50; private static final float PARTICLE_FADE_THRESHOLD = 0.8f; private static class Particle { float x, y; float vx, vy; float size; float alpha; float lifetime; float maxLifetime; boolean isDead = false; Particle(float x, float y) { this.x = x; this.y = y; Random rand = new Random(); this.vx = (rand.nextFloat() - 0.5f) * 0.2f; this.vy = (rand.nextFloat() - 0.5f) * 0.2f; this.size = 0.5f + rand.nextFloat() * 1f; this.alpha = 0.2f + rand.nextFloat() * 0.3f; this.maxLifetime = 10f + rand.nextFloat() * 10f; this.lifetime = 0f; } void update(float delta, int width, int height) { lifetime += delta / 60f; if (lifetime > maxLifetime * PARTICLE_FADE_THRESHOLD) { float fadeProgress = (lifetime - maxLifetime * PARTICLE_FADE_THRESHOLD) / (maxLifetime * (1f - PARTICLE_FADE_THRESHOLD)); alpha = Math.max(0, alpha * (1f - fadeProgress)); } if (lifetime >= maxLifetime) { isDead = true; return; } x += vx * delta; y += vy * delta; if (x < -10 || x > width + 10 || y < -10 || y > height + 10) { isDead = true; } } } private final List<Particle> particles = new java.util.ArrayList<>(); private boolean particlesInitialized = false; private int lastWindowWidth = 0; private int lastWindowHeight = 0; private enum View { MAIN_MENU, ALT_SCREEN } private View currentView = View.MAIN_MENU; private long screenStartTime = 0L; private boolean initialized = false; private long lastRenderTime = 0L; private int hoveredButton = -1; private float[] buttonHoverProgress = new float[6]; private final AccountRenderer accountRenderer; private final AccountConfig accountConfig; private String nicknameText = ""; private boolean nicknameFieldFocused = false; private float scrollOffset = 0f; private float targetScrollOffset = 0f; public MainMenuScreen() { super(Text.literal("Main Menu")); for (int i = 0; i < 6; i++) { buttonHoverProgress[i] = 0f; } this.accountRenderer = new AccountRenderer(); this.accountConfig = AccountConfig.getInstance(); this.accountConfig.load(); } @Override protected void init() { initialized = false; particlesInitialized = false; } private int getFixedScaledWidth() { return (int) Math.ceil((double) client.getWindow().getFramebufferWidth() / FIXED_GUI_SCALE); } private int getFixedScaledHeight() { return (int) Math.ceil((double) client.getWindow().getFramebufferHeight() / FIXED_GUI_SCALE); } private float toFixedCoord(double coord) { float currentScale = (float) client.getWindow().getScaleFactor(); return (float) (coord * currentScale / FIXED_GUI_SCALE); } private void initParticles(int width, int height) { if (particlesInitialized) return; Random rand = new Random(); for (int i = 0; i < PARTICLE_COUNT; i++) { particles.add(new Particle(rand.nextFloat() * width, rand.nextFloat() * height)); } particlesInitialized = true; } private void drawBackground() { int screenWidth = getFixedScaledWidth(); int screenHeight = getFixedScaledHeight(); Render2D.rect(0, 0, screenWidth, screenHeight, new Color(12, 15, 18).getRGB()); initParticles(screenWidth, screenHeight); for (Particle p : particles) { if (!p.isDead && p.alpha > 0.01f) { int alpha = (int) (p.alpha * 255); Render2D.rect(p.x, p.y, p.size, p.size, new Color(255, 255, 255, alpha).getRGB()); } } } @Override public void render(DrawContext context, int mouseX, int mouseY, float delta) { long currentTime = Util.getMeasuringTimeMs(); if (!initialized) { screenStartTime = currentTime; lastRenderTime = currentTime; initialized = true; } float deltaTime = Math.min(delta, 0.05f); lastRenderTime = currentTime; int fixedWidth = getFixedScaledWidth(); int fixedHeight = getFixedScaledHeight(); if (lastWindowWidth != fixedWidth || lastWindowHeight != fixedHeight) { particles.clear(); particlesInitialized = false; lastWindowWidth = fixedWidth; lastWindowHeight = fixedHeight; } for (Particle p : particles) { p.update(deltaTime * 60f, fixedWidth, fixedHeight); } particles.removeIf(p -> p.isDead); Random rand = new Random(); while (particles.size() < PARTICLE_COUNT) { particles.add(new Particle(rand.nextFloat() * fixedWidth, rand.nextFloat() * fixedHeight)); } float scaledMouseX = toFixedCoord(mouseX); float scaledMouseY = toFixedCoord(mouseY); updateButtonAnimations(deltaTime, scaledMouseX, scaledMouseY, fixedWidth, fixedHeight); Render2D.beginOverlay(); drawBackground(); if (currentView == View.MAIN_MENU) { renderMainMenu(fixedWidth, fixedHeight, scaledMouseX, scaledMouseY); } else { renderAltScreen(fixedWidth, fixedHeight, scaledMouseX, scaledMouseY, currentTime); } Render2D.endOverlay(); } private void renderMainMenu(int screenWidth, int screenHeight, float mouseX, float mouseY) { float centerX = screenWidth / 2f; float centerY = screenHeight / 2f; String username = "user"; float avatarSize = 20; float avatarX = 8; float avatarY = 10; Fonts.INTER_MEDIUM.draw("Logged in as", avatarX + avatarSize + 5, avatarY, 7f, new Color(150, 150, 150).getRGB()); Fonts.INTER_MEDIUM.draw(username, avatarX + avatarSize + 5, avatarY + 9, 8f, new Color(255, 255, 255).getRGB()); Render2D.rect(avatarX, avatarY, avatarSize, avatarSize, new Color(40, 45, 55).getRGB(), avatarSize / 2f); Identifier userAvatar = Identifier.of("rich", "user.png"); int[] avatarColors = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}; float[] avatarRadii = {avatarSize / 2f, avatarSize / 2f, avatarSize / 2f, avatarSize / 2f}; Initialization.getInstance().getManager().getRenderCore().getTexturePipeline() .drawTexture(userAvatar, avatarX, avatarY, avatarSize, avatarSize, 0, 0, 1, 1, avatarColors, avatarRadii, 1f); float logoSize = 35; float logoY = centerY - 90; Identifier logoTexture = Identifier.of("rich", "images/logo.png"); int[] logoColors = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}; float[] logoRadii = {0, 0, 0, 0}; Initialization.getInstance().getManager().getRenderCore().getTexturePipeline() .drawTexture(logoTexture, centerX - logoSize / 2f, logoY, logoSize, logoSize, 0, 0, 1, 1, logoColors, logoRadii, 1f); String timeOfDay = getTimeOfDay(); String greeting = "Good " + timeOfDay + ", "; String usernameColored = username; float greetingWidth = Fonts.INTER_SEMIBOLD.getWidth(greeting, 14f); float usernameWidth = Fonts.INTER_SEMIBOLD.getWidth(usernameColored, 14f); float totalGreetingWidth = greetingWidth + usernameWidth; float greetingStartX = centerX - totalGreetingWidth / 2f; float greetingY = centerY - 38; Fonts.INTER_SEMIBOLD.draw(greeting, greetingStartX, greetingY, 14f, new Color(255, 255, 255).getRGB()); Fonts.INTER_SEMIBOLD.draw(usernameColored, greetingStartX + greetingWidth, greetingY, 14f, new Color(100, 180, 255).getRGB()); String welcomeText = "Welcome to "; String clientName = "WexSide. The best client."; String restText = ""; float welcomeWidth = Fonts.INTER_MEDIUM.getWidth(welcomeText, 9f); float clientWidth = Fonts.INTER_MEDIUM.getWidth(clientName, 9f); float restWidth = Fonts.INTER_MEDIUM.getWidth(restText, 9f); float totalWidth = welcomeWidth + clientWidth + restWidth; float startX = centerX - totalWidth / 2f; float textY = centerY - 20; Fonts.INTER_MEDIUM.draw(welcomeText, startX, textY, 9f, new Color(180, 180, 180).getRGB()); Fonts.INTER_SEMIBOLD.draw(clientName, startX + welcomeWidth, textY, 9f, new Color(90, 22, 134).getRGB()); Fonts.INTER_MEDIUM.draw(restText, startX + welcomeWidth + clientWidth, textY, 9f, new Color(180, 180, 180).getRGB()); float buttonWidth = 220; float buttonHeight = 30; float buttonSpacing = 7; float buttonStartY = centerY + 3; drawButton(centerX - buttonWidth / 2f, buttonStartY, buttonWidth, buttonHeight, "Singleplayer", 0, mouseX, mouseY, new Color(30, 35, 45), false); drawButton(centerX - buttonWidth / 2f, buttonStartY + buttonHeight + buttonSpacing, buttonWidth, buttonHeight, "Multiplayer", 1, mouseX, mouseY, new Color(30, 35, 45), false); float swapAccountsY = buttonStartY + (buttonHeight + buttonSpacing) * 2 + 5; drawButton(centerX - buttonWidth / 2f, swapAccountsY, buttonWidth, buttonHeight, "Swap Accounts", 2, mouseX, mouseY, new Color(90, 22, 134), true); float bottomY = swapAccountsY + buttonHeight + 5; float bottomButtonWidth = 65; float bottomButtonHeight = 20; float bottomSpacing = 10; float totalBottomWidth = bottomButtonWidth * 3 + bottomSpacing * 2; float bottomStartX = centerX - totalBottomWidth / 2f; drawSmallButton(bottomStartX, bottomY, bottomButtonWidth, bottomButtonHeight, "Options", 3, mouseX, mouseY); drawSmallButton(bottomStartX + bottomButtonWidth + bottomSpacing, bottomY, bottomButtonWidth, bottomButtonHeight, "Proxies", 4, mouseX, mouseY); drawSmallButton(bottomStartX + (bottomButtonWidth + bottomSpacing) * 2, bottomY, bottomButtonWidth, bottomButtonHeight, "Exit", 5, mouseX, mouseY); String footerText = "By logging into your account, you agree to all of our policies,"; String policyLinks = "including our Privacy Policy and Terms of Service"; Fonts.INTER_MEDIUM.drawCentered(footerText, centerX, screenHeight - 17, 6.5f, new Color(100, 100, 100).getRGB()); Fonts.INTER_MEDIUM.drawCentered(policyLinks, centerX, screenHeight - 8, 6.5f, new Color(100, 100, 100).getRGB()); } private String getTimeOfDay() { int hour = java.time.LocalTime.now().getHour(); if (hour >= 5 && hour < 12) return "morning"; if (hour >= 12 && hour < 17) return "afternoon"; if (hour >= 17 && hour < 21) return "evening"; return "night"; } private void drawButton(float x, float y, float width, float height, String text, int index, float mouseX, float mouseY, Color baseColor, boolean isPurple) { boolean hovered = isMouseOver(mouseX, mouseY, x, y, width, height); float hoverProgress = buttonHoverProgress[index]; Color bgColor = baseColor; if (isPurple) { int brightness = (int) (hoverProgress * 20); bgColor = new Color( Math.min(255, baseColor.getRed() + brightness), Math.min(255, baseColor.getGreen() + brightness), Math.min(255, baseColor.getBlue() + brightness) ); } else { int brightness = (int) (hoverProgress * 15); bgColor = new Color( Math.min(255, baseColor.getRed() + brightness), Math.min(255, baseColor.getGreen() + brightness), Math.min(255, baseColor.getBlue() + brightness) ); } Render2D.rect(x, y, width, height, bgColor.getRGB(), 8); if (!isPurple) { Render2D.outline(x, y, width, height, 1f, new Color(50, 55, 65, 80).getRGB(), 8); } if (hoverProgress > 0.01f) { int borderAlpha = (int) (hoverProgress * 100); Color borderColor = isPurple ? new Color(138, 43, 226, borderAlpha) : new Color(100, 110, 130, borderAlpha); Render2D.outline(x, y, width, height, 1f, borderColor.getRGB(), 8); } float fontSize = 9f; float textHeight = Fonts.INTER_MEDIUM.getHeight(fontSize); Color textColor = isPurple ? new Color(255, 255, 255) : new Color(160, 160, 160); Fonts.INTER_MEDIUM.drawCentered(text, x + width / 2f, y + (height - textHeight) / 2f, fontSize, textColor.getRGB()); } private void drawSmallButton(float x, float y, float width, float height, String text, int index, float mouseX, float mouseY) { float hoverProgress = buttonHoverProgress[index]; int baseAlpha = 150; int hoverAlpha = (int) (baseAlpha + hoverProgress * 50); float fontSize = 8f; float textHeight = Fonts.INTER_MEDIUM.getHeight(fontSize); Fonts.INTER_MEDIUM.drawCentered(text, x + width / 2f, y + (height - textHeight) / 2f, fontSize, new Color(180, 180, 180, hoverAlpha).getRGB()); } private boolean isMouseOver(float mouseX, float mouseY, float x, float y, float width, float height) { return mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height; } private void updateButtonAnimations(float deltaTime, float mouseX, float mouseY, int screenWidth, int screenHeight) { float centerX = screenWidth / 2f; float centerY = screenHeight / 2f; float lerpSpeed = 1f - (float) Math.pow(0.001f, deltaTime); if (currentView == View.MAIN_MENU) { float buttonWidth = 220; float buttonHeight = 30; float buttonSpacing = 7; float buttonStartY = centerY + 3; for (int i = 0; i < 2; i++) { float y = buttonStartY + i * (buttonHeight + buttonSpacing); boolean hovered = isMouseOver(mouseX, mouseY, centerX - buttonWidth / 2f, y, buttonWidth, buttonHeight); float target = hovered ? 1f : 0f; buttonHoverProgress[i] = MathHelper.lerp(lerpSpeed, buttonHoverProgress[i], target); } float swapAccountsY = buttonStartY + (buttonHeight + buttonSpacing) * 2 + 5; boolean swapHovered = isMouseOver(mouseX, mouseY, centerX - buttonWidth / 2f, swapAccountsY, buttonWidth, buttonHeight); buttonHoverProgress[2] = MathHelper.lerp(lerpSpeed, buttonHoverProgress[2], swapHovered ? 1f : 0f); float bottomY = swapAccountsY + buttonHeight + 5; float bottomButtonWidth = 65; float bottomButtonHeight = 20; float bottomSpacing = 10; float totalBottomWidth = bottomButtonWidth * 3 + bottomSpacing * 2; float bottomStartX = centerX - totalBottomWidth / 2f; for (int i = 0; i < 3; i++) { float x = bottomStartX + i * (bottomButtonWidth + bottomSpacing); boolean hovered = isMouseOver(mouseX, mouseY, x, bottomY, bottomButtonWidth, bottomButtonHeight); float target = hovered ? 1f : 0f; buttonHoverProgress[i + 3] = MathHelper.lerp(lerpSpeed, buttonHoverProgress[i + 3], target); } } else { for (int i = 0; i < 6; i++) { buttonHoverProgress[i] = MathHelper.lerp(lerpSpeed, buttonHoverProgress[i], 0f); } } } private void renderAltScreen(int screenWidth, int screenHeight, float mouseX, float mouseY, long currentTime) { float totalWidth = 405; float totalHeight = 163; float centerX = screenWidth / 2f; float centerY = screenHeight / 2f; float startX = centerX - totalWidth / 2f; float startY = centerY - totalHeight / 2f; float leftPanelX = startX; float leftPanelTopY = startY; accountRenderer.renderLeftPanelTop(leftPanelX, leftPanelTopY, 100, 100, 1f, nicknameText, nicknameFieldFocused, mouseX, mouseY, currentTime); float leftPanelBottomY = startY + 100 + 5; accountRenderer.renderLeftPanelBottom(leftPanelX, leftPanelBottomY, 100, 58, 1f, accountConfig.getActiveAccountName(), accountConfig.getActiveAccountDate(), accountConfig.getActiveAccountSkin()); float rightPanelX = startX + 100 + 5; float rightPanelY = startY; List<AccountEntry> sortedAccounts = accountConfig.getSortedAccounts(); accountRenderer.renderRightPanel(rightPanelX, rightPanelY, 300, 165, 1f, sortedAccounts, scrollOffset, mouseX, mouseY, 1f, (int) FIXED_GUI_SCALE); } @Override public boolean mouseClicked(Click click, boolean doubled) { float scaledMouseX = toFixedCoord(click.x()); float scaledMouseY = toFixedCoord(click.y()); if (currentView == View.MAIN_MENU) { if (click.button() == 0) { int fixedWidth = getFixedScaledWidth(); int fixedHeight = getFixedScaledHeight(); float centerX = fixedWidth / 2f; float centerY = fixedHeight / 2f; float buttonWidth = 220; float buttonHeight = 30; float buttonSpacing = 7; float buttonStartY = centerY + 3; for (int i = 0; i < 2; i++) { float y = buttonStartY + i * (buttonHeight + buttonSpacing); if (isMouseOver(scaledMouseX, scaledMouseY, centerX - buttonWidth / 2f, y, buttonWidth, buttonHeight)) { handleMainMenuButtonClick(i); return true; } } float swapAccountsY = buttonStartY + (buttonHeight + buttonSpacing) * 2 + 5; if (isMouseOver(scaledMouseX, scaledMouseY, centerX - buttonWidth / 2f, swapAccountsY, buttonWidth, buttonHeight)) { handleMainMenuButtonClick(2); return true; } float bottomY = swapAccountsY + buttonHeight + 5; float bottomButtonWidth = 65; float bottomButtonHeight = 20; float bottomSpacing = 10; float totalBottomWidth = bottomButtonWidth * 3 + bottomSpacing * 2; float bottomStartX = centerX - totalBottomWidth / 2f; for (int i = 0; i < 3; i++) { float x = bottomStartX + i * (bottomButtonWidth + bottomSpacing); if (isMouseOver(scaledMouseX, scaledMouseY, x, bottomY, bottomButtonWidth, bottomButtonHeight)) { handleMainMenuButtonClick(i + 3); return true; } } } } else if (currentView == View.ALT_SCREEN) { return handleAltScreenClick(scaledMouseX, scaledMouseY, click); } return super.mouseClicked(click, doubled); } private void handleMainMenuButtonClick(int index) { switch (index) { case 0 -> this.client.setScreen(new SelectWorldScreen(this)); case 1 -> { Screen screen = this.client.options.skipMultiplayerWarning ? new MultiplayerScreen(this) : new MultiplayerWarningScreen(this); this.client.setScreen(screen); } case 2 -> currentView = View.ALT_SCREEN; case 3 -> this.client.setScreen(new OptionsScreen(this, this.client.options)); case 4 -> {} case 5 -> this.client.scheduleStop(); } } private boolean handleAltScreenClick(float mouseX, float mouseY, Click click) { int screenWidth = getFixedScaledWidth(); int screenHeight = getFixedScaledHeight(); float totalWidth = 100 + 5 + 300; float totalHeight = 100 + 5 + 58; float centerX = screenWidth / 2f; float centerY = screenHeight / 2f; float startX = centerX - totalWidth / 2f; float startY = centerY - totalHeight / 2f; float leftPanelX = startX; float leftPanelTopY = startY; float fieldX = leftPanelX + 5; float fieldY = leftPanelTopY + 38; float fieldHeight = 14; float addButtonSize = 14; float buttonGap = 3; float fieldWidth = 100 - 10 - addButtonSize - buttonGap; if (accountRenderer.isMouseOver(mouseX, mouseY, fieldX, fieldY, fieldWidth, fieldHeight)) { nicknameFieldFocused = true; return true; } else { nicknameFieldFocused = false; } float addButtonX = fieldX + fieldWidth + buttonGap; float addButtonY = fieldY; if (accountRenderer.isMouseOver(mouseX, mouseY, addButtonX, addButtonY, addButtonSize, addButtonSize)) { if (!nicknameText.isEmpty()) { addAccount(nicknameText); nicknameText = ""; } return true; } float buttonWidth = 100 - 10; float buttonHeight = 16; float randomButtonX = leftPanelX + 5; float randomButtonY = fieldY + fieldHeight + 6; if (accountRenderer.isMouseOver(mouseX, mouseY, randomButtonX, randomButtonY, buttonWidth, buttonHeight)) { String randomNick = generateRandomNickname(); addAccount(randomNick); nicknameText = ""; return true; } float clearButtonX = leftPanelX + 5; float clearButtonY = randomButtonY + buttonHeight + 5; if (accountRenderer.isMouseOver(mouseX, mouseY, clearButtonX, clearButtonY, buttonWidth, buttonHeight)) { accountConfig.clearAllAccounts(); targetScrollOffset = 0f; scrollOffset = 0f; return true; } float rightPanelX = startX + 100 + 5; float rightPanelY = startY; float accountListX = rightPanelX + 5; float accountListY = rightPanelY + 26; float accountListWidth = 300 - 10; float accountListHeight = 165 - 31; if (!accountRenderer.isMouseOver(mouseX, mouseY, accountListX, accountListY, accountListWidth, accountListHeight)) { return false; } float cardWidth = (accountListWidth - 5) / 2f; float cardHeight = 40; float cardGap = 5; List<AccountEntry> sortedAccounts = accountConfig.getSortedAccounts(); for (int i = 0; i < sortedAccounts.size(); i++) { int col = i % 2; int row = i / 2; float cardX = accountListX + col * (cardWidth + cardGap); float cardY = accountListY + row * (cardHeight + cardGap) - scrollOffset; if (cardY + cardHeight < accountListY || cardY > accountListY + accountListHeight) { continue; } float btnSize = 12; float buttonYPos = cardY + cardHeight - btnSize - 5; float pinButtonX = cardX + cardWidth - btnSize * 2 - 8; float deleteButtonX = cardX + cardWidth - btnSize - 5; if (accountRenderer.isMouseOver(mouseX, mouseY, pinButtonX, buttonYPos, btnSize, btnSize)) { AccountEntry entry = sortedAccounts.get(i); entry.togglePinned(); if (entry.isPinned()) { setActiveAccount(entry); } accountConfig.save(); return true; } if (accountRenderer.isMouseOver(mouseX, mouseY, deleteButtonX, buttonYPos, btnSize, btnSize)) { accountConfig.removeAccountByIndex(i); return true; } if (accountRenderer.isMouseOver(mouseX, mouseY, cardX, cardY, cardWidth, cardHeight)) { setActiveAccount(sortedAccounts.get(i)); return true; } } return false; } @Override public boolean mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { if (currentView != View.ALT_SCREEN) return false; float scaledMouseX = toFixedCoord(mouseX); float scaledMouseY = toFixedCoord(mouseY); int screenWidth = getFixedScaledWidth(); int screenHeight = getFixedScaledHeight(); float totalWidth = 100 + 5 + 300; float totalHeight = 100 + 5 + 58; float centerX = screenWidth / 2f; float centerY = screenHeight / 2f; float startX = centerX - totalWidth / 2f; float startY = centerY - totalHeight / 2f; float rightPanelX = startX + 100 + 5; float rightPanelY = startY; if (accountRenderer.isMouseOver(scaledMouseX, scaledMouseY, rightPanelX, rightPanelY, 300, 165)) { float cardHeight = 40; float cardGap = 5; float accountListHeight = 165 - 31; int rows = (int) Math.ceil(accountConfig.getSortedAccounts().size() / 2.0); float maxScroll = Math.max(0, rows * (cardHeight + cardGap) - accountListHeight); targetScrollOffset -= (float) verticalAmount * 25; targetScrollOffset = MathHelper.clamp(targetScrollOffset, 0, maxScroll); float scrollSpeed = 12f; float deltaTime = 0.016f; float scrollDiff = targetScrollOffset - scrollOffset; scrollOffset += scrollDiff * Math.min(1f, deltaTime * scrollSpeed); return true; } return super.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount); } @Override public boolean keyPressed(KeyInput input) { if (currentView == View.ALT_SCREEN) { if (nicknameFieldFocused) { int keyCode = input.key(); if (keyCode == 259) { if (!nicknameText.isEmpty()) { nicknameText = nicknameText.substring(0, nicknameText.length() - 1); } return true; } if (keyCode == 256) { nicknameFieldFocused = false; return true; } if (keyCode == 257 || keyCode == 335) { if (!nicknameText.isEmpty()) { addAccount(nicknameText); nicknameText = ""; } nicknameFieldFocused = false; return true; } } if (input.key() == 256) { currentView = View.MAIN_MENU; accountConfig.save(); return true; } } return super.keyPressed(input); } @Override public boolean charTyped(CharInput input) { if (currentView == View.ALT_SCREEN && nicknameFieldFocused) { int codepoint = input.codepoint(); if (Character.isLetterOrDigit(codepoint) || codepoint == '_') { if (nicknameText.length() < 16) { nicknameText += Character.toString(codepoint); } return true; } } return super.charTyped(input); } private void setActiveAccount(AccountEntry account) { accountConfig.setActiveAccount(account.getName(), account.getDate(), account.getSkin()); SessionChanger.changeUsername(account.getName()); } private void addAccount(String nickname) { LocalDateTime now = LocalDateTime.now(); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm"); String date = now.format(formatter); AccountEntry entry = new AccountEntry(nickname, date, null); accountConfig.addAccount(entry); setActiveAccount(entry); SessionChanger.changeUsername(nickname); } private String generateRandomNickname() { Random random = new Random(); StringBuilder username = new StringBuilder(); char[] vowels = {'a', 'e', 'i', 'o', 'u'}; char[] consonants = {'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z'}; String finalUsername = null; int attempts = 0; final int MAX_ATTEMPTS = 10; List<AccountEntry> existingAccounts = accountConfig.getAccounts(); do { username.setLength(0); int length = 6 + random.nextInt(5); boolean startWithVowel = random.nextBoolean(); for (int i = 0; i < length; i++) { if (i % 2 == 0) { username.append(startWithVowel ? vowels[random.nextInt(vowels.length)] : consonants[random.nextInt(consonants.length)]); } else { username.append(startWithVowel ? consonants[random.nextInt(consonants.length)] : vowels[random.nextInt(vowels.length)]); } } if (random.nextInt(100) < 30) { username.append(random.nextInt(100)); } String tempUsername = username.substring(0, 1).toUpperCase() + username.substring(1); attempts++; boolean exists = false; for (AccountEntry account : existingAccounts) { if (account.getName().equalsIgnoreCase(tempUsername)) { exists = true; break; } } if (!exists) { finalUsername = tempUsername; break; } } while (attempts < MAX_ATTEMPTS); if (finalUsername == null) { finalUsername = username.substring(0, 1).toUpperCase() + username.substring(1) + (System.currentTimeMillis() % 1000); } return finalUsername; } @Override public void renderBackground(DrawContext context, int mouseX, int mouseY, float delta) { drawBackground(); } @Override public boolean shouldCloseOnEsc() { return false; } @Override public boolean shouldPause() { return false; } private int withAlpha(int color, int alpha) { return (color & 0x00FFFFFF) | (MathHelper.clamp(alpha, 0, 255) << 24); } } }
Посмотреть вложение 327281
мое:Посмотреть вложение 327344
upd: добавил обводку
Проект предоставляет различный материал, относящийся к сфере киберспорта, программирования, ПО для игр, а также позволяет его участникам общаться на многие другие темы. Почта для жалоб: admin@yougame.biz