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

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

ну слушай получилось довольно не плохой скид но внизу где серый текст у векса текст белым ссылкой у тебя нету и фон чуть темнее чем у векса а так годно
блять там 3 строки поменять
 
врод похоже хз
фонты думаю сами найдете
код:
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: добавил обводку
ну мне нрав, да и вроде повторил как у векса
 
как фиксить?
20:50:07: Executing ':net.fabricmc.devlaunchinjector.Main.main()'…


> Configure project :
Fabric Loom: 1.15.3

> Task :compileJava FAILED

[Incubating] Problems report is available at: file:///C:/Users/Mykola/Downloads/Rich-Modern/build/reports/problems/problems-report.html

Deprecated Gradle features were used in this build, making it incompatible with Gradle 10.

You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.

For more on this, please refer to
Пожалуйста, авторизуйтесь для просмотра ссылки.
in the Gradle documentation.
1 actionable task: 1 executed
C:\Users\Mykola\Downloads\Rich-Modern\src\main\java\rich\screens\menu\MainMenuScreen.java:820: error: class, interface, enum, or record expected
}
^
1 error

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':compileJava'.
> Compilation failed; see the compiler output below.
C:\Users\Mykola\Downloads\Rich-Modern\src\main\java\rich\screens\menu\MainMenuScreen.java:820: error: class, interface, enum, or record expected
}
^
1 error

* Try:
> Check your code and dependencies to fix the compilation error(s)
> Run with --scan to generate a Build Scan (powered by Develocity).

BUILD FAILED in 595ms
20:50:07: Execution finished ':net.fabricmc.devlaunchinjector.Main.main()'.
 
врод похоже хз
фонты думаю сами найдете
код:
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: добавил обводку
+rep
 
где найти именно етот фонт
подумай логически
как фиксить?
20:50:07: Executing ':net.fabricmc.devlaunchinjector.Main.main()'…


> Configure project :
Fabric Loom: 1.15.3

> Task :compileJava FAILED

[Incubating] Problems report is available at: file:///C:/Users/Mykola/Downloads/Rich-Modern/build/reports/problems/problems-report.html

Deprecated Gradle features were used in this build, making it incompatible with Gradle 10.

You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.

For more on this, please refer to
Пожалуйста, авторизуйтесь для просмотра ссылки.
in the Gradle documentation.
1 actionable task: 1 executed
C:\Users\Mykola\Downloads\Rich-Modern\src\main\java\rich\screens\menu\MainMenuScreen.java:820: error: class, interface, enum, or record expected
}
^
1 error

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':compileJava'.
> Compilation failed; see the compiler output below.
C:\Users\Mykola\Downloads\Rich-Modern\src\main\java\rich\screens\menu\MainMenuScreen.java:820: error: class, interface, enum, or record expected
}
^
1 error

* Try:
> Check your code and dependencies to fix the compilation error(s)
> Run with --scan to generate a Build Scan (powered by Develocity).

BUILD FAILED in 595ms
20:50:07: Execution finished ':net.fabricmc.devlaunchinjector.Main.main()'.
в конце кода удали один } опечатка случайно
 
врод похоже хз
фонты думаю сами найдете
код:
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: добавил обводку
Прям похоже,возможно на 1.21.4 перенести?
 
врод похоже хз
фонты думаю сами найдете
код:
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: добавил обводку
нахуя ты все делаешь чтоб сливатЬ, сделай для себя что-то крутое. Это глупо, каждый день тебя вижу xD
блин ребята только начал пастить куда мне logo.png кидать? расскажите ток без хейта плиз
нубез слов брат
 
нахуя ты все делаешь чтоб сливатЬ, сделай для себя что-то крутое. Это глупо, каждый день тебя вижу xD

нубез слов брат
хз я так то это 1 раз слил когда людям понравилось
блин ребята только начал пастить куда мне logo.png кидать? расскажите ток без хейта плиз
брат код почитай плз
 
как фиксить?
20:50:07: Executing ':net.fabricmc.devlaunchinjector.Main.main()'…


> Configure project :
Fabric Loom: 1.15.3

> Task :compileJava FAILED

[Incubating] Problems report is available at: file:///C:/Users/Mykola/Downloads/Rich-Modern/build/reports/problems/problems-report.html

Deprecated Gradle features were used in this build, making it incompatible with Gradle 10.

You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.

For more on this, please refer to
Пожалуйста, авторизуйтесь для просмотра ссылки.
in the Gradle documentation.
1 actionable task: 1 executed
C:\Users\Mykola\Downloads\Rich-Modern\src\main\java\rich\screens\menu\MainMenuScreen.java:820: error: class, interface, enum, or record expected
}
^
1 error

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':compileJava'.
> Compilation failed; see the compiler output below.
C:\Users\Mykola\Downloads\Rich-Modern\src\main\java\rich\screens\menu\MainMenuScreen.java:820: error: class, interface, enum, or record expected
}
^
1 error

* Try:
> Check your code and dependencies to fix the compilation error(s)
> Run with --scan to generate a Build Scan (powered by Develocity).

BUILD FAILED in 595ms
20:50:07: Execution finished ':net.fabricmc.devlaunchinjector.Main.main()'.
мыколка
блин ребята только начал пастить куда мне logo.png кидать? расскажите ток без хейта плиз
images/logo.png
 
где фонт этот взять
package rich.screens.menu;

import net.minecraft.client.gui.Click;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen;
import net.minecraft.client.gui.screen.multiplayer.MultiplayerWarningScreen;
import net.minecraft.client.gui.screen.option.OptionsScreen;
import net.minecraft.client.gui.screen.world.SelectWorldScreen;
import net.minecraft.client.input.KeyInput;
import net.minecraft.client.input.CharInput;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import net.minecraft.util.Util;
import net.minecraft.util.math.MathHelper;
import rich.Initialization;
import rich.screens.account.AccountEntry;
import rich.screens.account.AccountRenderer;
import rich.util.config.impl.account.AccountConfig;
import rich.util.render.Render2D;
import rich.util.render.font.Fonts;
import rich.util.session.SessionChanger;
import rich.util.sounds.SoundManager;
import antidaunleak.api.UserProfile;

import java.awt.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Random;

public class MainMenuScreen extends Screen {

private static final Identifier BACKGROUND_TEXTURE = Identifier.of("rich", "textures/menu/backmenu.png");
private static final float FIXED_GUI_SCALE = 2.0f;
private static final int PARTICLE_COUNT = 50;
private static final float PARTICLE_FADE_THRESHOLD = 0.8f;

private static class Particle {
float x, y;
float vx, vy;
float size;
float alpha;
float lifetime;
float maxLifetime;
boolean isDead = false;

Particle(float x, float y) {
this.x = x;
this.y = y;
Random rand = new Random();
this.vx = (rand.nextFloat() - 0.5f) * 0.2f;
this.vy = (rand.nextFloat() - 0.5f) * 0.2f;
this.size = 0.5f + rand.nextFloat() * 1f;
this.alpha = 0.2f + rand.nextFloat() * 0.3f;
this.maxLifetime = 10f + rand.nextFloat() * 10f;
this.lifetime = 0f;
}

void update(float delta, int width, int height) {
lifetime += delta / 60f;

if (lifetime > maxLifetime * PARTICLE_FADE_THRESHOLD) {
float fadeProgress = (lifetime - maxLifetime * PARTICLE_FADE_THRESHOLD) / (maxLifetime * (1f - PARTICLE_FADE_THRESHOLD));
alpha = Math.max(0, alpha * (1f - fadeProgress));
}

if (lifetime >= maxLifetime) {
isDead = true;
return;
}

x += vx * delta;
y += vy * delta;

if (x < -10 || x > width + 10 || y < -10 || y > height + 10) {
isDead = true;
}
}
}

private final List<Particle> particles = new java.util.ArrayList<>();
private boolean particlesInitialized = false;
private int lastWindowWidth = 0;
private int lastWindowHeight = 0;

private enum View { MAIN_MENU, ALT_SCREEN }
private View currentView = View.MAIN_MENU;

private long screenStartTime = 0L;
private boolean initialized = false;
private long lastRenderTime = 0L;

private int hoveredButton = -1;
private float[] buttonHoverProgress = new float[6];

private final AccountRenderer accountRenderer;
private final AccountConfig accountConfig;
private String nicknameText = "";
private boolean nicknameFieldFocused = false;
private float scrollOffset = 0f;
private float targetScrollOffset = 0f;

public MainMenuScreen() {
super(Text.literal("Main Menu"));
for (int i = 0; i < 6; i++) {
buttonHoverProgress = 0f;
}
this.accountRenderer = new AccountRenderer();
this.accountConfig = AccountConfig.getInstance();
this.accountConfig.load();
}

@override
protected void init() {
initialized = false;
particlesInitialized = false;
}

private int getFixedScaledWidth() {
return (int) Math.ceil((double) client.getWindow().getFramebufferWidth() / FIXED_GUI_SCALE);
}

private int getFixedScaledHeight() {
return (int) Math.ceil((double) client.getWindow().getFramebufferHeight() / FIXED_GUI_SCALE);
}

private float toFixedCoord(double coord) {
float currentScale = (float) client.getWindow().getScaleFactor();
return (float) (coord * currentScale / FIXED_GUI_SCALE);
}

private void initParticles(int width, int height) {
if (particlesInitialized) return;
Random rand = new Random();
for (int i = 0; i < PARTICLE_COUNT; i++) {
particles.add(new Particle(rand.nextFloat() * width, rand.nextFloat() * height));
}
particlesInitialized = true;
}

private void drawBackground() {
int screenWidth = getFixedScaledWidth();
int screenHeight = getFixedScaledHeight();

Render2D.rect(0, 0, screenWidth, screenHeight, new Color(12, 15, 18).getRGB());

initParticles(screenWidth, screenHeight);

for (Particle p : particles) {
if (!p.isDead && p.alpha > 0.01f) {
int alpha = (int) (p.alpha * 255);
Render2D.rect(p.x, p.y, p.size, p.size, new Color(255, 255, 255, alpha).getRGB());
}
}
}

@override
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
long currentTime = Util.getMeasuringTimeMs();

if (!initialized) {
screenStartTime = currentTime;
lastRenderTime = currentTime;
initialized = true;
}

float deltaTime = Math.min(delta, 0.05f);
lastRenderTime = currentTime;

int fixedWidth = getFixedScaledWidth();
int fixedHeight = getFixedScaledHeight();

if (lastWindowWidth != fixedWidth || lastWindowHeight != fixedHeight) {
particles.clear();
particlesInitialized = false;
lastWindowWidth = fixedWidth;
lastWindowHeight = fixedHeight;
}

for (Particle p : particles) {
p.update(deltaTime * 60f, fixedWidth, fixedHeight);
}

particles.removeIf(p -> p.isDead);

Random rand = new Random();
while (particles.size() < PARTICLE_COUNT) {
particles.add(new Particle(rand.nextFloat() * fixedWidth, rand.nextFloat() * fixedHeight));
}

float scaledMouseX = toFixedCoord(mouseX);
float scaledMouseY = toFixedCoord(mouseY);

updateButtonAnimations(deltaTime, scaledMouseX, scaledMouseY, fixedWidth, fixedHeight);

Render2D.beginOverlay();

drawBackground();

if (currentView == View.MAIN_MENU) {
renderMainMenu(fixedWidth, fixedHeight, scaledMouseX, scaledMouseY);
} else {
renderAltScreen(fixedWidth, fixedHeight, scaledMouseX, scaledMouseY, currentTime);
}

Render2D.endOverlay();
}

