Подписывайтесь на наш Telegram и не пропускайте важные новости! Перейти

Визуальная часть Mainmenu skid wexside (rich 1.21.11)

Начинающий
Начинающий
Статус
Оффлайн
Регистрация
17 Фев 2025
Сообщения
38
Реакции
1
Выберите загрузчик игры
  1. Fabric
врод похоже хз
фонты думаю сами найдете
код:
Expand Collapse Copy
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);
    }
}

}
векса:
1770828362292.png

мое:
1770872822932.png


upd: добавил обводку
 

Вложения

  • logo.png
    logo.png
    7.9 KB · Просмотры: 82
Последнее редактирование:
врод похоже хз
фонты думаю сами найдете
код:
Expand Collapse Copy
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: добавил обводку
Норм
 
врод похоже хз
фонты думаю сами найдете
код:
Expand Collapse Copy
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: добавил обводку
ахуенно
 
врод похоже хз
фонты думаю сами найдете
код:
Expand Collapse Copy
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: добавил обводку
норм
 
врод похоже хз
фонты думаю сами найдете
код:
Expand Collapse Copy
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: добавил обводку
Похоже, норм
 
Назад
Сверху Снизу