Подписывайтесь на наш 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
 
Назад
Сверху Снизу