private void renderMainMenu(int screenWidth, int screenHeight, float mouseX, float mouseY) {
float centerX = screenWidth / 2f;
float centerY = screenHeight / 2f;

String username = "user";

float avatarSize = 20;
float avatarX = 8;
float avatarY = 10;

Fonts.INTER.draw("Logged in as", avatarX + avatarSize + 5, avatarY, 7f, new Color(150, 150, 150).getRGB());
Fonts.INTER.draw(username, avatarX + avatarSize + 5, avatarY + 9, 8f, new Color(255, 255, 255).getRGB());

Render2D.rect(avatarX, avatarY, avatarSize, avatarSize, new Color(40, 45, 55).getRGB(), avatarSize / 2f);

Identifier userAvatar = Identifier.of("rich", "steve.png");
int[] avatarColors = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF};
float[] avatarRadii = {avatarSize / 2f, avatarSize / 2f, avatarSize / 2f, avatarSize / 2f};

Initialization.getInstance().getManager().getRenderCore().getTexturePipeline()
.drawTexture(userAvatar, avatarX, avatarY, avatarSize, avatarSize,
0, 0, 1, 1, avatarColors, avatarRadii, 1f);

float logoSize = 35;
float logoY = centerY - 90;
Identifier logoTexture = Identifier.of("rich", "images/logo.png");

int[] logoColors = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF};
float[] logoRadii = {0, 0, 0, 0};

Initialization.getInstance().getManager().getRenderCore().getTexturePipeline()
.drawTexture(logoTexture, centerX - logoSize / 2f, logoY, logoSize, logoSize,
0, 0, 1, 1, logoColors, logoRadii, 1f);

String timeOfDay = getTimeOfDay();
String greeting = "Good " + timeOfDay + ", ";
String usernameColored = username;

float greetingWidth = Fonts.BOLD.getWidth(greeting, 14f);
float usernameWidth = Fonts.BOLD.getWidth(usernameColored, 14f);
float totalGreetingWidth = greetingWidth + usernameWidth;

float greetingStartX = centerX - totalGreetingWidth / 2f;
float greetingY = centerY - 38;

Fonts.BOLD.draw(greeting, greetingStartX, greetingY, 14f, new Color(255, 255, 255).getRGB());
Fonts.BOLD.draw(usernameColored, greetingStartX + greetingWidth, greetingY, 14f, new Color(100, 180, 255).getRGB());

String welcomeText = "Welcome to ";
String clientName = "RedDlc. The best client.";
String restText = "";

float welcomeWidth = Fonts.REGULARNEW.getWidth(welcomeText, 9f);
float clientWidth = Fonts.REGULARNEW.getWidth(clientName, 9f);
float restWidth = Fonts.REGULARNEW.getWidth(restText, 9f);
float totalWidth = welcomeWidth + clientWidth + restWidth;

float startX = centerX - totalWidth / 2f;
float textY = centerY - 20;

Fonts.REGULARNEW.draw(welcomeText, startX, textY, 9f, new Color(180, 180, 180).getRGB());
Fonts.REGULARNEW.draw(clientName, startX + welcomeWidth, textY, 9f, new Color(90, 22, 134).getRGB());
Fonts.REGULARNEW.draw(restText, startX + welcomeWidth + clientWidth, textY, 9f, new Color(180, 180, 180).getRGB());

float buttonWidth = 220;
float buttonHeight = 30;
float buttonSpacing = 7;
float buttonStartY = centerY + 3;

drawButton(centerX - buttonWidth / 2f, buttonStartY, buttonWidth, buttonHeight,
"Singleplayer", 0, mouseX, mouseY, new Color(30, 35, 45), false);

drawButton(centerX - buttonWidth / 2f, buttonStartY + buttonHeight + buttonSpacing, buttonWidth, buttonHeight,
"Multiplayer", 1, mouseX, mouseY, new Color(30, 35, 45), false);

float swapAccountsY = buttonStartY + (buttonHeight + buttonSpacing) * 2 + 5;
drawButton(centerX - buttonWidth / 2f, swapAccountsY, buttonWidth, buttonHeight,
"Swap Accounts", 2, mouseX, mouseY, new Color(90, 22, 134), true);

float bottomY = swapAccountsY + buttonHeight + 5;
float bottomButtonWidth = 65;
float bottomButtonHeight = 20;
float bottomSpacing = 10;

float totalBottomWidth = bottomButtonWidth * 3 + bottomSpacing * 2;
float bottomStartX = centerX - totalBottomWidth / 2f;

drawSmallButton(bottomStartX, bottomY, bottomButtonWidth, bottomButtonHeight,
"Options", 3, mouseX, mouseY);
drawSmallButton(bottomStartX + bottomButtonWidth + bottomSpacing, bottomY, bottomButtonWidth, bottomButtonHeight,
"Proxies", 4, mouseX, mouseY);
drawSmallButton(bottomStartX + (bottomButtonWidth + bottomSpacing) * 2, bottomY, bottomButtonWidth, bottomButtonHeight,
"Exit", 5, mouseX, mouseY);

String footerText = "By logging into your account, you agree to all of our policies,";
String policyLinks = "including our Privacy Policy and Terms of Service";

Fonts.SYSTEM.drawCentered(footerText, centerX, screenHeight - 17, 6.5f, new Color(100, 100, 100).getRGB());
Fonts.SYSTEM.drawCentered(policyLinks, centerX, screenHeight - 8, 6.5f, new Color(100, 100, 100).getRGB());
}

private String getTimeOfDay() {
int hour = java.time.LocalTime.now().getHour();
if (hour >= 5 && hour < 12) return "morning";
if (hour >= 12 && hour < 17) return "afternoon";
if (hour >= 17 && hour < 21) return "evening";
return "night";
}

private void drawButton(float x, float y, float width, float height, String text, int index,
float mouseX, float mouseY, Color baseColor, boolean isPurple) {
boolean hovered = isMouseOver(mouseX, mouseY, x, y, width, height);
float hoverProgress = buttonHoverProgress[index];

Color bgColor = baseColor;
if (isPurple) {
int brightness = (int) (hoverProgress * 20);
bgColor = new Color(
Math.min(255, baseColor.getRed() + brightness),
Math.min(255, baseColor.getGreen() + brightness),
Math.min(255, baseColor.getBlue() + brightness)
);
} else {
int brightness = (int) (hoverProgress * 15);
bgColor = new Color(
Math.min(255, baseColor.getRed() + brightness),
Math.min(255, baseColor.getGreen() + brightness),
Math.min(255, baseColor.getBlue() + brightness)
);
}

Render2D.rect(x, y, width, height, bgColor.getRGB(), 8);

if (!isPurple) {
Render2D.outline(x, y, width, height, 1f, new Color(50, 55, 65, 80).getRGB(), 8);
}

if (hoverProgress > 0.01f) {
int borderAlpha = (int) (hoverProgress * 100);
Color borderColor = isPurple
? new Color(138, 43, 226, borderAlpha)
: new Color(100, 110, 130, borderAlpha);
Render2D.outline(x, y, width, height, 1f, borderColor.getRGB(), 8);
}

float fontSize = 9f;

// ВЫБИРАЕМ ШРИФТ В ЗАВИСИМОСТИ ОТ КНОПКИ
rich.util.render.font.Font fontToUse;

// Индексы: 0 - Singleplayer, 1 - Multiplayer, 2 - Swap Accounts
if (index == 0 || index == 1) {
// Для Singleplayer и Multiplayer используем BOLD
fontToUse = Fonts.BOLD;
} else if (index == 2) {
// Для Swap Accounts используем REGULARNEW
fontToUse = Fonts.REGULARNEW;
} else {
// Для остальных кнопок (Options, Proxies, Exit) оставляем INTER
fontToUse = Fonts.INTER;
}

Color textColor;
if (isPurple) {
textColor = new Color(255, 255, 255);
} else {
textColor = new Color(220, 220, 220);
}

float textHeight = fontToUse.getHeight(fontSize);
float textWidth = fontToUse.getWidth(text, fontSize);
float textX = x + (width - textWidth) / 2f;
float textY = y + (height - textHeight) / 2f;
fontToUse.draw(text, textX, textY, fontSize, textColor.getRGB());
}

private void drawSmallButton(float x, float y, float width, float height, String text, int index,
float mouseX, float mouseY) {
float hoverProgress = buttonHoverProgress[index];
int baseAlpha = 220;
int hoverAlpha = (int) (baseAlpha + hoverProgress * 35);
float fontSize = 8f;

// Для маленьких кнопок используем INTER
float textHeight = Fonts.INTER.getHeight(fontSize);
float textWidth = Fonts.INTER.getWidth(text, fontSize);
float textX = x + (width - textWidth) / 2f;
float textY = y + (height - textHeight) / 2f;

Fonts.INTER.draw(text, textX, textY, fontSize, new Color(255, 255, 255, hoverAlpha).getRGB());
}

private boolean isMouseOver(float mouseX, float mouseY, float x, float y, float width, float height) {
return mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height;
}

private void updateButtonAnimations(float deltaTime, float mouseX, float mouseY, int screenWidth, int screenHeight) {
float centerX = screenWidth / 2f;
float centerY = screenHeight / 2f;
float lerpSpeed = 1f - (float) Math.pow(0.001f, deltaTime);

if (currentView == View.MAIN_MENU) {
float buttonWidth = 220;
float buttonHeight = 30;
float buttonSpacing = 7;
float buttonStartY = centerY + 3;

for (int i = 0; i < 2; i++) {
float y = buttonStartY + i * (buttonHeight + buttonSpacing);
boolean hovered = isMouseOver(mouseX, mouseY, centerX - buttonWidth / 2f, y, buttonWidth, buttonHeight);
float target = hovered ? 1f : 0f;
buttonHoverProgress = MathHelper.lerp(lerpSpeed, buttonHoverProgress, target);
}

float swapAccountsY = buttonStartY + (buttonHeight + buttonSpacing) * 2 + 5;
boolean swapHovered = isMouseOver(mouseX, mouseY, centerX - buttonWidth / 2f, swapAccountsY, buttonWidth, buttonHeight);
buttonHoverProgress[2] = MathHelper.lerp(lerpSpeed, buttonHoverProgress[2], swapHovered ? 1f : 0f);

float bottomY = swapAccountsY + buttonHeight + 5;
float bottomButtonWidth = 65;
float bottomButtonHeight = 20;
float bottomSpacing = 10;
float totalBottomWidth = bottomButtonWidth * 3 + bottomSpacing * 2;
float bottomStartX = centerX - totalBottomWidth / 2f;

for (int i = 0; i < 3; i++) {
float x = bottomStartX + i * (bottomButtonWidth + bottomSpacing);
boolean hovered = isMouseOver(mouseX, mouseY, x, bottomY, bottomButtonWidth, bottomButtonHeight);
float target = hovered ? 1f : 0f;
buttonHoverProgress[i + 3] = MathHelper.lerp(lerpSpeed, buttonHoverProgress[i + 3], target);
}
} else {
for (int i = 0; i < 6; i++) {
buttonHoverProgress = MathHelper.lerp(lerpSpeed, buttonHoverProgress, 0f);
}
}
}

private void renderAltScreen(int screenWidth, int screenHeight, float mouseX, float mouseY, long currentTime) {
float totalWidth = 405;
float totalHeight = 163;

float centerX = screenWidth / 2f;
float centerY = screenHeight / 2f;

float startX = centerX - totalWidth / 2f;
float startY = centerY - totalHeight / 2f;

float leftPanelX = startX;
float leftPanelTopY = startY;

accountRenderer.renderLeftPanelTop(leftPanelX, leftPanelTopY, 100, 100,
1f, nicknameText, nicknameFieldFocused, mouseX, mouseY, currentTime);

float leftPanelBottomY = startY + 100 + 5;
accountRenderer.renderLeftPanelBottom(leftPanelX, leftPanelBottomY, 100, 58,
1f, accountConfig.getActiveAccountName(), accountConfig.getActiveAccountDate(), accountConfig.getActiveAccountSkin());

float rightPanelX = startX + 100 + 5;
float rightPanelY = startY;

List<AccountEntry> sortedAccounts = accountConfig.getSortedAccounts();
accountRenderer.renderRightPanel(rightPanelX, rightPanelY, 300, 165,
1f, sortedAccounts, scrollOffset, mouseX, mouseY, 1f, (int) FIXED_GUI_SCALE);
}

@override
public boolean mouseClicked(Click click, boolean doubled) {
float scaledMouseX = toFixedCoord(click.x());
float scaledMouseY = toFixedCoord(click.y());

if (currentView == View.MAIN_MENU) {
if (click.button() == 0) {
int fixedWidth = getFixedScaledWidth();
int fixedHeight = getFixedScaledHeight();
float centerX = fixedWidth / 2f;
float centerY = fixedHeight / 2f;

float buttonWidth = 220;
float buttonHeight = 30;
float buttonSpacing = 7;
float buttonStartY = centerY + 3;

for (int i = 0; i < 2; i++) {
float y = buttonStartY + i * (buttonHeight + buttonSpacing);
if (isMouseOver(scaledMouseX, scaledMouseY, centerX - buttonWidth / 2f, y, buttonWidth, buttonHeight)) {
handleMainMenuButtonClick(i);
return true;
}
}

float swapAccountsY = buttonStartY + (buttonHeight + buttonSpacing) * 2 + 5;
if (isMouseOver(scaledMouseX, scaledMouseY, centerX - buttonWidth / 2f, swapAccountsY, buttonWidth, buttonHeight)) {
handleMainMenuButtonClick(2);
return true;
}

float bottomY = swapAccountsY + buttonHeight + 5;
float bottomButtonWidth = 65;
float bottomButtonHeight = 20;
float bottomSpacing = 10;
float totalBottomWidth = bottomButtonWidth * 3 + bottomSpacing * 2;
float bottomStartX = centerX - totalBottomWidth / 2f;

for (int i = 0; i < 3; i++) {
float x = bottomStartX + i * (bottomButtonWidth + bottomSpacing);
if (isMouseOver(scaledMouseX, scaledMouseY, x, bottomY, bottomButtonWidth, bottomButtonHeight)) {
handleMainMenuButtonClick(i + 3);
return true;
}
}
}
} else if (currentView == View.ALT_SCREEN) {
return handleAltScreenClick(scaledMouseX, scaledMouseY, click);
}

return super.mouseClicked(click, doubled);
}

private void handleMainMenuButtonClick(int index) {
switch (index) {
case 0 -> this.client.setScreen(new SelectWorldScreen(this));
case 1 -> {
Screen screen = this.client.options.skipMultiplayerWarning
? new MultiplayerScreen(this)
: new MultiplayerWarningScreen(this);
this.client.setScreen(screen);
}
case 2 -> currentView = View.ALT_SCREEN;
case 3 -> this.client.setScreen(new OptionsScreen(this, this.client.options));
case 4 -> {}
case 5 -> this.client.scheduleStop();
}
}

private boolean handleAltScreenClick(float mouseX, float mouseY, Click click) {
int screenWidth = getFixedScaledWidth();
int screenHeight = getFixedScaledHeight();

float totalWidth = 100 + 5 + 300;
float totalHeight = 100 + 5 + 58;

float centerX = screenWidth / 2f;
float centerY = screenHeight / 2f;

float startX = centerX - totalWidth / 2f;
float startY = centerY - totalHeight / 2f;

float leftPanelX = startX;
float leftPanelTopY = startY;

float fieldX = leftPanelX + 5;
float fieldY = leftPanelTopY + 38;
float fieldHeight = 14;
float addButtonSize = 14;
float buttonGap = 3;
float fieldWidth = 100 - 10 - addButtonSize - buttonGap;

if (accountRenderer.isMouseOver(mouseX, mouseY, fieldX, fieldY, fieldWidth, fieldHeight)) {
nicknameFieldFocused = true;
return true;
} else {
nicknameFieldFocused = false;
}

float addButtonX = fieldX + fieldWidth + buttonGap;
float addButtonY = fieldY;

if (accountRenderer.isMouseOver(mouseX, mouseY, addButtonX, addButtonY, addButtonSize, addButtonSize)) {
if (!nicknameText.isEmpty()) {
addAccount(nicknameText);
nicknameText = "";
}
return true;
}

float buttonWidth = 100 - 10;
float buttonHeight = 16;

float randomButtonX = leftPanelX + 5;
float randomButtonY = fieldY + fieldHeight + 6;

if (accountRenderer.isMouseOver(mouseX, mouseY, randomButtonX, randomButtonY, buttonWidth, buttonHeight)) {
String randomNick = generateRandomNickname();
addAccount(randomNick);
nicknameText = "";
return true;
}

float clearButtonX = leftPanelX + 5;
float clearButtonY = randomButtonY + buttonHeight + 5;

if (accountRenderer.isMouseOver(mouseX, mouseY, clearButtonX, clearButtonY, buttonWidth, buttonHeight)) {
accountConfig.clearAllAccounts();
targetScrollOffset = 0f;
scrollOffset = 0f;
return true;
}

float rightPanelX = startX + 100 + 5;
float rightPanelY = startY;

float accountListX = rightPanelX + 5;
float accountListY = rightPanelY + 26;
float accountListWidth = 300 - 10;
float accountListHeight = 165 - 31;

if (!accountRenderer.isMouseOver(mouseX, mouseY, accountListX, accountListY, accountListWidth, accountListHeight)) {
return false;
}

float cardWidth = (accountListWidth - 5) / 2f;
float cardHeight = 40;
float cardGap = 5;

List<AccountEntry> sortedAccounts = accountConfig.getSortedAccounts();

for (int i = 0; i < sortedAccounts.size(); i++) {
int col = i % 2;
int row = i / 2;

float cardX = accountListX + col * (cardWidth + cardGap);
float cardY = accountListY + row * (cardHeight + cardGap) - scrollOffset;

if (cardY + cardHeight < accountListY || cardY > accountListY + accountListHeight) {
continue;
}

float btnSize = 12;
float buttonYPos = cardY + cardHeight - btnSize - 5;
float pinButtonX = cardX + cardWidth - btnSize * 2 - 8;
float deleteButtonX = cardX + cardWidth - btnSize - 5;

if (accountRenderer.isMouseOver(mouseX, mouseY, pinButtonX, buttonYPos, btnSize, btnSize)) {
AccountEntry entry = sortedAccounts.get(i);
entry.togglePinned();
if (entry.isPinned()) {
setActiveAccount(entry);
}
accountConfig.save();
return true;
}

if (accountRenderer.isMouseOver(mouseX, mouseY, deleteButtonX, buttonYPos, btnSize, btnSize)) {
accountConfig.removeAccountByIndex(i);
return true;
}

if (accountRenderer.isMouseOver(mouseX, mouseY, cardX, cardY, cardWidth, cardHeight)) {
setActiveAccount(sortedAccounts.get(i));
return true;
}
}

return false;
}

@override
public boolean mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) {
if (currentView != View.ALT_SCREEN) return false;

float scaledMouseX = toFixedCoord(mouseX);
float scaledMouseY = toFixedCoord(mouseY);
int screenWidth = getFixedScaledWidth();
int screenHeight = getFixedScaledHeight();

float totalWidth = 100 + 5 + 300;
float totalHeight = 100 + 5 + 58;

float centerX = screenWidth / 2f;
float centerY = screenHeight / 2f;

float startX = centerX - totalWidth / 2f;
float startY = centerY - totalHeight / 2f;

float rightPanelX = startX + 100 + 5;
float rightPanelY = startY;

if (accountRenderer.isMouseOver(scaledMouseX, scaledMouseY, rightPanelX, rightPanelY, 300, 165)) {
float cardHeight = 40;
float cardGap = 5;
float accountListHeight = 165 - 31;
int rows = (int) Math.ceil(accountConfig.getSortedAccounts().size() / 2.0);
float maxScroll = Math.max(0, rows * (cardHeight + cardGap) - accountListHeight);

targetScrollOffset -= (float) verticalAmount * 25;
targetScrollOffset = MathHelper.clamp(targetScrollOffset, 0, maxScroll);

float scrollSpeed = 12f;
float deltaTime = 0.016f;
float scrollDiff = targetScrollOffset - scrollOffset;
scrollOffset += scrollDiff * Math.min(1f, deltaTime * scrollSpeed);

return true;
}

return super.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount);
}

@override
public boolean keyPressed(KeyInput input) {
if (currentView == View.ALT_SCREEN) {
if (nicknameFieldFocused) {
int keyCode = input.key();

if (keyCode == 259) {
if (!nicknameText.isEmpty()) {
nicknameText = nicknameText.substring(0, nicknameText.length() - 1);
}
return true;
}

if (keyCode == 256) {
nicknameFieldFocused = false;
return true;
}

if (keyCode == 257 || keyCode == 335) {
if (!nicknameText.isEmpty()) {
addAccount(nicknameText);
nicknameText = "";
}
nicknameFieldFocused = false;
return true;
}
}

if (input.key() == 256) {
currentView = View.MAIN_MENU;
accountConfig.save();
return true;
}
}

return super.keyPressed(input);
}

@override
public boolean charTyped(CharInput input) {
if (currentView == View.ALT_SCREEN && nicknameFieldFocused) {
int codepoint = input.codepoint();
if (Character.isLetterOrDigit(codepoint) || codepoint == '_') {
if (nicknameText.length() < 16) {
nicknameText += Character.toString(codepoint);
}
return true;
}
}
return super.charTyped(input);
}

private void setActiveAccount(AccountEntry account) {
accountConfig.setActiveAccount(account.getName(), account.getDate(), account.getSkin());
SessionChanger.changeUsername(account.getName());
}

private void addAccount(String nickname) {
LocalDateTime now = LocalDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm");
String date = now.format(formatter);

AccountEntry entry = new AccountEntry(nickname, date, null);
accountConfig.addAccount(entry);
setActiveAccount(entry);
SessionChanger.changeUsername(nickname);
}

private String generateRandomNickname() {
Random random = new Random();
StringBuilder username = new StringBuilder();
char[] vowels = {'a', 'e', 'i', 'o', 'u'};
char[] consonants = {'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z'};

String finalUsername = null;
int attempts = 0;
final int MAX_ATTEMPTS = 10;

List<AccountEntry> existingAccounts = accountConfig.getAccounts();

do {
username.setLength(0);
int length = 6 + random.nextInt(5);
boolean startWithVowel = random.nextBoolean();

for (int i = 0; i < length; i++) {
if (i % 2 == 0) {
username.append(startWithVowel ? vowels[random.nextInt(vowels.length)] : consonants[random.nextInt(consonants.length)]);
} else {
username.append(startWithVowel ? consonants[random.nextInt(consonants.length)] : vowels[random.nextInt(vowels.length)]);
}
}

if (random.nextInt(100) < 30) {
username.append(random.nextInt(100));
}

String tempUsername = username.substring(0, 1).toUpperCase() + username.substring(1);
attempts++;

boolean exists = false;
for (AccountEntry account : existingAccounts) {
if (account.getName().equalsIgnoreCase(tempUsername)) {
exists = true;
break;
}
}

if (!exists) {
finalUsername = tempUsername;
break;
}

} while (attempts < MAX_ATTEMPTS);

if (finalUsername == null) {
finalUsername = username.substring(0, 1).toUpperCase() + username.substring(1) + (System.currentTimeMillis() % 1000);
}

return finalUsername;
}

@override
public void renderBackground(DrawContext context, int mouseX, int mouseY, float delta) {
drawBackground();
}

@override
public boolean shouldCloseOnEsc() {
return false;
}

@override
public boolean shouldPause() {
return false;
}

private int withAlpha(int color, int alpha) {
return (color & 0x00FFFFFF) | (MathHelper.clamp(alpha, 0, 255) << 24);
}
} Вот тут шрифты все
 
package rich.screens.menu;

import net.minecraft.client.gui.Click;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen;
import net.minecraft.client.gui.screen.multiplayer.MultiplayerWarningScreen;
import net.minecraft.client.gui.screen.option.OptionsScreen;
import net.minecraft.client.gui.screen.world.SelectWorldScreen;
import net.minecraft.client.input.KeyInput;
import net.minecraft.client.input.CharInput;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import net.minecraft.util.Util;
import net.minecraft.util.math.MathHelper;
import rich.Initialization;
import rich.screens.account.AccountEntry;
import rich.screens.account.AccountRenderer;
import rich.util.config.impl.account.AccountConfig;
import rich.util.render.Render2D;
import rich.util.render.font.Fonts;
import rich.util.session.SessionChanger;
import rich.util.sounds.SoundManager;
import antidaunleak.api.UserProfile;

import java.awt.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Random;

public class MainMenuScreen extends Screen {

private static final Identifier BACKGROUND_TEXTURE = Identifier.of("rich", "textures/menu/backmenu.png");
private static final float FIXED_GUI_SCALE = 2.0f;
private static final int PARTICLE_COUNT = 50;
private static final float PARTICLE_FADE_THRESHOLD = 0.8f;

private static class Particle {
float x, y;
float vx, vy;
float size;
float alpha;
float lifetime;
float maxLifetime;
boolean isDead = false;

Particle(float x, float y) {
this.x = x;
this.y = y;
Random rand = new Random();
this.vx = (rand.nextFloat() - 0.5f) * 0.2f;
this.vy = (rand.nextFloat() - 0.5f) * 0.2f;
this.size = 0.5f + rand.nextFloat() * 1f;
this.alpha = 0.2f + rand.nextFloat() * 0.3f;
this.maxLifetime = 10f + rand.nextFloat() * 10f;
this.lifetime = 0f;
}

void update(float delta, int width, int height) {
lifetime += delta / 60f;

if (lifetime > maxLifetime * PARTICLE_FADE_THRESHOLD) {
float fadeProgress = (lifetime - maxLifetime * PARTICLE_FADE_THRESHOLD) / (maxLifetime * (1f - PARTICLE_FADE_THRESHOLD));
alpha = Math.max(0, alpha * (1f - fadeProgress));
}

if (lifetime >= maxLifetime) {
isDead = true;
return;
}

x += vx * delta;
y += vy * delta;

if (x < -10 || x > width + 10 || y < -10 || y > height + 10) {
isDead = true;
}
}
}

private final List<Particle> particles = new java.util.ArrayList<>();
private boolean particlesInitialized = false;
private int lastWindowWidth = 0;
private int lastWindowHeight = 0;

private enum View { MAIN_MENU, ALT_SCREEN }
private View currentView = View.MAIN_MENU;

private long screenStartTime = 0L;
private boolean initialized = false;
private long lastRenderTime = 0L;

private int hoveredButton = -1;
private float[] buttonHoverProgress = new float[6];

private final AccountRenderer accountRenderer;
private final AccountConfig accountConfig;
private String nicknameText = "";
private boolean nicknameFieldFocused = false;
private float scrollOffset = 0f;
private float targetScrollOffset = 0f;

public MainMenuScreen() {
super(Text.literal("Main Menu"));
for (int i = 0; i < 6; i++) {
buttonHoverProgress = 0f;
}
this.accountRenderer = new AccountRenderer();
this.accountConfig = AccountConfig.getInstance();
this.accountConfig.load();
}

@override
protected void init() {
initialized = false;
particlesInitialized = false;
}

private int getFixedScaledWidth() {
return (int) Math.ceil((double) client.getWindow().getFramebufferWidth() / FIXED_GUI_SCALE);
}

private int getFixedScaledHeight() {
return (int) Math.ceil((double) client.getWindow().getFramebufferHeight() / FIXED_GUI_SCALE);
}

private float toFixedCoord(double coord) {
float currentScale = (float) client.getWindow().getScaleFactor();
return (float) (coord * currentScale / FIXED_GUI_SCALE);
}

private void initParticles(int width, int height) {
if (particlesInitialized) return;
Random rand = new Random();
for (int i = 0; i < PARTICLE_COUNT; i++) {
particles.add(new Particle(rand.nextFloat() * width, rand.nextFloat() * height));
}
particlesInitialized = true;
}

private void drawBackground() {

int screenWidth = getFixedScaledWidth();
int screenHeight = getFixedScaledHeight();

Render2D.rect(0, 0, screenWidth, screenHeight, new Color(12, 15, 18).getRGB());

initParticles(screenWidth, screenHeight);

for (Particle p : particles) {
if (!p.isDead && p.alpha > 0.01f) {
int alpha = (int) (p.alpha * 255);
Render2D.rect(p.x, p.y, p.size, p.size, new Color(255, 255, 255, alpha).getRGB());
}
}
}

@override
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
long currentTime = Util.getMeasuringTimeMs();

if (!initialized) {

screenStartTime = currentTime;
lastRenderTime = currentTime;
initialized = true;
}

float deltaTime = Math.min(delta, 0.05f);

lastRenderTime = currentTime;

int fixedWidth = getFixedScaledWidth();
int fixedHeight = getFixedScaledHeight();

if (lastWindowWidth != fixedWidth || lastWindowHeight != fixedHeight) {

particles.clear();
particlesInitialized = false;

lastWindowWidth = fixedWidth;
lastWindowHeight = fixedHeight;
}

for (Particle p : particles) {
p.update(deltaTime * 60f, fixedWidth, fixedHeight);
}

particles.removeIf(p -> p.isDead);

Random rand = new Random();
while (particles.size() < PARTICLE_COUNT) {
particles.add(new Particle(rand.nextFloat() * fixedWidth, rand.nextFloat() * fixedHeight));
}


float scaledMouseX = toFixedCoord(mouseX);
float scaledMouseY = toFixedCoord(mouseY);

updateButtonAnimations(deltaTime, scaledMouseX, scaledMouseY, fixedWidth, fixedHeight);

Render2D.beginOverlay();

drawBackground();

if (currentView == View.MAIN_MENU) {
renderMainMenu(fixedWidth, fixedHeight, scaledMouseX, scaledMouseY);
} else {
renderAltScreen(fixedWidth, fixedHeight, scaledMouseX, scaledMouseY, currentTime);
}

Render2D.endOverlay();
}

private void renderMainMenu(int screenWidth, int screenHeight, float mouseX, float mouseY) {
float centerX = screenWidth / 2f;
float centerY = screenHeight / 2f;

String username = "user";

float avatarSize = 20;
float avatarX = 8;
float avatarY = 10;

Fonts.INTER.draw("Logged in as", avatarX + avatarSize + 5, avatarY, 7f, new Color(150, 150, 150).getRGB());
Fonts.INTER.draw(username, avatarX + avatarSize + 5, avatarY + 9, 8f, new Color(255, 255, 255).getRGB());

Render2D.rect(avatarX, avatarY, avatarSize, avatarSize, new Color(40, 45, 55).getRGB(), avatarSize / 2f);

Identifier userAvatar = Identifier.of("rich", "steve.png");
int[] avatarColors = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF};
float[] avatarRadii = {avatarSize / 2f, avatarSize / 2f, avatarSize / 2f, avatarSize / 2f};

Initialization.getInstance().getManager().getRenderCore().getTexturePipeline()
.drawTexture(userAvatar, avatarX, avatarY, avatarSize, avatarSize,
0, 0, 1, 1, avatarColors, avatarRadii, 1f);

float logoSize = 35;
float logoY = centerY - 90;
Identifier logoTexture = Identifier.of("rich", "images/logo.png");

int[] logoColors = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF};
float[] logoRadii = {0, 0, 0, 0};

Initialization.getInstance().getManager().getRenderCore().getTexturePipeline()
.drawTexture(logoTexture, centerX - logoSize / 2f, logoY, logoSize, logoSize,
0, 0, 1, 1, logoColors, logoRadii, 1f);

String timeOfDay = getTimeOfDay();
String greeting = "Good " + timeOfDay + ", ";
String usernameColored = username;

float greetingWidth = Fonts.BOLD.getWidth(greeting, 14f);
float usernameWidth = Fonts.BOLD.getWidth(usernameColored, 14f);

float totalGreetingWidth = greetingWidth + usernameWidth;

float greetingStartX = centerX - totalGreetingWidth / 2f;
float greetingY = centerY - 38;

Fonts.BOLD.draw(greeting, greetingStartX, greetingY, 14f, new Color(255, 255, 255).getRGB());
Fonts.BOLD.draw(usernameColored, greetingStartX + greetingWidth, greetingY, 14f, new Color(100, 180, 255).getRGB());

String welcomeText = "Welcome to ";
String clientName = "RedDlc. The best client.";
String restText = "";

float welcomeWidth = Fonts.REGULARNEW.getWidth(welcomeText, 9f);
float clientWidth = Fonts.REGULARNEW.getWidth(clientName, 9f);
float restWidth = Fonts.REGULARNEW.getWidth(restText, 9f);

float totalWidth = welcomeWidth + clientWidth + restWidth;

float startX = centerX - totalWidth / 2f;
float textY = centerY - 20;

Fonts.REGULARNEW.draw(welcomeText, startX, textY, 9f, new Color(180, 180, 180).getRGB());
Fonts.REGULARNEW.draw(clientName, startX + welcomeWidth, textY, 9f, new Color(90, 22, 134).getRGB());
Fonts.REGULARNEW.draw(restText, startX + welcomeWidth + clientWidth, textY, 9f, new Color(180, 180, 180).getRGB());

float buttonWidth = 220;
float buttonHeight = 30;
float buttonSpacing = 7;
float buttonStartY = centerY + 3;

drawButton(centerX - buttonWidth / 2f, buttonStartY, buttonWidth, buttonHeight,
"Singleplayer", 0, mouseX, mouseY, new Color(30, 35, 45), false);

drawButton(centerX - buttonWidth / 2f, buttonStartY + buttonHeight + buttonSpacing, buttonWidth, buttonHeight,
"Multiplayer", 1, mouseX, mouseY, new Color(30, 35, 45), false);

float swapAccountsY = buttonStartY + (buttonHeight + buttonSpacing) * 2 + 5;
drawButton(centerX - buttonWidth / 2f, swapAccountsY, buttonWidth, buttonHeight,
"Swap Accounts", 2, mouseX, mouseY, new Color(90, 22, 134), true);

float bottomY = swapAccountsY + buttonHeight + 5;
float bottomButtonWidth = 65;
float bottomButtonHeight = 20;
float bottomSpacing = 10;

float totalBottomWidth = bottomButtonWidth * 3 + bottomSpacing * 2;
float bottomStartX = centerX - totalBottomWidth / 2f;

drawSmallButton(bottomStartX, bottomY, bottomButtonWidth, bottomButtonHeight,
"Options", 3, mouseX, mouseY);
drawSmallButton(bottomStartX + bottomButtonWidth + bottomSpacing, bottomY, bottomButtonWidth, bottomButtonHeight,
"Proxies", 4, mouseX, mouseY);
drawSmallButton(bottomStartX + (bottomButtonWidth + bottomSpacing) * 2, bottomY, bottomButtonWidth, bottomButtonHeight,
"Exit", 5, mouseX, mouseY);

String footerText = "By logging into your account, you agree to all of our policies,";
String policyLinks = "including our Privacy Policy and Terms of Service";

Fonts.SYSTEM.drawCentered(footerText, centerX, screenHeight - 17, 6.5f, new Color(100, 100, 100).getRGB());
Fonts.SYSTEM.drawCentered(policyLinks, centerX, screenHeight - 8, 6.5f, new Color(100, 100, 100).getRGB());
}

private String getTimeOfDay() {
int hour = java.time.LocalTime.now().getHour();
if (hour >= 5 && hour < 12) return "morning";
if (hour >= 12 && hour < 17) return "afternoon";
if (hour >= 17 && hour < 21) return "evening";
return "night";
}

private void drawButton(float x, float y, float width, float height, String text, int index,
float mouseX, float mouseY, Color baseColor, boolean isPurple) {

boolean hovered = isMouseOver(mouseX, mouseY, x, y, width, height);
float hoverProgress = buttonHoverProgress[index];

Color bgColor = baseColor;

if (isPurple) {
int brightness = (int) (hoverProgress * 20);
bgColor = new Color(
Math.min(255, baseColor.getRed() + brightness),
Math.min(255, baseColor.getGreen() + brightness),
Math.min(255, baseColor.getBlue() + brightness)
);
} else {
int brightness = (int) (hoverProgress * 15);
bgColor = new Color(
Math.min(255, baseColor.getRed() + brightness),
Math.min(255, baseColor.getGreen() + brightness),
Math.min(255, baseColor.getBlue() + brightness)
);
}

Render2D.rect(x, y, width, height, bgColor.getRGB(), 8);


if (!isPurple) {
Render2D.outline(x, y, width, height, 1f, new Color(50, 55, 65, 80).getRGB(), 8);
}

if (hoverProgress > 0.01f) {
int borderAlpha = (int) (hoverProgress * 100);
Color borderColor = isPurple
? new Color(138, 43, 226, borderAlpha)
: new Color(100, 110, 130, borderAlpha);
Render2D.outline(x, y, width, height, 1f, borderColor.getRGB(), 8);
}

float fontSize = 9f;

// ВЫБИРАЕМ ШРИФТ В ЗАВИСИМОСТИ ОТ КНОПКИ
rich.util.render.font.Font fontToUse;

// Индексы: 0 - Singleplayer, 1 - Multiplayer, 2 - Swap Accounts
if (index == 0 || index == 1) {
// Для Singleplayer и Multiplayer используем BOLD
fontToUse = Fonts.BOLD;
} else if (index == 2) {
// Для Swap Accounts используем REGULARNEW
fontToUse = Fonts.REGULARNEW;
} else {
// Для остальных кнопок (Options, Proxies, Exit) оставляем INTER
fontToUse = Fonts.INTER;
}

Color textColor;

if (isPurple) {
textColor = new Color(255, 255, 255);
} else {
textColor = new Color(220, 220, 220);
}


float textHeight = fontToUse.getHeight(fontSize);
float textWidth = fontToUse.getWidth(text, fontSize);
float textX = x + (width - textWidth) / 2f;
float textY = y + (height - textHeight) / 2f;
fontToUse.draw(text, textX, textY, fontSize, textColor.getRGB());
}

private void drawSmallButton(float x, float y, float width, float height, String text, int index,
float mouseX, float mouseY) {
float hoverProgress = buttonHoverProgress[index];
int baseAlpha = 220;
int hoverAlpha = (int) (baseAlpha + hoverProgress * 35);
float fontSize = 8f;

// Для маленьких кнопок используем INTER
float textHeight = Fonts.INTER.getHeight(fontSize);
float textWidth = Fonts.INTER.getWidth(text, fontSize);
float textX = x + (width - textWidth) / 2f;
float textY = y + (height - textHeight) / 2f;

Fonts.INTER.draw(text, textX, textY, fontSize, new Color(255, 255, 255, hoverAlpha).getRGB());
}

private boolean isMouseOver(float mouseX, float mouseY, float x, float y, float width, float height) {

return mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height;
}

private void updateButtonAnimations(float deltaTime, float mouseX, float mouseY, int screenWidth, int screenHeight) {
float centerX = screenWidth / 2f;
float centerY = screenHeight / 2f;
float lerpSpeed = 1f - (float) Math.pow(0.001f, deltaTime);

if (currentView == View.MAIN_MENU) {
float buttonWidth = 220;
float buttonHeight = 30;
float buttonSpacing = 7;
float buttonStartY = centerY + 3;

for (int i = 0; i < 2; i++) {

float y = buttonStartY + i * (buttonHeight + buttonSpacing);
boolean hovered = isMouseOver(mouseX, mouseY, centerX - buttonWidth / 2f, y, buttonWidth, buttonHeight);
float target = hovered ? 1f : 0f;
buttonHoverProgress = MathHelper.lerp(lerpSpeed, buttonHoverProgress, target);
}

float swapAccountsY = buttonStartY + (buttonHeight + buttonSpacing) * 2 + 5;
boolean swapHovered = isMouseOver(mouseX, mouseY, centerX - buttonWidth / 2f, swapAccountsY, buttonWidth, buttonHeight);
buttonHoverProgress[2] = MathHelper.lerp(lerpSpeed, buttonHoverProgress[2], swapHovered ? 1f : 0f);

float bottomY = swapAccountsY + buttonHeight + 5;
float bottomButtonWidth = 65;
float bottomButtonHeight = 20;
float bottomSpacing = 10;
float totalBottomWidth = bottomButtonWidth * 3 + bottomSpacing * 2;
float bottomStartX = centerX - totalBottomWidth / 2f;

for (int i = 0; i < 3; i++) {

float x = bottomStartX + i * (bottomButtonWidth + bottomSpacing);
boolean hovered = isMouseOver(mouseX, mouseY, x, bottomY, bottomButtonWidth, bottomButtonHeight);
float target = hovered ? 1f : 0f;
buttonHoverProgress[i + 3] = MathHelper.lerp(lerpSpeed, buttonHoverProgress[i + 3], target);
}
} else {
for (int i = 0; i < 6; i++) {
buttonHoverProgress = MathHelper.lerp(lerpSpeed, buttonHoverProgress, 0f);
}
}
}

private void renderAltScreen(int screenWidth, int screenHeight, float mouseX, float mouseY, long currentTime) {
float totalWidth = 405;
float totalHeight = 163;

float centerX = screenWidth / 2f;
float centerY = screenHeight / 2f;

float startX = centerX - totalWidth / 2f;
float startY = centerY - totalHeight / 2f;


float leftPanelX = startX;
float leftPanelTopY = startY;

accountRenderer.renderLeftPanelTop(leftPanelX, leftPanelTopY, 100, 100,
1f, nicknameText, nicknameFieldFocused, mouseX, mouseY, currentTime);

float leftPanelBottomY = startY + 100 + 5;
accountRenderer.renderLeftPanelBottom(leftPanelX, leftPanelBottomY, 100, 58,
1f, accountConfig.getActiveAccountName(), accountConfig.getActiveAccountDate(), accountConfig.getActiveAccountSkin());

float rightPanelX = startX + 100 + 5;

float rightPanelY = startY;

List<AccountEntry> sortedAccounts = accountConfig.getSortedAccounts();
accountRenderer.renderRightPanel(rightPanelX, rightPanelY, 300, 165,
1f, sortedAccounts, scrollOffset, mouseX, mouseY, 1f, (int) FIXED_GUI_SCALE);
}

@override
public boolean mouseClicked(Click click, boolean doubled) {

float scaledMouseX = toFixedCoord(click.x());
float scaledMouseY = toFixedCoord(click.y());

if (currentView == View.MAIN_MENU) {
if (click.button() == 0) {

int fixedWidth = getFixedScaledWidth();
int fixedHeight = getFixedScaledHeight();
float centerX = fixedWidth / 2f;
float centerY = fixedHeight / 2f;

float buttonWidth = 220;
float buttonHeight = 30;
float buttonSpacing = 7;
float buttonStartY = centerY + 3;

for (int i = 0; i < 2; i++) {

float y = buttonStartY + i * (buttonHeight + buttonSpacing);
if (isMouseOver(scaledMouseX, scaledMouseY, centerX - buttonWidth / 2f, y, buttonWidth, buttonHeight)) {
handleMainMenuButtonClick(i);

return true;
}
}

float swapAccountsY = buttonStartY + (buttonHeight + buttonSpacing) * 2 + 5;
if (isMouseOver(scaledMouseX, scaledMouseY, centerX - buttonWidth / 2f, swapAccountsY, buttonWidth, buttonHeight)) {
handleMainMenuButtonClick(2);

return true;
}

float bottomY = swapAccountsY + buttonHeight + 5;
float bottomButtonWidth = 65;
float bottomButtonHeight = 20;
float bottomSpacing = 10;
float totalBottomWidth = bottomButtonWidth * 3 + bottomSpacing * 2;
float bottomStartX = centerX - totalBottomWidth / 2f;

for (int i = 0; i < 3; i++) {

float x = bottomStartX + i * (bottomButtonWidth + bottomSpacing);
if (isMouseOver(scaledMouseX, scaledMouseY, x, bottomY, bottomButtonWidth, bottomButtonHeight)) {
handleMainMenuButtonClick(i + 3);

return true;
}
}
}
} else if (currentView == View.ALT_SCREEN) {

return handleAltScreenClick(scaledMouseX, scaledMouseY, click);
}


return super.mouseClicked(click, doubled);
}

private void handleMainMenuButtonClick(int index) {

switch (index) {
case 0 -> this.client.setScreen(new SelectWorldScreen(this));
case 1 -> {
Screen screen = this.client.options.skipMultiplayerWarning
? new MultiplayerScreen(this)
: new MultiplayerWarningScreen(this);
this.client.setScreen(screen);
}
case 2 -> currentView = View.ALT_SCREEN;
case 3 -> this.client.setScreen(new OptionsScreen(this, this.client.options));
case 4 -> {}
case 5 -> this.client.scheduleStop();
}
}

private boolean handleAltScreenClick(float mouseX, float mouseY, Click click) {

int screenWidth = getFixedScaledWidth();
int screenHeight = getFixedScaledHeight();

float totalWidth = 100 + 5 + 300;
float totalHeight = 100 + 5 + 58;

float centerX = screenWidth / 2f;
float centerY = screenHeight / 2f;

float startX = centerX - totalWidth / 2f;
float startY = centerY - totalHeight / 2f;


float leftPanelX = startX;
float leftPanelTopY = startY;

float fieldX = leftPanelX + 5;
float fieldY = leftPanelTopY + 38;
float fieldHeight = 14;
float addButtonSize = 14;
float buttonGap = 3;
float fieldWidth = 100 - 10 - addButtonSize - buttonGap;

if (accountRenderer.isMouseOver(mouseX, mouseY, fieldX, fieldY, fieldWidth, fieldHeight)) {
nicknameFieldFocused = true;

return true;
} else {
nicknameFieldFocused = false;
}


float addButtonX = fieldX + fieldWidth + buttonGap;
float addButtonY = fieldY;

if (accountRenderer.isMouseOver(mouseX, mouseY, addButtonX, addButtonY, addButtonSize, addButtonSize)) {
if (!nicknameText.isEmpty()) {
addAccount(nicknameText);
nicknameText = "";
}

return true;
}

float buttonWidth = 100 - 10;
float buttonHeight = 16;

float randomButtonX = leftPanelX + 5;
float randomButtonY = fieldY + fieldHeight + 6;

if (accountRenderer.isMouseOver(mouseX, mouseY, randomButtonX, randomButtonY, buttonWidth, buttonHeight)) {
String randomNick = generateRandomNickname();
addAccount(randomNick);
nicknameText = "";

return true;
}

float clearButtonX = leftPanelX + 5;
float clearButtonY = randomButtonY + buttonHeight + 5;

if (accountRenderer.isMouseOver(mouseX, mouseY, clearButtonX, clearButtonY, buttonWidth, buttonHeight)) {

accountConfig.clearAllAccounts();
targetScrollOffset = 0f;
scrollOffset = 0f;

return true;
}

float rightPanelX = startX + 100 + 5;

float rightPanelY = startY;

float accountListX = rightPanelX + 5;
float accountListY = rightPanelY + 26;
float accountListWidth = 300 - 10;
float accountListHeight = 165 - 31;

if (!accountRenderer.isMouseOver(mouseX, mouseY, accountListX, accountListY, accountListWidth, accountListHeight)) {

return false;
}

float cardWidth = (accountListWidth - 5) / 2f;
float cardHeight = 40;
float cardGap = 5;

List<AccountEntry> sortedAccounts = accountConfig.getSortedAccounts();

for (int i = 0; i < sortedAccounts.size(); i++) {
int col = i % 2;
int row = i / 2;


float cardX = accountListX + col * (cardWidth + cardGap);
float cardY = accountListY + row * (cardHeight + cardGap) - scrollOffset;


if (cardY + cardHeight < accountListY || cardY > accountListY + accountListHeight) {
continue;
}

float btnSize = 12;
float buttonYPos = cardY + cardHeight - btnSize - 5;
float pinButtonX = cardX + cardWidth - btnSize * 2 - 8;
float deleteButtonX = cardX + cardWidth - btnSize - 5;

if (accountRenderer.isMouseOver(mouseX, mouseY, pinButtonX, buttonYPos, btnSize, btnSize)) {
AccountEntry entry = sortedAccounts.get(i);
entry.togglePinned();

if (entry.isPinned()) {
setActiveAccount(entry);
}

accountConfig.save();
return true;
}

if (accountRenderer.isMouseOver(mouseX, mouseY, deleteButtonX, buttonYPos, btnSize, btnSize)) {

accountConfig.removeAccountByIndex(i);
return true;
}

if (accountRenderer.isMouseOver(mouseX, mouseY, cardX, cardY, cardWidth, cardHeight)) {
setActiveAccount(sortedAccounts.get(i));

return true;
}
}


return false;
}

@override
public boolean mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) {
if (currentView != View.ALT_SCREEN) return false;


float scaledMouseX = toFixedCoord(mouseX);
float scaledMouseY = toFixedCoord(mouseY);
int screenWidth = getFixedScaledWidth();
int screenHeight = getFixedScaledHeight();

float totalWidth = 100 + 5 + 300;
float totalHeight = 100 + 5 + 58;

float centerX = screenWidth / 2f;
float centerY = screenHeight / 2f;

float startX = centerX - totalWidth / 2f;
float startY = centerY - totalHeight / 2f;

float rightPanelX = startX + 100 + 5;

float rightPanelY = startY;

if (accountRenderer.isMouseOver(scaledMouseX, scaledMouseY, rightPanelX, rightPanelY, 300, 165)) {
float cardHeight = 40;
float cardGap = 5;
float accountListHeight = 165 - 31;
int rows = (int) Math.ceil(accountConfig.getSortedAccounts().size() / 2.0);
float maxScroll = Math.max(0, rows * (cardHeight + cardGap) - accountListHeight);

targetScrollOffset -= (float) verticalAmount * 25;
targetScrollOffset = MathHelper.clamp(targetScrollOffset, 0, maxScroll);

float scrollSpeed = 12f;
float deltaTime = 0.016f;
float scrollDiff = targetScrollOffset - scrollOffset;
scrollOffset += scrollDiff * Math.min(1f, deltaTime * scrollSpeed);


return true;
}


return super.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount);
}

@override
public boolean keyPressed(KeyInput input) {
if (currentView == View.ALT_SCREEN) {
if (nicknameFieldFocused) {

int keyCode = input.key();

if (keyCode == 259) {
if (!nicknameText.isEmpty()) {
nicknameText = nicknameText.substring(0, nicknameText.length() - 1);
}

return true;
}

if (keyCode == 256) {
nicknameFieldFocused = false;

return true;
}

if (keyCode == 257 || keyCode == 335) {
if (!nicknameText.isEmpty()) {
addAccount(nicknameText);
nicknameText = "";
}
nicknameFieldFocused = false;

return true;
}
}

if (input.key() == 256) {
currentView = View.MAIN_MENU;

accountConfig.save();
return true;
}
}


return super.keyPressed(input);
}

@override
public boolean charTyped(CharInput input) {
if (currentView == View.ALT_SCREEN && nicknameFieldFocused) {

int codepoint = input.codepoint();
if (Character.isLetterOrDigit(codepoint) || codepoint == '_') {
if (nicknameText.length() < 16) {
nicknameText += Character.toString(codepoint);
}

return true;
}
}

return super.charTyped(input);
}

private void setActiveAccount(AccountEntry account) {

accountConfig.setActiveAccount(account.getName(), account.getDate(), account.getSkin());
SessionChanger.changeUsername(account.getName());
}

private void addAccount(String nickname) {
LocalDateTime now = LocalDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm");
String date = now.format(formatter);

AccountEntry entry = new AccountEntry(nickname, date, null);

accountConfig.addAccount(entry);
setActiveAccount(entry);
SessionChanger.changeUsername(nickname);
}

private String generateRandomNickname() {
Random random = new Random();
StringBuilder username = new StringBuilder();
char[] vowels = {'a', 'e', 'i', 'o', 'u'};
char[] consonants = {'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z'};

String finalUsername = null;
int attempts = 0;
final int MAX_ATTEMPTS = 10;

List<AccountEntry> existingAccounts = accountConfig.getAccounts();


do {
username.setLength(0);
int length = 6 + random.nextInt(5);

boolean startWithVowel = random.nextBoolean();

for (int i = 0; i < length; i++) {
if (i % 2 == 0) {
username.append(startWithVowel ? vowels[random.nextInt(vowels.length)] : consonants[random.nextInt(consonants.length)]);
} else {
username.append(startWithVowel ? consonants[random.nextInt(consonants.length)] : vowels[random.nextInt(vowels.length)]);
}
}

if (random.nextInt(100) < 30) {
username.append(random.nextInt(100));
}

String tempUsername = username.substring(0, 1).toUpperCase() + username.substring(1);
attempts++;

boolean exists = false;

for (AccountEntry account : existingAccounts) {
if (account.getName().equalsIgnoreCase(tempUsername)) {
exists = true;

break;
}
}


if (!exists) {
finalUsername = tempUsername;

break;
}

} while (attempts < MAX_ATTEMPTS);

if (finalUsername == null) {
finalUsername = username.substring(0, 1).toUpperCase() + username.substring(1) + (System.currentTimeMillis() % 1000);
}


return finalUsername;
}

@override
public void renderBackground(DrawContext context, int mouseX, int mouseY, float delta) {
drawBackground();
}

@override
public boolean shouldCloseOnEsc() {

return false;
}

@override
public boolean shouldPause() {

return false;
}

private int withAlpha(int color, int alpha) {
return (color & 0x00FFFFFF) | (MathHelper.clamp(alpha, 0, 255) << 24);
}
} Вот тут шрифты все
17:03:25: Executing ':net.fabricmc.devlaunchinjector.Main.main()'…


> Configure project :
Fabric Loom: 1.15.3

> Task :compileJava FAILED

[Incubating] Problems report is available at: file:///C:/Users/Mykola/Downloads/Rich-Modern/build/reports/problems/problems-report.html

Deprecated Gradle features were used in this build, making it incompatible with Gradle 10.

You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.

For more on this, please refer to
Пожалуйста, авторизуйтесь для просмотра ссылки.
in the Gradle documentation.
1 actionable task: 1 executed
C:\Users\Mykola\Downloads\Rich-Modern\src\main\java\rich\screens\menu\MainMenuScreen.java:107: error: incompatible types: float cannot be converted to float[]
buttonHoverProgress = 0f;
^
C:\Users\Mykola\Downloads\Rich-Modern\src\main\java\rich\screens\menu\MainMenuScreen.java:307: error: cannot find symbol
Fonts.SYSTEM.drawCentered(footerText, centerX, screenHeight - 17, 6.5f, new Color(100, 100, 100).getRGB());
^
symbol: variable SYSTEM
location: class Fonts
C:\Users\Mykola\Downloads\Rich-Modern\src\main\java\rich\screens\menu\MainMenuScreen.java:308: error: cannot find symbol
Fonts.SYSTEM.drawCentered(policyLinks, centerX, screenHeight - 8, 6.5f, new Color(100, 100, 100).getRGB());
^
symbol: variable SYSTEM
location: class Fonts
C:\Users\Mykola\Downloads\Rich-Modern\src\main\java\rich\screens\menu\MainMenuScreen.java:421: error: no suitable method found for lerp(float,float[],float)
buttonHoverProgress = MathHelper.lerp(lerpSpeed, buttonHoverProgress, target);
^
method MathHelper.lerp(float,int,int) is not applicable
(argument mismatch; float[] cannot be converted to int)
method MathHelper.lerp(float,float,float) is not applicable
(argument mismatch; float[] cannot be converted to float)
method MathHelper.lerp(double,Vec3d,Vec3d) is not applicable
(argument mismatch; float[] cannot be converted to Vec3d)
method MathHelper.lerp(double,double,double) is not applicable
(argument mismatch; float[] cannot be converted to double)
C:\Users\Mykola\Downloads\Rich-Modern\src\main\java\rich\screens\menu\MainMenuScreen.java:443: error: no suitable method found for lerp(float,float[],float)
buttonHoverProgress = MathHelper.lerp(lerpSpeed, buttonHoverProgress, 0f);
^
method MathHelper.lerp(float,int,int) is not applicable
(argument mismatch; float[] cannot be converted to int)
method MathHelper.lerp(float,float,float) is not applicable
(argument mismatch; float[] cannot be converted to float)
method MathHelper.lerp(double,Vec3d,Vec3d) is not applicable
(argument mismatch; float[] cannot be converted to Vec3d)
method MathHelper.lerp(double,double,double) is not applicable
(argument mismatch; float[] cannot be converted to double)
5 errors

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':compileJava'.
> Compilation failed; see the compiler output below.
C:\Users\Mykola\Downloads\Rich-Modern\src\main\java\rich\screens\menu\MainMenuScreen.java:421: error: no suitable method found for lerp(float,float[],float)
buttonHoverProgress = MathHelper.lerp(lerpSpeed, buttonHoverProgress, target);
^
method MathHelper.lerp(float,int,int) is not applicable
(argument mismatch; float[] cannot be converted to int)
method MathHelper.lerp(float,float,float) is not applicable
(argument mismatch; float[] cannot be converted to float)
method MathHelper.lerp(double,Vec3d,Vec3d) is not applicable
(argument mismatch; float[] cannot be converted to Vec3d)
method MathHelper.lerp(double,double,double) is not applicable
(argument mismatch; float[] cannot be converted to double)
C:\Users\Mykola\Downloads\Rich-Modern\src\main\java\rich\screens\menu\MainMenuScreen.java:443: error: no suitable method found for lerp(float,float[],float)
buttonHoverProgress = MathHelper.lerp(lerpSpeed, buttonHoverProgress, 0f);
^
method MathHelper.lerp(float,int,int) is not applicable
(argument mismatch; float[] cannot be converted to int)
method MathHelper.lerp(float,float,float) is not applicable
(argument mismatch; float[] cannot be converted to float)
method MathHelper.lerp(double,Vec3d,Vec3d) is not applicable
(argument mismatch; float[] cannot be converted to Vec3d)
method MathHelper.lerp(double,double,double) is not applicable
(argument mismatch; float[] cannot be converted to double)
C:\Users\Mykola\Downloads\Rich-Modern\src\main\java\rich\screens\menu\MainMenuScreen.java:107: error: incompatible types: float cannot be converted to float[]
buttonHoverProgress = 0f;
^
C:\Users\Mykola\Downloads\Rich-Modern\src\main\java\rich\screens\menu\MainMenuScreen.java:307: error: cannot find symbol
Fonts.SYSTEM.drawCentered(footerText, centerX, screenHeight - 17, 6.5f, new Color(100, 100, 100).getRGB());
^
symbol: variable SYSTEM
location: class Fonts
C:\Users\Mykola\Downloads\Rich-Modern\src\main\java\rich\screens\menu\MainMenuScreen.java:308: error: cannot find symbol
Fonts.SYSTEM.drawCentered(policyLinks, centerX, screenHeight - 8, 6.5f, new Color(100, 100, 100).getRGB());
^
symbol: variable SYSTEM
location: class Fonts
5 errors

* Try:
> Check your code and dependencies to fix the compilation error(s)
> Run with --scan to generate a Build Scan (powered by Develocity).

BUILD FAILED in 1s
17:03:27: Execution finished ':net.fabricmc.devlaunchinjector.Main.main()'.
 
17:03:25: Executing ':net.fabricmc.devlaunchinjector.Main.main()'…


> Configure project :
Fabric Loom: 1.15.3

> Task :compileJava FAILED

[Incubating] Problems report is available at: file:///C:/Users/Mykola/Downloads/Rich-Modern/build/reports/problems/problems-report.html

Deprecated Gradle features were used in this build, making it incompatible with Gradle 10.

You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.

For more on this, please refer to
Пожалуйста, авторизуйтесь для просмотра ссылки.
in the Gradle documentation.
1 actionable task: 1 executed
C:\Users\Mykola\Downloads\Rich-Modern\src\main\java\rich\screens\menu\MainMenuScreen.java:107: error: incompatible types: float cannot be converted to float[]
buttonHoverProgress = 0f;
^
C:\Users\Mykola\Downloads\Rich-Modern\src\main\java\rich\screens\menu\MainMenuScreen.java:307: error: cannot find symbol
Fonts.SYSTEM.drawCentered(footerText, centerX, screenHeight - 17, 6.5f, new Color(100, 100, 100).getRGB());
^
symbol: variable SYSTEM
location: class Fonts
C:\Users\Mykola\Downloads\Rich-Modern\src\main\java\rich\screens\menu\MainMenuScreen.java:308: error: cannot find symbol
Fonts.SYSTEM.drawCentered(policyLinks, centerX, screenHeight - 8, 6.5f, new Color(100, 100, 100).getRGB());
^
symbol: variable SYSTEM
location: class Fonts
C:\Users\Mykola\Downloads\Rich-Modern\src\main\java\rich\screens\menu\MainMenuScreen.java:421: error: no suitable method found for lerp(float,float[],float)
buttonHoverProgress = MathHelper.lerp(lerpSpeed, buttonHoverProgress, target);
^
method MathHelper.lerp(float,int,int) is not applicable
(argument mismatch; float[] cannot be converted to int)
method MathHelper.lerp(float,float,float) is not applicable
(argument mismatch; float[] cannot be converted to float)
method MathHelper.lerp(double,Vec3d,Vec3d) is not applicable
(argument mismatch; float[] cannot be converted to Vec3d)
method MathHelper.lerp(double,double,double) is not applicable
(argument mismatch; float[] cannot be converted to double)
C:\Users\Mykola\Downloads\Rich-Modern\src\main\java\rich\screens\menu\MainMenuScreen.java:443: error: no suitable method found for lerp(float,float[],float)
buttonHoverProgress = MathHelper.lerp(lerpSpeed, buttonHoverProgress, 0f);
^
method MathHelper.lerp(float,int,int) is not applicable
(argument mismatch; float[] cannot be converted to int)
method MathHelper.lerp(float,float,float) is not applicable
(argument mismatch; float[] cannot be converted to float)
method MathHelper.lerp(double,Vec3d,Vec3d) is not applicable
(argument mismatch; float[] cannot be converted to Vec3d)
method MathHelper.lerp(double,double,double) is not applicable
(argument mismatch; float[] cannot be converted to double)
5 errors

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':compileJava'.
> Compilation failed; see the compiler output below.
C:\Users\Mykola\Downloads\Rich-Modern\src\main\java\rich\screens\menu\MainMenuScreen.java:421: error: no suitable method found for lerp(float,float[],float)
buttonHoverProgress = MathHelper.lerp(lerpSpeed, buttonHoverProgress, target);
^
method MathHelper.lerp(float,int,int) is not applicable
(argument mismatch; float[] cannot be converted to int)
method MathHelper.lerp(float,float,float) is not applicable
(argument mismatch; float[] cannot be converted to float)
method MathHelper.lerp(double,Vec3d,Vec3d) is not applicable
(argument mismatch; float[] cannot be converted to Vec3d)
method MathHelper.lerp(double,double,double) is not applicable
(argument mismatch; float[] cannot be converted to double)
C:\Users\Mykola\Downloads\Rich-Modern\src\main\java\rich\screens\menu\MainMenuScreen.java:443: error: no suitable method found for lerp(float,float[],float)
buttonHoverProgress = MathHelper.lerp(lerpSpeed, buttonHoverProgress, 0f);
^
method MathHelper.lerp(float,int,int) is not applicable
(argument mismatch; float[] cannot be converted to int)
method MathHelper.lerp(float,float,float) is not applicable
(argument mismatch; float[] cannot be converted to float)
method MathHelper.lerp(double,Vec3d,Vec3d) is not applicable
(argument mismatch; float[] cannot be converted to Vec3d)
method MathHelper.lerp(double,double,double) is not applicable
(argument mismatch; float[] cannot be converted to double)
C:\Users\Mykola\Downloads\Rich-Modern\src\main\java\rich\screens\menu\MainMenuScreen.java:107: error: incompatible types: float cannot be converted to float[]
buttonHoverProgress = 0f;
^
C:\Users\Mykola\Downloads\Rich-Modern\src\main\java\rich\screens\menu\MainMenuScreen.java:307: error: cannot find symbol
Fonts.SYSTEM.drawCentered(footerText, centerX, screenHeight - 17, 6.5f, new Color(100, 100, 100).getRGB());
^
symbol: variable SYSTEM
location: class Fonts
C:\Users\Mykola\Downloads\Rich-Modern\src\main\java\rich\screens\menu\MainMenuScreen.java:308: error: cannot find symbol
Fonts.SYSTEM.drawCentered(policyLinks, centerX, screenHeight - 8, 6.5f, new Color(100, 100, 100).getRGB());
^
symbol: variable SYSTEM
location: class Fonts
5 errors

* Try:
> Check your code and dependencies to fix the compilation error(s)
> Run with --scan to generate a Build Scan (powered by Develocity).

BUILD FAILED in 1s
17:03:27: Execution finished ':net.fabricmc.devlaunchinjector.Main.main()'.
хз ты чет с фонтами сделал не моя проблема
 
врод похоже хз
фонты думаю сами найдете
код:
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: добавил обводку
нихуя, это рил годно /top
 
Назад
Сверху Снизу