Вопрос AltManager 3.1

Начинающий
Статус
Оффлайн
Регистрация
1 Авг 2024
Сообщения
174
Реакции[?]
0
Поинты[?]
0

Перед прочтением основного контента ниже, пожалуйста, обратите внимание на обновление внутри секции Майна на нашем форуме. У нас появились:

  • бесплатные читы для Майнкрафт — любое использование на свой страх и риск;
  • маркетплейс Майнкрафт — абсолютно любая коммерция, связанная с игрой, за исключением продажи читов (аккаунты, предоставления услуг, поиск кодеров читов и так далее);
  • приватные читы для Minecraft — в этом разделе только платные хаки для игры, покупайте группу "Продавец" и выставляйте на продажу свой софт;
  • обсуждения и гайды — всё тот же раздел с вопросами, но теперь модернизированный: поиск нужных хаков, пати с игроками-читерами и другая полезная информация.

Спасибо!

qq гайс, как можно ли вшить альт менеджер по типу

Пожалуйста, авторизуйтесь для просмотра ссылки.

1740327232099.png
в эксп 3.1
если да то как, помогите пожалуйста я долбаеб(
 
Начинающий
Статус
Онлайн
Регистрация
14 Ноя 2024
Сообщения
387
Реакции[?]
7
Поинты[?]
4K
Начинающий
Статус
Оффлайн
Регистрация
22 Май 2023
Сообщения
174
Реакции[?]
4
Поинты[?]
3K
Начинающий
Статус
Оффлайн
Регистрация
3 Мар 2024
Сообщения
76
Реакции[?]
0
Поинты[?]
0
qq гайс, как можно ли вшить альт менеджер по типу

Пожалуйста, авторизуйтесь для просмотра ссылки.

Посмотреть вложение 299357
в эксп 3.1
если да то как, помогите пожалуйста я долбаеб(
Код:
package im.expensive.another.screen;

import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.platform.GlStateManager;
import im.expensive.ui.mainmenu.MainScreen;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.client.gui.widget.button.Button;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.Session;
import net.minecraft.util.text.StringTextComponent;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.*;


public class AccountManagement extends Screen {

    private static final Logger LOGGER = LogManager.getLogger();
    private static final long DOUBLE_CLICK_INTERVAL = 250;
    private static final int ACCOUNT_LIST_START_Y = 45;
    private static final int ACCOUNT_LIST_ENTRY_HEIGHT = 20;
    private static final int MAX_LIST_HEIGHT = 400;
    private static final int LIST_WIDTH = 400;
    private static final int BUTTON_WIDTH = 100;
    private static final int BUTTON_HEIGHT = 20;
    private static final int TEXT_FIELD_HEIGHT = 20;
    private static final int COLOR_SELECTED = new Color(124, 124, 125, 255).getRGB();
    private static final int COLOR_BACKGROUND = new Color(0, 0, 0, 255).getRGB();
    private static final int COLOR_HIGHLIGHT = new Color(0, 0, 0, 100).getRGB();
    private static final int COLOR_WHITE = 0xFFFFFF;
    private static final int COLOR_GREEN = 0x00FF00;
    private static final int COLOR_HINT = 0xCCCCCC;
    private static final ResourceLocation STEVE_SKIN = new ResourceLocation("textures/entity/steve.png");
    private static final String ACCOUNTS_FILE_PATH = "Clouse/files/accounts.clouse";

    private long lastClickTime = 0;
    private boolean isScrolling = false;
    private int lastMouseY = 0;
    private int scrollOffset = 0;
    private Button loginButton;
    private Button deleteButton;
    private static List<Account> filteredAccounts = new ArrayList<>();
    private static final List<Account> accounts = new ArrayList<>();
    private Account selectedAccount = null;
    private static TextFieldWidget searchField;
    private TextFieldWidget fieldWidget;
    private int mouseY;


    public AccountManagement() {
        super(new StringTextComponent("Активный аккаунт"));
        loadAccounts();
    }

    private static class Account {
        String username;
        Account(String username) {
            this.username = username;
        }
    }

    @Override
    public void init() {
        int centerX = this.width / 2;
        int centerY = this.height / 2;
        int listX = centerX - LIST_WIDTH / 2;
        int searchFieldX = centerX - 100;

        // Поисковое текстовое поле для фильтрации аккаунтов
        searchField = new TextFieldWidget(font, searchFieldX, 20, 200, TEXT_FIELD_HEIGHT, new StringTextComponent(""));
        searchField.setResponder(this::filterAccounts);
        this.children.add(searchField);
        //Текст-заполнитель для searchField
        searchField.setSuggestion("");

        int buttonY = this.height - 35;
        int buttonSpacing = BUTTON_WIDTH + 5;
        // Добавить кнопку для действий
        loginButton = addButton(new Button(centerX - 2 * buttonSpacing , buttonY, BUTTON_WIDTH, BUTTON_HEIGHT, new StringTextComponent("Войти"), button -> loginSelectedAccount()));
        deleteButton = addButton(new Button(centerX - buttonSpacing, buttonY, BUTTON_WIDTH, BUTTON_HEIGHT, new StringTextComponent("Удалить"), button -> deleteSelectedAccount()));
        addButton(new Button(centerX, buttonY, BUTTON_WIDTH, BUTTON_HEIGHT, new StringTextComponent("Добавить аккаунт"), button -> Minecraft.getInstance().displayGuiScreen(new AddAccountScreen())));
        addButton(new Button(centerX + buttonSpacing, buttonY, BUTTON_WIDTH, BUTTON_HEIGHT, new StringTextComponent("Выйти"), button -> Minecraft.getInstance().displayGuiScreen(new MainScreen())));

        // Текстовое поле для ввода имени пользователя (скрыто по умолчанию)
        fieldWidget = new TextFieldWidget(this.font, centerX - 150, 100, 300, TEXT_FIELD_HEIGHT, new StringTextComponent("Никнейм"));
        fieldWidget.setVisible(false);
        fieldWidget.setMaxStringLength(16);
        this.children.add(fieldWidget);

        // Изначально показывать все аккаунты
        filteredAccounts = new ArrayList<>(accounts);

    }


    public void addAccount(String username) {
        if (!isValidUsername(username)) {
            LOGGER.warn("Попытка с недопустимым именем пользователя: " + username);
            return;
        }
        for (Account account : accounts) {
            if (account.username.equalsIgnoreCase(username)) {
                LOGGER.warn("Попытка с дублирующимся именем пользователя: " + username);
                return; // предотвратить добавление дубликатов имен пользователей
            }
        }
        accounts.add(new Account(username));
        saveAccounts();
    }


    @Override
    public void render(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) {
        this.renderBackground(matrixStack);
        super.render(matrixStack, mouseX, mouseY, partialTicks);


        loginButton.active = selectedAccount != null;
        deleteButton.active = selectedAccount != null;
        // Обновить подсказки кнопок
        updateButtonTooltips(loginButton, deleteButton, mouseX);

        String currentUsername = Minecraft.getInstance().getSession().getUsername();
        String screenTitle = "Текущий аккаунт - " + currentUsername + "";
        drawCenteredString(matrixStack, font, screenTitle, this.width / 2, 8, COLOR_WHITE);

        int listWidth = LIST_WIDTH;
        int listX = this.width / 2 - listWidth / 2;
        int listY = ACCOUNT_LIST_START_Y;
        int visibleAccounts = MAX_LIST_HEIGHT / ACCOUNT_LIST_ENTRY_HEIGHT;
        int startIndex = scrollOffset / ACCOUNT_LIST_ENTRY_HEIGHT;
        int endIndex = Math.min(filteredAccounts.size(), startIndex + visibleAccounts);
        int maxRenderY = this.height - 35 - ACCOUNT_LIST_ENTRY_HEIGHT;

        //Отрисовка фона списка аккаунтов
        fill(matrixStack, listX, listY, listX + listWidth, listY + MAX_LIST_HEIGHT, 0x80000000);

        if (!filteredAccounts.isEmpty()) {
            for (int i = startIndex; i < endIndex; i++) {
                int entryY = listY + (i - startIndex) * ACCOUNT_LIST_ENTRY_HEIGHT - (scrollOffset % ACCOUNT_LIST_ENTRY_HEIGHT);

                if (entryY + ACCOUNT_LIST_ENTRY_HEIGHT <= maxRenderY) {
                    Account account = filteredAccounts.get(i);
                    String accountName = account.username;
                    // Отрисовка выделения для выбранного аккаунта

                    if (selectedAccount != null && accountName.equals(selectedAccount.username)) {
                        fill(matrixStack, listX, entryY, listX + listWidth, entryY + ACCOUNT_LIST_ENTRY_HEIGHT, COLOR_SELECTED);
                        fill(matrixStack, listX + 1, entryY + 1, listX + listWidth - 1, entryY + ACCOUNT_LIST_ENTRY_HEIGHT - 1, COLOR_BACKGROUND);
                    }


                    //Отрисовка иконки головы игрока
                    Minecraft.getInstance().getTextureManager().bindTexture(STEVE_SKIN);
                    GlStateManager.enableBlend();
                    drawScaledCustomSizeModalRect(listX + 2, entryY + 2, 8, 8, 8, 8, 16, 16, 64, 64);
                    GlStateManager.disableBlend();


                    //Отрисовка имени аккаунта с разным цветом для аккаунта текущей сессии
                    int textColor = accountName.equals(currentUsername) ? COLOR_GREEN : COLOR_WHITE;
                    drawString(matrixStack, font, accountName, listX + 21, entryY + 6, textColor);
                }


                //Отрисовка полосы прокрутки
                if (filteredAccounts.size() > visibleAccounts) {
                    int scrollBarHeight = MAX_LIST_HEIGHT * visibleAccounts / filteredAccounts.size();
                    int scrollBarY = listY + (scrollOffset * (MAX_LIST_HEIGHT - scrollBarHeight)) / (filteredAccounts.size() * ACCOUNT_LIST_ENTRY_HEIGHT - MAX_LIST_HEIGHT);
                    fill(matrixStack, listX + listWidth + 2, scrollBarY, listX + listWidth + 6, scrollBarY + scrollBarHeight, COLOR_WHITE);
                }
                // Отрисовка выделения, если мышь находится над определенным аккаунтом
                if (mouseX >= listX && mouseX < listX + listWidth && mouseY >= entryY && mouseY < entryY + ACCOUNT_LIST_ENTRY_HEIGHT) {
                    fill(matrixStack, listX + 2, entryY + 2, listX + 18, entryY + 18, COLOR_HIGHLIGHT);
                }

            }

        } else {
            String noAccountsText = "Аккаунт не найден!";
            drawCenteredString(matrixStack, font, noAccountsText, this.width / 2, listY + 20, COLOR_WHITE);
        }
        //Отрисовка searchField и текста-заполнителя
        searchField.render(matrixStack, mouseX, mouseY, partialTicks);
        renderSearchFieldPlaceholder(matrixStack);
        //Отрисовка textField виджета
        if (fieldWidget.getVisible()) {
            fieldWidget.render(matrixStack, mouseX, mouseY, partialTicks);
        }
    }

    private void renderSearchFieldPlaceholder(MatrixStack matrixStack) {
        String searchFieldText = "Поиск аккаунта";
        int searchFieldX = this.width / 2 - this.font.getStringWidth(searchFieldText) / 2 - 60;
        int searchFieldY = 26;
        if (!searchField.isFocused() && searchField.getText().isEmpty()) {
            this.font.drawString(matrixStack, searchFieldText, searchFieldX, searchFieldY, COLOR_HINT);
        }
    }

    private void updateButtonTooltips(Button loginButton, Button deleteButton, int mouseX) {
        if (loginButton != null) {
            loginButton.setMessage(new StringTextComponent(selectedAccount != null ? "Войти" : "Войти"));
        }
        if (deleteButton != null) {
            deleteButton.setMessage(new StringTextComponent(selectedAccount != null ? "Удалить" : "Удалить"));
        }
        if (mouseOverButton(loginButton, mouseX)) {
            renderTooltip(new StringTextComponent("Войти в выбранный аккаунт"), mouseX, mouseY);
        }
        if (mouseOverButton(deleteButton, mouseX)) {
            renderTooltip(new StringTextComponent("Удалить выбранный аккаунт"), mouseX, mouseY);
        }
    }

    private void renderTooltip(StringTextComponent войтиВВыбранныйАккаунт, int mouseX, int mouseY) {

    }

    // Вспомогательный метод для проверки, находится ли мышь над кнопкой
    private boolean mouseOverButton(Button button, int mouseX) {
        return  button != null && mouseX >= button.x && mouseX < button.x + button.getWidth() &&
                mouseY >= button.y && mouseY < button.y + button.getHeightRealms();
    }
    @Override
    public boolean mouseClicked(double mouseX, double mouseY, int button) {
        int listWidth = LIST_WIDTH;
        int listX = this.width / 2 - listWidth / 2;

        int visibleAccounts = MAX_LIST_HEIGHT / ACCOUNT_LIST_ENTRY_HEIGHT;
        int startIndex = scrollOffset / ACCOUNT_LIST_ENTRY_HEIGHT;
        int endIndex = Math.min(filteredAccounts.size(), startIndex + visibleAccounts);
        int maxRenderY = this.height - 35 - ACCOUNT_LIST_ENTRY_HEIGHT;

        if (button == 0) { //Левая кнопка мыши
            long currentTime = System.currentTimeMillis();
            for (int i = startIndex; i < endIndex; i++) {
                int entryY = ACCOUNT_LIST_START_Y + (i - startIndex) * ACCOUNT_LIST_ENTRY_HEIGHT - (scrollOffset % ACCOUNT_LIST_ENTRY_HEIGHT);
                if (entryY + ACCOUNT_LIST_ENTRY_HEIGHT <= maxRenderY && mouseX >= listX && mouseX < listX + listWidth && mouseY >= entryY && mouseY < entryY + ACCOUNT_LIST_ENTRY_HEIGHT) {
                    selectedAccount = filteredAccounts.get(i);

                    if (currentTime - lastClickTime < DOUBLE_CLICK_INTERVAL) {
                        loginSelectedAccount();
                    }
                    lastClickTime = currentTime;
                    return true;
                }
            }
        }
        return super.mouseClicked(mouseX, mouseY, button);
    }
    @Override
    public boolean mouseReleased(double mouseX, double mouseY, int button) {
        if (this.isScrolling) {
            this.isScrolling = false;
            return true;
        }
        return super.mouseReleased(mouseX, mouseY, button);
    }

    @Override
    public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) {
        if (this.isScrolling) {
            int deltaYInt = (int) mouseY - this.lastMouseY;
            this.scrollOffset -= deltaYInt;
            this.scrollOffset = Math.max(0, Math.min(this.scrollOffset, filteredAccounts.size() * ACCOUNT_LIST_ENTRY_HEIGHT - MAX_LIST_HEIGHT));
            this.lastMouseY = (int) mouseY;
            return true;
        }
        return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY);
    }

    private void filterAccounts(String query) {
        if (query.isEmpty()) {
            filteredAccounts = new ArrayList<>(accounts);
        } else {
            filteredAccounts.clear();
            for (Account account : accounts) {
                if (account.username.toLowerCase().contains(query.toLowerCase())) {
                    filteredAccounts.add(account);
                }
            }
        }
    }

    private void loginSelectedAccount() {
        if (selectedAccount != null) {
            Minecraft.getInstance().session = new Session(selectedAccount.username, "", "", "mojang");

        }
    }
    @Override
    public boolean mouseScrolled(double mouseX, double mouseY, double delta) {
        if (isMouseOverScreen(mouseX, mouseY)) {
            scrollOffset -= (int) delta * ACCOUNT_LIST_ENTRY_HEIGHT;
            int maxScroll = Math.max(0, filteredAccounts.size() * ACCOUNT_LIST_ENTRY_HEIGHT - MAX_LIST_HEIGHT);
            scrollOffset = Math.max(0, Math.min(scrollOffset, maxScroll));
            return true;
        }
        return super.mouseScrolled(mouseX, mouseY, delta);
    }

    private boolean isMouseOverScreen(double mouseX, double mouseY) {
        int listWidth = LIST_WIDTH;
        int listX = this.width / 2 - listWidth / 2;
        int listY = ACCOUNT_LIST_START_Y;
        return mouseX >= listX && mouseX < listX + listWidth && mouseY >= listY && mouseY < listY + MAX_LIST_HEIGHT;
    }

    private void deleteSelectedAccount() {
        if (selectedAccount != null) {
            accounts.remove(selectedAccount);
            saveAccounts();
            selectedAccount = null;
        }
    }

    // Проверить, является ли имя пользователя допустимым
    private boolean isValidUsername(String username) {
        if (username == null || username.length() < 3 || username.length() > 16) {
            return false;
        }
        return username.matches("[a-zA-Z0-9-_]+");
    }

    // Сохранить аккаунты в файл
    private void saveAccounts() {
        try (PrintWriter out = new PrintWriter(Files.newBufferedWriter(Paths.get(ACCOUNTS_FILE_PATH)))) {
            Set<String> uniqueUsernames = new HashSet<>();
            for (Account account : accounts) {
                if (uniqueUsernames.add(account.username.toLowerCase()) && isValidUsername(account.username)) {
                    out.println(account.username);
                }
            }
        } catch (IOException e) {
            LOGGER.error("Не удалось сохранить аккаунты", e);
        }
    }


    // Загрузить аккаунты из файла
    private void loadAccounts() {
        File file = new File(ACCOUNTS_FILE_PATH);
        if (file.exists()) {
            try (Scanner scanner = new Scanner(file)) {
                accounts.clear();
                Set<String> uniqueUsernames = new HashSet<>();
                while (scanner.hasNextLine()) {
                    String username = scanner.nextLine();
                    if (uniqueUsernames.add(username.toLowerCase()) && isValidUsername(username)) {
                        accounts.add(new Account(username));
                    }
                }
            } catch (IOException e) {
                LOGGER.error("Не удалось загрузить аккаунты", e);
            }
        }
        if (searchField != null) {
            filterAccounts(searchField.getText());
        }
    }

    @Override
    public void onClose() {
        saveAccounts();
        super.onClose();
    }
}
Код:
package im.expensive.another.screen;

import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.platform.GlStateManager;
import im.expensive.ui.mainmenu.MainScreen;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.client.gui.widget.button.Button;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.Session;
import net.minecraft.util.text.StringTextComponent;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.*;


public class AccountManagement extends Screen {

    private static final Logger LOGGER = LogManager.getLogger();
    private static final long DOUBLE_CLICK_INTERVAL = 250;
    private static final int ACCOUNT_LIST_START_Y = 45;
    private static final int ACCOUNT_LIST_ENTRY_HEIGHT = 20;
    private static final int MAX_LIST_HEIGHT = 400;
    private static final int LIST_WIDTH = 400;
    private static final int BUTTON_WIDTH = 100;
    private static final int BUTTON_HEIGHT = 20;
    private static final int TEXT_FIELD_HEIGHT = 20;
    private static final int COLOR_SELECTED = new Color(124, 124, 125, 255).getRGB();
    private static final int COLOR_BACKGROUND = new Color(0, 0, 0, 255).getRGB();
    private static final int COLOR_HIGHLIGHT = new Color(0, 0, 0, 100).getRGB();
    private static final int COLOR_WHITE = 0xFFFFFF;
    private static final int COLOR_GREEN = 0x00FF00;
    private static final int COLOR_HINT = 0xCCCCCC;
    private static final ResourceLocation STEVE_SKIN = new ResourceLocation("textures/entity/steve.png");
    private static final String ACCOUNTS_FILE_PATH = "Clouse/files/accounts.clouse";

    private long lastClickTime = 0;
    private boolean isScrolling = false;
    private int lastMouseY = 0;
    private int scrollOffset = 0;
    private Button loginButton;
    private Button deleteButton;
    private static List<Account> filteredAccounts = new ArrayList<>();
    private static final List<Account> accounts = new ArrayList<>();
    private Account selectedAccount = null;
    private static TextFieldWidget searchField;
    private TextFieldWidget fieldWidget;
    private int mouseY;


    public AccountManagement() {
        super(new StringTextComponent("Активный аккаунт"));
        loadAccounts();
    }

    private static class Account {
        String username;
        Account(String username) {
            this.username = username;
        }
    }

    @Override
    public void init() {
        int centerX = this.width / 2;
        int centerY = this.height / 2;
        int listX = centerX - LIST_WIDTH / 2;
        int searchFieldX = centerX - 100;

        // Поисковое текстовое поле для фильтрации аккаунтов
        searchField = new TextFieldWidget(font, searchFieldX, 20, 200, TEXT_FIELD_HEIGHT, new StringTextComponent(""));
        searchField.setResponder(this::filterAccounts);
        this.children.add(searchField);
        //Текст-заполнитель для searchField
        searchField.setSuggestion("");

        int buttonY = this.height - 35;
        int buttonSpacing = BUTTON_WIDTH + 5;
        // Добавить кнопку для действий
        loginButton = addButton(new Button(centerX - 2 * buttonSpacing , buttonY, BUTTON_WIDTH, BUTTON_HEIGHT, new StringTextComponent("Войти"), button -> loginSelectedAccount()));
        deleteButton = addButton(new Button(centerX - buttonSpacing, buttonY, BUTTON_WIDTH, BUTTON_HEIGHT, new StringTextComponent("Удалить"), button -> deleteSelectedAccount()));
        addButton(new Button(centerX, buttonY, BUTTON_WIDTH, BUTTON_HEIGHT, new StringTextComponent("Добавить аккаунт"), button -> Minecraft.getInstance().displayGuiScreen(new AddAccountScreen())));
        addButton(new Button(centerX + buttonSpacing, buttonY, BUTTON_WIDTH, BUTTON_HEIGHT, new StringTextComponent("Выйти"), button -> Minecraft.getInstance().displayGuiScreen(new MainScreen())));

        // Текстовое поле для ввода имени пользователя (скрыто по умолчанию)
        fieldWidget = new TextFieldWidget(this.font, centerX - 150, 100, 300, TEXT_FIELD_HEIGHT, new StringTextComponent("Никнейм"));
        fieldWidget.setVisible(false);
        fieldWidget.setMaxStringLength(16);
        this.children.add(fieldWidget);

        // Изначально показывать все аккаунты
        filteredAccounts = new ArrayList<>(accounts);

    }


    public void addAccount(String username) {
        if (!isValidUsername(username)) {
            LOGGER.warn("Попытка с недопустимым именем пользователя: " + username);
            return;
        }
        for (Account account : accounts) {
            if (account.username.equalsIgnoreCase(username)) {
                LOGGER.warn("Попытка с дублирующимся именем пользователя: " + username);
                return; // предотвратить добавление дубликатов имен пользователей
            }
        }
        accounts.add(new Account(username));
        saveAccounts();
    }


    @Override
    public void render(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) {
        this.renderBackground(matrixStack);
        super.render(matrixStack, mouseX, mouseY, partialTicks);


        loginButton.active = selectedAccount != null;
        deleteButton.active = selectedAccount != null;
        // Обновить подсказки кнопок
        updateButtonTooltips(loginButton, deleteButton, mouseX);

        String currentUsername = Minecraft.getInstance().getSession().getUsername();
        String screenTitle = "Текущий аккаунт - " + currentUsername + "";
        drawCenteredString(matrixStack, font, screenTitle, this.width / 2, 8, COLOR_WHITE);

        int listWidth = LIST_WIDTH;
        int listX = this.width / 2 - listWidth / 2;
        int listY = ACCOUNT_LIST_START_Y;
        int visibleAccounts = MAX_LIST_HEIGHT / ACCOUNT_LIST_ENTRY_HEIGHT;
        int startIndex = scrollOffset / ACCOUNT_LIST_ENTRY_HEIGHT;
        int endIndex = Math.min(filteredAccounts.size(), startIndex + visibleAccounts);
        int maxRenderY = this.height - 35 - ACCOUNT_LIST_ENTRY_HEIGHT;

        //Отрисовка фона списка аккаунтов
        fill(matrixStack, listX, listY, listX + listWidth, listY + MAX_LIST_HEIGHT, 0x80000000);

        if (!filteredAccounts.isEmpty()) {
            for (int i = startIndex; i < endIndex; i++) {
                int entryY = listY + (i - startIndex) * ACCOUNT_LIST_ENTRY_HEIGHT - (scrollOffset % ACCOUNT_LIST_ENTRY_HEIGHT);

                if (entryY + ACCOUNT_LIST_ENTRY_HEIGHT <= maxRenderY) {
                    Account account = filteredAccounts.get(i);
                    String accountName = account.username;
                    // Отрисовка выделения для выбранного аккаунта

                    if (selectedAccount != null && accountName.equals(selectedAccount.username)) {
                        fill(matrixStack, listX, entryY, listX + listWidth, entryY + ACCOUNT_LIST_ENTRY_HEIGHT, COLOR_SELECTED);
                        fill(matrixStack, listX + 1, entryY + 1, listX + listWidth - 1, entryY + ACCOUNT_LIST_ENTRY_HEIGHT - 1, COLOR_BACKGROUND);
                    }


                    //Отрисовка иконки головы игрока
                    Minecraft.getInstance().getTextureManager().bindTexture(STEVE_SKIN);
                    GlStateManager.enableBlend();
                    drawScaledCustomSizeModalRect(listX + 2, entryY + 2, 8, 8, 8, 8, 16, 16, 64, 64);
                    GlStateManager.disableBlend();


                    //Отрисовка имени аккаунта с разным цветом для аккаунта текущей сессии
                    int textColor = accountName.equals(currentUsername) ? COLOR_GREEN : COLOR_WHITE;
                    drawString(matrixStack, font, accountName, listX + 21, entryY + 6, textColor);
                }


                //Отрисовка полосы прокрутки
                if (filteredAccounts.size() > visibleAccounts) {
                    int scrollBarHeight = MAX_LIST_HEIGHT * visibleAccounts / filteredAccounts.size();
                    int scrollBarY = listY + (scrollOffset * (MAX_LIST_HEIGHT - scrollBarHeight)) / (filteredAccounts.size() * ACCOUNT_LIST_ENTRY_HEIGHT - MAX_LIST_HEIGHT);
                    fill(matrixStack, listX + listWidth + 2, scrollBarY, listX + listWidth + 6, scrollBarY + scrollBarHeight, COLOR_WHITE);
                }
                // Отрисовка выделения, если мышь находится над определенным аккаунтом
                if (mouseX >= listX && mouseX < listX + listWidth && mouseY >= entryY && mouseY < entryY + ACCOUNT_LIST_ENTRY_HEIGHT) {
                    fill(matrixStack, listX + 2, entryY + 2, listX + 18, entryY + 18, COLOR_HIGHLIGHT);
                }

            }

        } else {
            String noAccountsText = "Аккаунт не найден!";
            drawCenteredString(matrixStack, font, noAccountsText, this.width / 2, listY + 20, COLOR_WHITE);
        }
        //Отрисовка searchField и текста-заполнителя
        searchField.render(matrixStack, mouseX, mouseY, partialTicks);
        renderSearchFieldPlaceholder(matrixStack);
        //Отрисовка textField виджета
        if (fieldWidget.getVisible()) {
            fieldWidget.render(matrixStack, mouseX, mouseY, partialTicks);
        }
    }

    private void renderSearchFieldPlaceholder(MatrixStack matrixStack) {
        String searchFieldText = "Поиск аккаунта";
        int searchFieldX = this.width / 2 - this.font.getStringWidth(searchFieldText) / 2 - 60;
        int searchFieldY = 26;
        if (!searchField.isFocused() && searchField.getText().isEmpty()) {
            this.font.drawString(matrixStack, searchFieldText, searchFieldX, searchFieldY, COLOR_HINT);
        }
    }

    private void updateButtonTooltips(Button loginButton, Button deleteButton, int mouseX) {
        if (loginButton != null) {
            loginButton.setMessage(new StringTextComponent(selectedAccount != null ? "Войти" : "Войти"));
        }
        if (deleteButton != null) {
            deleteButton.setMessage(new StringTextComponent(selectedAccount != null ? "Удалить" : "Удалить"));
        }
        if (mouseOverButton(loginButton, mouseX)) {
            renderTooltip(new StringTextComponent("Войти в выбранный аккаунт"), mouseX, mouseY);
        }
        if (mouseOverButton(deleteButton, mouseX)) {
            renderTooltip(new StringTextComponent("Удалить выбранный аккаунт"), mouseX, mouseY);
        }
    }

    private void renderTooltip(StringTextComponent войтиВВыбранныйАккаунт, int mouseX, int mouseY) {

    }

    // Вспомогательный метод для проверки, находится ли мышь над кнопкой
    private boolean mouseOverButton(Button button, int mouseX) {
        return  button != null && mouseX >= button.x && mouseX < button.x + button.getWidth() &&
                mouseY >= button.y && mouseY < button.y + button.getHeightRealms();
    }
    @Override
    public boolean mouseClicked(double mouseX, double mouseY, int button) {
        int listWidth = LIST_WIDTH;
        int listX = this.width / 2 - listWidth / 2;

        int visibleAccounts = MAX_LIST_HEIGHT / ACCOUNT_LIST_ENTRY_HEIGHT;
        int startIndex = scrollOffset / ACCOUNT_LIST_ENTRY_HEIGHT;
        int endIndex = Math.min(filteredAccounts.size(), startIndex + visibleAccounts);
        int maxRenderY = this.height - 35 - ACCOUNT_LIST_ENTRY_HEIGHT;

        if (button == 0) { //Левая кнопка мыши
            long currentTime = System.currentTimeMillis();
            for (int i = startIndex; i < endIndex; i++) {
                int entryY = ACCOUNT_LIST_START_Y + (i - startIndex) * ACCOUNT_LIST_ENTRY_HEIGHT - (scrollOffset % ACCOUNT_LIST_ENTRY_HEIGHT);
                if (entryY + ACCOUNT_LIST_ENTRY_HEIGHT <= maxRenderY && mouseX >= listX && mouseX < listX + listWidth && mouseY >= entryY && mouseY < entryY + ACCOUNT_LIST_ENTRY_HEIGHT) {
                    selectedAccount = filteredAccounts.get(i);

                    if (currentTime - lastClickTime < DOUBLE_CLICK_INTERVAL) {
                        loginSelectedAccount();
                    }
                    lastClickTime = currentTime;
                    return true;
                }
            }
        }
        return super.mouseClicked(mouseX, mouseY, button);
    }
    @Override
    public boolean mouseReleased(double mouseX, double mouseY, int button) {
        if (this.isScrolling) {
            this.isScrolling = false;
            return true;
        }
        return super.mouseReleased(mouseX, mouseY, button);
    }

    @Override
    public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) {
        if (this.isScrolling) {
            int deltaYInt = (int) mouseY - this.lastMouseY;
            this.scrollOffset -= deltaYInt;
            this.scrollOffset = Math.max(0, Math.min(this.scrollOffset, filteredAccounts.size() * ACCOUNT_LIST_ENTRY_HEIGHT - MAX_LIST_HEIGHT));
            this.lastMouseY = (int) mouseY;
            return true;
        }
        return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY);
    }

    private void filterAccounts(String query) {
        if (query.isEmpty()) {
            filteredAccounts = new ArrayList<>(accounts);
        } else {
            filteredAccounts.clear();
            for (Account account : accounts) {
                if (account.username.toLowerCase().contains(query.toLowerCase())) {
                    filteredAccounts.add(account);
                }
            }
        }
    }

    private void loginSelectedAccount() {
        if (selectedAccount != null) {
            Minecraft.getInstance().session = new Session(selectedAccount.username, "", "", "mojang");

        }
    }
    @Override
    public boolean mouseScrolled(double mouseX, double mouseY, double delta) {
        if (isMouseOverScreen(mouseX, mouseY)) {
            scrollOffset -= (int) delta * ACCOUNT_LIST_ENTRY_HEIGHT;
            int maxScroll = Math.max(0, filteredAccounts.size() * ACCOUNT_LIST_ENTRY_HEIGHT - MAX_LIST_HEIGHT);
            scrollOffset = Math.max(0, Math.min(scrollOffset, maxScroll));
            return true;
        }
        return super.mouseScrolled(mouseX, mouseY, delta);
    }

    private boolean isMouseOverScreen(double mouseX, double mouseY) {
        int listWidth = LIST_WIDTH;
        int listX = this.width / 2 - listWidth / 2;
        int listY = ACCOUNT_LIST_START_Y;
        return mouseX >= listX && mouseX < listX + listWidth && mouseY >= listY && mouseY < listY + MAX_LIST_HEIGHT;
    }

    private void deleteSelectedAccount() {
        if (selectedAccount != null) {
            accounts.remove(selectedAccount);
            saveAccounts();
            selectedAccount = null;
        }
    }

    // Проверить, является ли имя пользователя допустимым
    private boolean isValidUsername(String username) {
        if (username == null || username.length() < 3 || username.length() > 16) {
            return false;
        }
        return username.matches("[a-zA-Z0-9-_]+");
    }

    // Сохранить аккаунты в файл
    private void saveAccounts() {
        try (PrintWriter out = new PrintWriter(Files.newBufferedWriter(Paths.get(ACCOUNTS_FILE_PATH)))) {
            Set<String> uniqueUsernames = new HashSet<>();
            for (Account account : accounts) {
                if (uniqueUsernames.add(account.username.toLowerCase()) && isValidUsername(account.username)) {
                    out.println(account.username);
                }
            }
        } catch (IOException e) {
            LOGGER.error("Не удалось сохранить аккаунты", e);
        }
    }


    // Загрузить аккаунты из файла
    private void loadAccounts() {
        File file = new File(ACCOUNTS_FILE_PATH);
        if (file.exists()) {
            try (Scanner scanner = new Scanner(file)) {
                accounts.clear();
                Set<String> uniqueUsernames = new HashSet<>();
                while (scanner.hasNextLine()) {
                    String username = scanner.nextLine();
                    if (uniqueUsernames.add(username.toLowerCase()) && isValidUsername(username)) {
                        accounts.add(new Account(username));
                    }
                }
            } catch (IOException e) {
                LOGGER.error("Не удалось загрузить аккаунты", e);
            }
        }
        if (searchField != null) {
            filterAccounts(searchField.getText());
        }
    }

    @Override
    public void onClose() {
        saveAccounts();
        super.onClose();
    }
}
[CODE]package im.expensive.another.screen;

import com.mojang.blaze3d.matrix.MatrixStack;
import io.netty.util.internal.ThreadLocalRandom;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.client.gui.widget.button.Button;
import net.minecraft.util.text.StringTextComponent;

import java.util.Random;

public class AddAccountScreen extends Screen {
    private TextFieldWidget fieldWidget;
    private Button loginButton;
    private Button randomButton;
    private int textWidth = 200;
    private int buttonHeight = 20;
    private int randomButtonWidth = 50;
    private int loginButtonWidth = 150;
    String currentUsername = Minecraft.getInstance().getSession().getUsername();
    AccountManagement accountManagement = new AccountManagement();

    public AddAccountScreen() {
        super(new StringTextComponent("Добавь новый аккаунт"));
    }

    @Override
    public void init(Minecraft minecraft, int width, int height) {
        super.init(minecraft, width, height);

        int textFieldX = this.width / 2 - textWidth / 2;
        int textFieldY = this.height / 2 - 60;
        int buttonY = textFieldY + 25;

        fieldWidget = new TextFieldWidget(font, textFieldX, textFieldY, textWidth, 20, new StringTextComponent("Аккаунт")) {
            @Override
            public boolean charTyped(char codePoint, int modifiers) {
                if (Character.toString(codePoint).matches("[a-zA-Z0-9-_]") || codePoint == '\b') {
                    return super.charTyped(codePoint, modifiers);
                }
                return false;
            }
        };
        fieldWidget.setMaxStringLength(16);
        addButton(fieldWidget);

        loginButton = new Button(textFieldX, buttonY, loginButtonWidth, buttonHeight, new StringTextComponent("Войти"), button -> {
            String username = fieldWidget.getText().trim();
            if (!username.isEmpty()) {
                accountManagement.addAccount(username);
                Minecraft.getInstance().displayGuiScreen(new AccountManagement());
            }
        });
        addButton(loginButton);

        randomButton = new Button(textFieldX + loginButtonWidth, buttonY, randomButtonWidth, buttonHeight, new StringTextComponent("Рандом"), button -> {
            Random random = new Random();
            String randomNick = generateRandomName();
            fieldWidget.setText(randomNick);
        });
        addButton(randomButton);

        Button cancelButton = new Button(textFieldX, buttonY + 25, textWidth, buttonHeight, new StringTextComponent("Аккаунты"), button -> {
            Minecraft.getInstance().displayGuiScreen(new AccountManagement());
        });
        addButton(cancelButton);
    }

    private String generateRandomName() {
        String[] prefixes = {"EvgenBro", "Oskar","Maksim", "Gamer", "Clouse", "Vitya", "4len" ,"Sasho","NEFOR", "Sasha", "SANEK", "SANA", "Muhamad", "Muhamed", "MoonBr", "DragonYT", "YTMAX",  "Quantum", "Alpha", "Omega", "Ultra", "Mega", "Super", "Hyper"};
        String[] suffixes = {"Hi", "Go", "Gd", "YT","zah","Vit","Mak", "AnDrEY", "Mr", "Sash", "4len","Game", "Bro", "Ivan", "TV", "Pro", "God", "Lord", "King", "Boss", "Max"};
        String prefix = prefixes[ThreadLocalRandom.current().nextInt(prefixes.length)];
        String suffix = suffixes[ThreadLocalRandom.current().nextInt(suffixes.length)];
        int number = ThreadLocalRandom.current().nextInt(100, 999);
        return prefix + suffix + number;
    }

    @Override
    public void tick() {
        super.tick();
        fieldWidget.tick();
        loginButton.active = fieldWidget.getText().trim().length() >= 3;
    }

    @Override
    public void render(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) {
        this.renderDirtBackground(0);
        super.render(matrixStack, mouseX, mouseY, partialTicks);

        fieldWidget.render(matrixStack, mouseX, mouseY, partialTicks);
        loginButton.render(matrixStack, mouseX, mouseY, partialTicks);
        randomButton.render(matrixStack, mouseX, mouseY, partialTicks);

        if (fieldWidget.getText().isEmpty()) {
            drawString(matrixStack, font, "Введите никнейм", width / 2 - textWidth / 2, height / 2 - 75, 0xCCCCCC);
        }

        if (!fieldWidget.getText().isEmpty()) {
            drawString(matrixStack, font, "Введите никнейм", width / 2 - textWidth / 2, height / 2 - 75, 0xCCCCCC);
        }

        if (mouseOverButton(loginButton, mouseX, mouseY)) {
            if (!loginButton.active) {
                renderTooltip(matrixStack, new StringTextComponent("Введите никнейм от 3 символов"), mouseX, mouseY);
            } else {
                renderTooltip(matrixStack, new StringTextComponent("Нажми что-бы войти"), mouseX, mouseY);
            }
        }

        if (mouseOverButton(randomButton, mouseX, mouseY)) {
            renderTooltip(matrixStack, new StringTextComponent("Рандомный никнейм"), mouseX, mouseY);
        }

        drawCenteredString(matrixStack, font, "Аккаунты", this.width / 2, 10, 0xFFFFFF);

    }

    private boolean mouseOverButton(Button button, int mouseX, int mouseY) {

        int buttonX1 = button.x;
        int buttonY1 = button.y;
        int buttonX2 = button.x + button.getWidth();
        int buttonY2 = button.y + button.getHeightRealms();

        return mouseX >= buttonX1 && mouseY >= buttonY1 && mouseX < buttonX2 && mouseY < buttonY2;
    }
}
[/CODE]
Код:
 y += 34 - 1.5f;
        buttons.add(new Button(x + 30, y + 14, widthButton - 140, 68 - 45, "Account", () -> mc.displayGuiScreen(new AccountManagement())));
 
Начинающий
Статус
Оффлайн
Регистрация
26 Дек 2023
Сообщения
1,171
Реакции[?]
15
Поинты[?]
6K
Начинающий
Статус
Оффлайн
Регистрация
1 Авг 2024
Сообщения
174
Реакции[?]
0
Поинты[?]
0
Код:
package im.expensive.another.screen;

import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.platform.GlStateManager;
import im.expensive.ui.mainmenu.MainScreen;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.client.gui.widget.button.Button;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.Session;
import net.minecraft.util.text.StringTextComponent;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.*;


public class AccountManagement extends Screen {

    private static final Logger LOGGER = LogManager.getLogger();
    private static final long DOUBLE_CLICK_INTERVAL = 250;
    private static final int ACCOUNT_LIST_START_Y = 45;
    private static final int ACCOUNT_LIST_ENTRY_HEIGHT = 20;
    private static final int MAX_LIST_HEIGHT = 400;
    private static final int LIST_WIDTH = 400;
    private static final int BUTTON_WIDTH = 100;
    private static final int BUTTON_HEIGHT = 20;
    private static final int TEXT_FIELD_HEIGHT = 20;
    private static final int COLOR_SELECTED = new Color(124, 124, 125, 255).getRGB();
    private static final int COLOR_BACKGROUND = new Color(0, 0, 0, 255).getRGB();
    private static final int COLOR_HIGHLIGHT = new Color(0, 0, 0, 100).getRGB();
    private static final int COLOR_WHITE = 0xFFFFFF;
    private static final int COLOR_GREEN = 0x00FF00;
    private static final int COLOR_HINT = 0xCCCCCC;
    private static final ResourceLocation STEVE_SKIN = new ResourceLocation("textures/entity/steve.png");
    private static final String ACCOUNTS_FILE_PATH = "Clouse/files/accounts.clouse";

    private long lastClickTime = 0;
    private boolean isScrolling = false;
    private int lastMouseY = 0;
    private int scrollOffset = 0;
    private Button loginButton;
    private Button deleteButton;
    private static List<Account> filteredAccounts = new ArrayList<>();
    private static final List<Account> accounts = new ArrayList<>();
    private Account selectedAccount = null;
    private static TextFieldWidget searchField;
    private TextFieldWidget fieldWidget;
    private int mouseY;


    public AccountManagement() {
        super(new StringTextComponent("Активный аккаунт"));
        loadAccounts();
    }

    private static class Account {
        String username;
        Account(String username) {
            this.username = username;
        }
    }

    @Override
    public void init() {
        int centerX = this.width / 2;
        int centerY = this.height / 2;
        int listX = centerX - LIST_WIDTH / 2;
        int searchFieldX = centerX - 100;

        // Поисковое текстовое поле для фильтрации аккаунтов
        searchField = new TextFieldWidget(font, searchFieldX, 20, 200, TEXT_FIELD_HEIGHT, new StringTextComponent(""));
        searchField.setResponder(this::filterAccounts);
        this.children.add(searchField);
        //Текст-заполнитель для searchField
        searchField.setSuggestion("");

        int buttonY = this.height - 35;
        int buttonSpacing = BUTTON_WIDTH + 5;
        // Добавить кнопку для действий
        loginButton = addButton(new Button(centerX - 2 * buttonSpacing , buttonY, BUTTON_WIDTH, BUTTON_HEIGHT, new StringTextComponent("Войти"), button -> loginSelectedAccount()));
        deleteButton = addButton(new Button(centerX - buttonSpacing, buttonY, BUTTON_WIDTH, BUTTON_HEIGHT, new StringTextComponent("Удалить"), button -> deleteSelectedAccount()));
        addButton(new Button(centerX, buttonY, BUTTON_WIDTH, BUTTON_HEIGHT, new StringTextComponent("Добавить аккаунт"), button -> Minecraft.getInstance().displayGuiScreen(new AddAccountScreen())));
        addButton(new Button(centerX + buttonSpacing, buttonY, BUTTON_WIDTH, BUTTON_HEIGHT, new StringTextComponent("Выйти"), button -> Minecraft.getInstance().displayGuiScreen(new MainScreen())));

        // Текстовое поле для ввода имени пользователя (скрыто по умолчанию)
        fieldWidget = new TextFieldWidget(this.font, centerX - 150, 100, 300, TEXT_FIELD_HEIGHT, new StringTextComponent("Никнейм"));
        fieldWidget.setVisible(false);
        fieldWidget.setMaxStringLength(16);
        this.children.add(fieldWidget);

        // Изначально показывать все аккаунты
        filteredAccounts = new ArrayList<>(accounts);

    }


    public void addAccount(String username) {
        if (!isValidUsername(username)) {
            LOGGER.warn("Попытка с недопустимым именем пользователя: " + username);
            return;
        }
        for (Account account : accounts) {
            if (account.username.equalsIgnoreCase(username)) {
                LOGGER.warn("Попытка с дублирующимся именем пользователя: " + username);
                return; // предотвратить добавление дубликатов имен пользователей
            }
        }
        accounts.add(new Account(username));
        saveAccounts();
    }


    @Override
    public void render(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) {
        this.renderBackground(matrixStack);
        super.render(matrixStack, mouseX, mouseY, partialTicks);


        loginButton.active = selectedAccount != null;
        deleteButton.active = selectedAccount != null;
        // Обновить подсказки кнопок
        updateButtonTooltips(loginButton, deleteButton, mouseX);

        String currentUsername = Minecraft.getInstance().getSession().getUsername();
        String screenTitle = "Текущий аккаунт - " + currentUsername + "";
        drawCenteredString(matrixStack, font, screenTitle, this.width / 2, 8, COLOR_WHITE);

        int listWidth = LIST_WIDTH;
        int listX = this.width / 2 - listWidth / 2;
        int listY = ACCOUNT_LIST_START_Y;
        int visibleAccounts = MAX_LIST_HEIGHT / ACCOUNT_LIST_ENTRY_HEIGHT;
        int startIndex = scrollOffset / ACCOUNT_LIST_ENTRY_HEIGHT;
        int endIndex = Math.min(filteredAccounts.size(), startIndex + visibleAccounts);
        int maxRenderY = this.height - 35 - ACCOUNT_LIST_ENTRY_HEIGHT;

        //Отрисовка фона списка аккаунтов
        fill(matrixStack, listX, listY, listX + listWidth, listY + MAX_LIST_HEIGHT, 0x80000000);

        if (!filteredAccounts.isEmpty()) {
            for (int i = startIndex; i < endIndex; i++) {
                int entryY = listY + (i - startIndex) * ACCOUNT_LIST_ENTRY_HEIGHT - (scrollOffset % ACCOUNT_LIST_ENTRY_HEIGHT);

                if (entryY + ACCOUNT_LIST_ENTRY_HEIGHT <= maxRenderY) {
                    Account account = filteredAccounts.get(i);
                    String accountName = account.username;
                    // Отрисовка выделения для выбранного аккаунта

                    if (selectedAccount != null && accountName.equals(selectedAccount.username)) {
                        fill(matrixStack, listX, entryY, listX + listWidth, entryY + ACCOUNT_LIST_ENTRY_HEIGHT, COLOR_SELECTED);
                        fill(matrixStack, listX + 1, entryY + 1, listX + listWidth - 1, entryY + ACCOUNT_LIST_ENTRY_HEIGHT - 1, COLOR_BACKGROUND);
                    }


                    //Отрисовка иконки головы игрока
                    Minecraft.getInstance().getTextureManager().bindTexture(STEVE_SKIN);
                    GlStateManager.enableBlend();
                    drawScaledCustomSizeModalRect(listX + 2, entryY + 2, 8, 8, 8, 8, 16, 16, 64, 64);
                    GlStateManager.disableBlend();


                    //Отрисовка имени аккаунта с разным цветом для аккаунта текущей сессии
                    int textColor = accountName.equals(currentUsername) ? COLOR_GREEN : COLOR_WHITE;
                    drawString(matrixStack, font, accountName, listX + 21, entryY + 6, textColor);
                }


                //Отрисовка полосы прокрутки
                if (filteredAccounts.size() > visibleAccounts) {
                    int scrollBarHeight = MAX_LIST_HEIGHT * visibleAccounts / filteredAccounts.size();
                    int scrollBarY = listY + (scrollOffset * (MAX_LIST_HEIGHT - scrollBarHeight)) / (filteredAccounts.size() * ACCOUNT_LIST_ENTRY_HEIGHT - MAX_LIST_HEIGHT);
                    fill(matrixStack, listX + listWidth + 2, scrollBarY, listX + listWidth + 6, scrollBarY + scrollBarHeight, COLOR_WHITE);
                }
                // Отрисовка выделения, если мышь находится над определенным аккаунтом
                if (mouseX >= listX && mouseX < listX + listWidth && mouseY >= entryY && mouseY < entryY + ACCOUNT_LIST_ENTRY_HEIGHT) {
                    fill(matrixStack, listX + 2, entryY + 2, listX + 18, entryY + 18, COLOR_HIGHLIGHT);
                }

            }

        } else {
            String noAccountsText = "Аккаунт не найден!";
            drawCenteredString(matrixStack, font, noAccountsText, this.width / 2, listY + 20, COLOR_WHITE);
        }
        //Отрисовка searchField и текста-заполнителя
        searchField.render(matrixStack, mouseX, mouseY, partialTicks);
        renderSearchFieldPlaceholder(matrixStack);
        //Отрисовка textField виджета
        if (fieldWidget.getVisible()) {
            fieldWidget.render(matrixStack, mouseX, mouseY, partialTicks);
        }
    }

    private void renderSearchFieldPlaceholder(MatrixStack matrixStack) {
        String searchFieldText = "Поиск аккаунта";
        int searchFieldX = this.width / 2 - this.font.getStringWidth(searchFieldText) / 2 - 60;
        int searchFieldY = 26;
        if (!searchField.isFocused() && searchField.getText().isEmpty()) {
            this.font.drawString(matrixStack, searchFieldText, searchFieldX, searchFieldY, COLOR_HINT);
        }
    }

    private void updateButtonTooltips(Button loginButton, Button deleteButton, int mouseX) {
        if (loginButton != null) {
            loginButton.setMessage(new StringTextComponent(selectedAccount != null ? "Войти" : "Войти"));
        }
        if (deleteButton != null) {
            deleteButton.setMessage(new StringTextComponent(selectedAccount != null ? "Удалить" : "Удалить"));
        }
        if (mouseOverButton(loginButton, mouseX)) {
            renderTooltip(new StringTextComponent("Войти в выбранный аккаунт"), mouseX, mouseY);
        }
        if (mouseOverButton(deleteButton, mouseX)) {
            renderTooltip(new StringTextComponent("Удалить выбранный аккаунт"), mouseX, mouseY);
        }
    }

    private void renderTooltip(StringTextComponent войтиВВыбранныйАккаунт, int mouseX, int mouseY) {

    }

    // Вспомогательный метод для проверки, находится ли мышь над кнопкой
    private boolean mouseOverButton(Button button, int mouseX) {
        return  button != null && mouseX >= button.x && mouseX < button.x + button.getWidth() &&
                mouseY >= button.y && mouseY < button.y + button.getHeightRealms();
    }
    @Override
    public boolean mouseClicked(double mouseX, double mouseY, int button) {
        int listWidth = LIST_WIDTH;
        int listX = this.width / 2 - listWidth / 2;

        int visibleAccounts = MAX_LIST_HEIGHT / ACCOUNT_LIST_ENTRY_HEIGHT;
        int startIndex = scrollOffset / ACCOUNT_LIST_ENTRY_HEIGHT;
        int endIndex = Math.min(filteredAccounts.size(), startIndex + visibleAccounts);
        int maxRenderY = this.height - 35 - ACCOUNT_LIST_ENTRY_HEIGHT;

        if (button == 0) { //Левая кнопка мыши
            long currentTime = System.currentTimeMillis();
            for (int i = startIndex; i < endIndex; i++) {
                int entryY = ACCOUNT_LIST_START_Y + (i - startIndex) * ACCOUNT_LIST_ENTRY_HEIGHT - (scrollOffset % ACCOUNT_LIST_ENTRY_HEIGHT);
                if (entryY + ACCOUNT_LIST_ENTRY_HEIGHT <= maxRenderY && mouseX >= listX && mouseX < listX + listWidth && mouseY >= entryY && mouseY < entryY + ACCOUNT_LIST_ENTRY_HEIGHT) {
                    selectedAccount = filteredAccounts.get(i);

                    if (currentTime - lastClickTime < DOUBLE_CLICK_INTERVAL) {
                        loginSelectedAccount();
                    }
                    lastClickTime = currentTime;
                    return true;
                }
            }
        }
        return super.mouseClicked(mouseX, mouseY, button);
    }
    @Override
    public boolean mouseReleased(double mouseX, double mouseY, int button) {
        if (this.isScrolling) {
            this.isScrolling = false;
            return true;
        }
        return super.mouseReleased(mouseX, mouseY, button);
    }

    @Override
    public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) {
        if (this.isScrolling) {
            int deltaYInt = (int) mouseY - this.lastMouseY;
            this.scrollOffset -= deltaYInt;
            this.scrollOffset = Math.max(0, Math.min(this.scrollOffset, filteredAccounts.size() * ACCOUNT_LIST_ENTRY_HEIGHT - MAX_LIST_HEIGHT));
            this.lastMouseY = (int) mouseY;
            return true;
        }
        return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY);
    }

    private void filterAccounts(String query) {
        if (query.isEmpty()) {
            filteredAccounts = new ArrayList<>(accounts);
        } else {
            filteredAccounts.clear();
            for (Account account : accounts) {
                if (account.username.toLowerCase().contains(query.toLowerCase())) {
                    filteredAccounts.add(account);
                }
            }
        }
    }

    private void loginSelectedAccount() {
        if (selectedAccount != null) {
            Minecraft.getInstance().session = new Session(selectedAccount.username, "", "", "mojang");

        }
    }
    @Override
    public boolean mouseScrolled(double mouseX, double mouseY, double delta) {
        if (isMouseOverScreen(mouseX, mouseY)) {
            scrollOffset -= (int) delta * ACCOUNT_LIST_ENTRY_HEIGHT;
            int maxScroll = Math.max(0, filteredAccounts.size() * ACCOUNT_LIST_ENTRY_HEIGHT - MAX_LIST_HEIGHT);
            scrollOffset = Math.max(0, Math.min(scrollOffset, maxScroll));
            return true;
        }
        return super.mouseScrolled(mouseX, mouseY, delta);
    }

    private boolean isMouseOverScreen(double mouseX, double mouseY) {
        int listWidth = LIST_WIDTH;
        int listX = this.width / 2 - listWidth / 2;
        int listY = ACCOUNT_LIST_START_Y;
        return mouseX >= listX && mouseX < listX + listWidth && mouseY >= listY && mouseY < listY + MAX_LIST_HEIGHT;
    }

    private void deleteSelectedAccount() {
        if (selectedAccount != null) {
            accounts.remove(selectedAccount);
            saveAccounts();
            selectedAccount = null;
        }
    }

    // Проверить, является ли имя пользователя допустимым
    private boolean isValidUsername(String username) {
        if (username == null || username.length() < 3 || username.length() > 16) {
            return false;
        }
        return username.matches("[a-zA-Z0-9-_]+");
    }

    // Сохранить аккаунты в файл
    private void saveAccounts() {
        try (PrintWriter out = new PrintWriter(Files.newBufferedWriter(Paths.get(ACCOUNTS_FILE_PATH)))) {
            Set<String> uniqueUsernames = new HashSet<>();
            for (Account account : accounts) {
                if (uniqueUsernames.add(account.username.toLowerCase()) && isValidUsername(account.username)) {
                    out.println(account.username);
                }
            }
        } catch (IOException e) {
            LOGGER.error("Не удалось сохранить аккаунты", e);
        }
    }


    // Загрузить аккаунты из файла
    private void loadAccounts() {
        File file = new File(ACCOUNTS_FILE_PATH);
        if (file.exists()) {
            try (Scanner scanner = new Scanner(file)) {
                accounts.clear();
                Set<String> uniqueUsernames = new HashSet<>();
                while (scanner.hasNextLine()) {
                    String username = scanner.nextLine();
                    if (uniqueUsernames.add(username.toLowerCase()) && isValidUsername(username)) {
                        accounts.add(new Account(username));
                    }
                }
            } catch (IOException e) {
                LOGGER.error("Не удалось загрузить аккаунты", e);
            }
        }
        if (searchField != null) {
            filterAccounts(searchField.getText());
        }
    }

    @Override
    public void onClose() {
        saveAccounts();
        super.onClose();
    }
}
Код:
 y += 34 - 1.5f;
        buttons.add(new Button(x + 30, y + 14, widthButton - 140, 68 - 45, "Account", () -> mc.displayGuiScreen(new AccountManagement())));
1740542193702.png
 
Начинающий
Статус
Оффлайн
Регистрация
1 Авг 2024
Сообщения
174
Реакции[?]
0
Поинты[?]
0
Код:
package im.expensive.another.screen;

import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.platform.GlStateManager;
import im.expensive.ui.mainmenu.MainScreen;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.client.gui.widget.button.Button;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.Session;
import net.minecraft.util.text.StringTextComponent;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.*;


public class AccountManagement extends Screen {

    private static final Logger LOGGER = LogManager.getLogger();
    private static final long DOUBLE_CLICK_INTERVAL = 250;
    private static final int ACCOUNT_LIST_START_Y = 45;
    private static final int ACCOUNT_LIST_ENTRY_HEIGHT = 20;
    private static final int MAX_LIST_HEIGHT = 400;
    private static final int LIST_WIDTH = 400;
    private static final int BUTTON_WIDTH = 100;
    private static final int BUTTON_HEIGHT = 20;
    private static final int TEXT_FIELD_HEIGHT = 20;
    private static final int COLOR_SELECTED = new Color(124, 124, 125, 255).getRGB();
    private static final int COLOR_BACKGROUND = new Color(0, 0, 0, 255).getRGB();
    private static final int COLOR_HIGHLIGHT = new Color(0, 0, 0, 100).getRGB();
    private static final int COLOR_WHITE = 0xFFFFFF;
    private static final int COLOR_GREEN = 0x00FF00;
    private static final int COLOR_HINT = 0xCCCCCC;
    private static final ResourceLocation STEVE_SKIN = new ResourceLocation("textures/entity/steve.png");
    private static final String ACCOUNTS_FILE_PATH = "Clouse/files/accounts.clouse";

    private long lastClickTime = 0;
    private boolean isScrolling = false;
    private int lastMouseY = 0;
    private int scrollOffset = 0;
    private Button loginButton;
    private Button deleteButton;
    private static List<Account> filteredAccounts = new ArrayList<>();
    private static final List<Account> accounts = new ArrayList<>();
    private Account selectedAccount = null;
    private static TextFieldWidget searchField;
    private TextFieldWidget fieldWidget;
    private int mouseY;


    public AccountManagement() {
        super(new StringTextComponent("Активный аккаунт"));
        loadAccounts();
    }

    private static class Account {
        String username;
        Account(String username) {
            this.username = username;
        }
    }

    @Override
    public void init() {
        int centerX = this.width / 2;
        int centerY = this.height / 2;
        int listX = centerX - LIST_WIDTH / 2;
        int searchFieldX = centerX - 100;

        // Поисковое текстовое поле для фильтрации аккаунтов
        searchField = new TextFieldWidget(font, searchFieldX, 20, 200, TEXT_FIELD_HEIGHT, new StringTextComponent(""));
        searchField.setResponder(this::filterAccounts);
        this.children.add(searchField);
        //Текст-заполнитель для searchField
        searchField.setSuggestion("");

        int buttonY = this.height - 35;
        int buttonSpacing = BUTTON_WIDTH + 5;
        // Добавить кнопку для действий
        loginButton = addButton(new Button(centerX - 2 * buttonSpacing , buttonY, BUTTON_WIDTH, BUTTON_HEIGHT, new StringTextComponent("Войти"), button -> loginSelectedAccount()));
        deleteButton = addButton(new Button(centerX - buttonSpacing, buttonY, BUTTON_WIDTH, BUTTON_HEIGHT, new StringTextComponent("Удалить"), button -> deleteSelectedAccount()));
        addButton(new Button(centerX, buttonY, BUTTON_WIDTH, BUTTON_HEIGHT, new StringTextComponent("Добавить аккаунт"), button -> Minecraft.getInstance().displayGuiScreen(new AddAccountScreen())));
        addButton(new Button(centerX + buttonSpacing, buttonY, BUTTON_WIDTH, BUTTON_HEIGHT, new StringTextComponent("Выйти"), button -> Minecraft.getInstance().displayGuiScreen(new MainScreen())));

        // Текстовое поле для ввода имени пользователя (скрыто по умолчанию)
        fieldWidget = new TextFieldWidget(this.font, centerX - 150, 100, 300, TEXT_FIELD_HEIGHT, new StringTextComponent("Никнейм"));
        fieldWidget.setVisible(false);
        fieldWidget.setMaxStringLength(16);
        this.children.add(fieldWidget);

        // Изначально показывать все аккаунты
        filteredAccounts = new ArrayList<>(accounts);

    }


    public void addAccount(String username) {
        if (!isValidUsername(username)) {
            LOGGER.warn("Попытка с недопустимым именем пользователя: " + username);
            return;
        }
        for (Account account : accounts) {
            if (account.username.equalsIgnoreCase(username)) {
                LOGGER.warn("Попытка с дублирующимся именем пользователя: " + username);
                return; // предотвратить добавление дубликатов имен пользователей
            }
        }
        accounts.add(new Account(username));
        saveAccounts();
    }


    @Override
    public void render(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) {
        this.renderBackground(matrixStack);
        super.render(matrixStack, mouseX, mouseY, partialTicks);


        loginButton.active = selectedAccount != null;
        deleteButton.active = selectedAccount != null;
        // Обновить подсказки кнопок
        updateButtonTooltips(loginButton, deleteButton, mouseX);

        String currentUsername = Minecraft.getInstance().getSession().getUsername();
        String screenTitle = "Текущий аккаунт - " + currentUsername + "";
        drawCenteredString(matrixStack, font, screenTitle, this.width / 2, 8, COLOR_WHITE);

        int listWidth = LIST_WIDTH;
        int listX = this.width / 2 - listWidth / 2;
        int listY = ACCOUNT_LIST_START_Y;
        int visibleAccounts = MAX_LIST_HEIGHT / ACCOUNT_LIST_ENTRY_HEIGHT;
        int startIndex = scrollOffset / ACCOUNT_LIST_ENTRY_HEIGHT;
        int endIndex = Math.min(filteredAccounts.size(), startIndex + visibleAccounts);
        int maxRenderY = this.height - 35 - ACCOUNT_LIST_ENTRY_HEIGHT;

        //Отрисовка фона списка аккаунтов
        fill(matrixStack, listX, listY, listX + listWidth, listY + MAX_LIST_HEIGHT, 0x80000000);

        if (!filteredAccounts.isEmpty()) {
            for (int i = startIndex; i < endIndex; i++) {
                int entryY = listY + (i - startIndex) * ACCOUNT_LIST_ENTRY_HEIGHT - (scrollOffset % ACCOUNT_LIST_ENTRY_HEIGHT);

                if (entryY + ACCOUNT_LIST_ENTRY_HEIGHT <= maxRenderY) {
                    Account account = filteredAccounts.get(i);
                    String accountName = account.username;
                    // Отрисовка выделения для выбранного аккаунта

                    if (selectedAccount != null && accountName.equals(selectedAccount.username)) {
                        fill(matrixStack, listX, entryY, listX + listWidth, entryY + ACCOUNT_LIST_ENTRY_HEIGHT, COLOR_SELECTED);
                        fill(matrixStack, listX + 1, entryY + 1, listX + listWidth - 1, entryY + ACCOUNT_LIST_ENTRY_HEIGHT - 1, COLOR_BACKGROUND);
                    }


                    //Отрисовка иконки головы игрока
                    Minecraft.getInstance().getTextureManager().bindTexture(STEVE_SKIN);
                    GlStateManager.enableBlend();
                    drawScaledCustomSizeModalRect(listX + 2, entryY + 2, 8, 8, 8, 8, 16, 16, 64, 64);
                    GlStateManager.disableBlend();


                    //Отрисовка имени аккаунта с разным цветом для аккаунта текущей сессии
                    int textColor = accountName.equals(currentUsername) ? COLOR_GREEN : COLOR_WHITE;
                    drawString(matrixStack, font, accountName, listX + 21, entryY + 6, textColor);
                }


                //Отрисовка полосы прокрутки
                if (filteredAccounts.size() > visibleAccounts) {
                    int scrollBarHeight = MAX_LIST_HEIGHT * visibleAccounts / filteredAccounts.size();
                    int scrollBarY = listY + (scrollOffset * (MAX_LIST_HEIGHT - scrollBarHeight)) / (filteredAccounts.size() * ACCOUNT_LIST_ENTRY_HEIGHT - MAX_LIST_HEIGHT);
                    fill(matrixStack, listX + listWidth + 2, scrollBarY, listX + listWidth + 6, scrollBarY + scrollBarHeight, COLOR_WHITE);
                }
                // Отрисовка выделения, если мышь находится над определенным аккаунтом
                if (mouseX >= listX && mouseX < listX + listWidth && mouseY >= entryY && mouseY < entryY + ACCOUNT_LIST_ENTRY_HEIGHT) {
                    fill(matrixStack, listX + 2, entryY + 2, listX + 18, entryY + 18, COLOR_HIGHLIGHT);
                }

            }

        } else {
            String noAccountsText = "Аккаунт не найден!";
            drawCenteredString(matrixStack, font, noAccountsText, this.width / 2, listY + 20, COLOR_WHITE);
        }
        //Отрисовка searchField и текста-заполнителя
        searchField.render(matrixStack, mouseX, mouseY, partialTicks);
        renderSearchFieldPlaceholder(matrixStack);
        //Отрисовка textField виджета
        if (fieldWidget.getVisible()) {
            fieldWidget.render(matrixStack, mouseX, mouseY, partialTicks);
        }
    }

    private void renderSearchFieldPlaceholder(MatrixStack matrixStack) {
        String searchFieldText = "Поиск аккаунта";
        int searchFieldX = this.width / 2 - this.font.getStringWidth(searchFieldText) / 2 - 60;
        int searchFieldY = 26;
        if (!searchField.isFocused() && searchField.getText().isEmpty()) {
            this.font.drawString(matrixStack, searchFieldText, searchFieldX, searchFieldY, COLOR_HINT);
        }
    }

    private void updateButtonTooltips(Button loginButton, Button deleteButton, int mouseX) {
        if (loginButton != null) {
            loginButton.setMessage(new StringTextComponent(selectedAccount != null ? "Войти" : "Войти"));
        }
        if (deleteButton != null) {
            deleteButton.setMessage(new StringTextComponent(selectedAccount != null ? "Удалить" : "Удалить"));
        }
        if (mouseOverButton(loginButton, mouseX)) {
            renderTooltip(new StringTextComponent("Войти в выбранный аккаунт"), mouseX, mouseY);
        }
        if (mouseOverButton(deleteButton, mouseX)) {
            renderTooltip(new StringTextComponent("Удалить выбранный аккаунт"), mouseX, mouseY);
        }
    }

    private void renderTooltip(StringTextComponent войтиВВыбранныйАккаунт, int mouseX, int mouseY) {

    }

    // Вспомогательный метод для проверки, находится ли мышь над кнопкой
    private boolean mouseOverButton(Button button, int mouseX) {
        return  button != null && mouseX >= button.x && mouseX < button.x + button.getWidth() &&
                mouseY >= button.y && mouseY < button.y + button.getHeightRealms();
    }
    @Override
    public boolean mouseClicked(double mouseX, double mouseY, int button) {
        int listWidth = LIST_WIDTH;
        int listX = this.width / 2 - listWidth / 2;

        int visibleAccounts = MAX_LIST_HEIGHT / ACCOUNT_LIST_ENTRY_HEIGHT;
        int startIndex = scrollOffset / ACCOUNT_LIST_ENTRY_HEIGHT;
        int endIndex = Math.min(filteredAccounts.size(), startIndex + visibleAccounts);
        int maxRenderY = this.height - 35 - ACCOUNT_LIST_ENTRY_HEIGHT;

        if (button == 0) { //Левая кнопка мыши
            long currentTime = System.currentTimeMillis();
            for (int i = startIndex; i < endIndex; i++) {
                int entryY = ACCOUNT_LIST_START_Y + (i - startIndex) * ACCOUNT_LIST_ENTRY_HEIGHT - (scrollOffset % ACCOUNT_LIST_ENTRY_HEIGHT);
                if (entryY + ACCOUNT_LIST_ENTRY_HEIGHT <= maxRenderY && mouseX >= listX && mouseX < listX + listWidth && mouseY >= entryY && mouseY < entryY + ACCOUNT_LIST_ENTRY_HEIGHT) {
                    selectedAccount = filteredAccounts.get(i);

                    if (currentTime - lastClickTime < DOUBLE_CLICK_INTERVAL) {
                        loginSelectedAccount();
                    }
                    lastClickTime = currentTime;
                    return true;
                }
            }
        }
        return super.mouseClicked(mouseX, mouseY, button);
    }
    @Override
    public boolean mouseReleased(double mouseX, double mouseY, int button) {
        if (this.isScrolling) {
            this.isScrolling = false;
            return true;
        }
        return super.mouseReleased(mouseX, mouseY, button);
    }

    @Override
    public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) {
        if (this.isScrolling) {
            int deltaYInt = (int) mouseY - this.lastMouseY;
            this.scrollOffset -= deltaYInt;
            this.scrollOffset = Math.max(0, Math.min(this.scrollOffset, filteredAccounts.size() * ACCOUNT_LIST_ENTRY_HEIGHT - MAX_LIST_HEIGHT));
            this.lastMouseY = (int) mouseY;
            return true;
        }
        return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY);
    }

    private void filterAccounts(String query) {
        if (query.isEmpty()) {
            filteredAccounts = new ArrayList<>(accounts);
        } else {
            filteredAccounts.clear();
            for (Account account : accounts) {
                if (account.username.toLowerCase().contains(query.toLowerCase())) {
                    filteredAccounts.add(account);
                }
            }
        }
    }

    private void loginSelectedAccount() {
        if (selectedAccount != null) {
            Minecraft.getInstance().session = new Session(selectedAccount.username, "", "", "mojang");

        }
    }
    @Override
    public boolean mouseScrolled(double mouseX, double mouseY, double delta) {
        if (isMouseOverScreen(mouseX, mouseY)) {
            scrollOffset -= (int) delta * ACCOUNT_LIST_ENTRY_HEIGHT;
            int maxScroll = Math.max(0, filteredAccounts.size() * ACCOUNT_LIST_ENTRY_HEIGHT - MAX_LIST_HEIGHT);
            scrollOffset = Math.max(0, Math.min(scrollOffset, maxScroll));
            return true;
        }
        return super.mouseScrolled(mouseX, mouseY, delta);
    }

    private boolean isMouseOverScreen(double mouseX, double mouseY) {
        int listWidth = LIST_WIDTH;
        int listX = this.width / 2 - listWidth / 2;
        int listY = ACCOUNT_LIST_START_Y;
        return mouseX >= listX && mouseX < listX + listWidth && mouseY >= listY && mouseY < listY + MAX_LIST_HEIGHT;
    }

    private void deleteSelectedAccount() {
        if (selectedAccount != null) {
            accounts.remove(selectedAccount);
            saveAccounts();
            selectedAccount = null;
        }
    }

    // Проверить, является ли имя пользователя допустимым
    private boolean isValidUsername(String username) {
        if (username == null || username.length() < 3 || username.length() > 16) {
            return false;
        }
        return username.matches("[a-zA-Z0-9-_]+");
    }

    // Сохранить аккаунты в файл
    private void saveAccounts() {
        try (PrintWriter out = new PrintWriter(Files.newBufferedWriter(Paths.get(ACCOUNTS_FILE_PATH)))) {
            Set<String> uniqueUsernames = new HashSet<>();
            for (Account account : accounts) {
                if (uniqueUsernames.add(account.username.toLowerCase()) && isValidUsername(account.username)) {
                    out.println(account.username);
                }
            }
        } catch (IOException e) {
            LOGGER.error("Не удалось сохранить аккаунты", e);
        }
    }


    // Загрузить аккаунты из файла
    private void loadAccounts() {
        File file = new File(ACCOUNTS_FILE_PATH);
        if (file.exists()) {
            try (Scanner scanner = new Scanner(file)) {
                accounts.clear();
                Set<String> uniqueUsernames = new HashSet<>();
                while (scanner.hasNextLine()) {
                    String username = scanner.nextLine();
                    if (uniqueUsernames.add(username.toLowerCase()) && isValidUsername(username)) {
                        accounts.add(new Account(username));
                    }
                }
            } catch (IOException e) {
                LOGGER.error("Не удалось загрузить аккаунты", e);
            }
        }
        if (searchField != null) {
            filterAccounts(searchField.getText());
        }
    }

    @Override
    public void onClose() {
        saveAccounts();
        super.onClose();
    }
}
Код:
 y += 34 - 1.5f;
        buttons.add(new Button(x + 30, y + 14, widthButton - 140, 68 - 45, "Account", () -> mc.displayGuiScreen(new AccountManagement())));
скинь addaccountscreen пожалуйста
 
Начинающий
Статус
Оффлайн
Регистрация
30 Сен 2023
Сообщения
4
Реакции[?]
0
Поинты[?]
0
скинь addaccountscreen пожалуйста
Код:
package im.expensive.another.screen;

import com.mojang.blaze3d.matrix.MatrixStack;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.client.gui.widget.button.Button;
import net.minecraft.util.Session;
import net.minecraft.util.text.StringTextComponent;

import java.util.Random;

public class AddAccountScreen extends Screen {
    private TextFieldWidget fieldWidget;
    private Button loginButton;
    private Button randomButton;
    private int textWidth = 200;
    private int buttonHeight = 20;
    private int randomButtonWidth = 50;
    private int loginButtonWidth = 150;
    String currentUsername = Minecraft.getInstance().getSession().getUsername();
    AccountManagement accountManagement = new AccountManagement();

    public AddAccountScreen() {
        super(new StringTextComponent("Add New Account"));
    }

    @Override
    public void init(Minecraft minecraft, int width, int height) {
        super.init(minecraft, width, height);

        int textFieldX = this.width / 2 - textWidth / 2;
        int textFieldY = this.height / 2 - 60;
        int buttonY = textFieldY + 25;

        fieldWidget = new TextFieldWidget(font, textFieldX, textFieldY, textWidth, 20, new StringTextComponent("Account")) {
            @Override
            public boolean charTyped(char codePoint, int modifiers) {
                if (Character.toString(codePoint).matches("[a-zA-Z0-9]") || codePoint == '\b') {
                    return super.charTyped(codePoint, modifiers);
                }
                return false;
            }
        };
        fieldWidget.setMaxStringLength(16);
        addButton(fieldWidget);

        loginButton = new Button(textFieldX, buttonY, loginButtonWidth, buttonHeight, new StringTextComponent("Login"), button -> {
            String username = fieldWidget.getText().trim();
            if (!username.isEmpty()) {
                accountManagement.addAccount(username);
                Minecraft.getInstance().displayGuiScreen(new AccountManagement());
            }
        });
        addButton(loginButton);

        randomButton = new Button(textFieldX + loginButtonWidth, buttonY, randomButtonWidth, buttonHeight, new StringTextComponent("Random"), button -> {
            Random random = new Random();
            String randomNick = "paster" + (100 + random.nextInt(899));
            fieldWidget.setText(randomNick);
        });
        addButton(randomButton);

        Button cancelButton = new Button(textFieldX, buttonY + 25, textWidth, buttonHeight, new StringTextComponent("Отмена"), button -> {
            Minecraft.getInstance().displayGuiScreen(new AccountManagement());
        });
        addButton(cancelButton);
    }

    @Override
    public void tick() {
        super.tick();
        fieldWidget.tick();
        loginButton.active = fieldWidget.getText().trim().length() >= 3;
    }

    @Override
    public void render(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) {
        this.renderDirtBackground(0);
        super.render(matrixStack, mouseX, mouseY, partialTicks);

        fieldWidget.render(matrixStack, mouseX, mouseY, partialTicks);
        loginButton.render(matrixStack, mouseX, mouseY, partialTicks);
        randomButton.render(matrixStack, mouseX, mouseY, partialTicks);

        if (fieldWidget.getText().isEmpty()) {
            drawString(matrixStack, font, "Enter name...", width / 2 - textWidth / 2, height / 2 - 75, 0xCCCCCC);
        }

        if (!fieldWidget.getText().isEmpty()) {
            drawString(matrixStack, font, "Enter name", width / 2 - textWidth / 2, height / 2 - 75, 0xCCCCCC);
        }

        if (mouseOverButton(loginButton, mouseX, mouseY)) {
            if (!loginButton.active) {
                renderTooltip(matrixStack, new StringTextComponent("Enter at least 3 characters"), mouseX, mouseY);
            } else {
                renderTooltip(matrixStack, new StringTextComponent("Click to login"), mouseX, mouseY);
            }
        }

        if (mouseOverButton(randomButton, mouseX, mouseY)) {
            renderTooltip(matrixStack, new StringTextComponent("Click to generate a random username"), mouseX, mouseY);
        }

        drawCenteredString(matrixStack, font, "Login account info", this.width / 2, 10, 0xFFFFFF);

    }

    private boolean mouseOverButton(Button button, int mouseX, int mouseY) {

        int buttonX1 = button.x;
        int buttonY1 = button.y;
        int buttonX2 = button.x + button.getWidth();
        int buttonY2 = button.y + button.getHeightRealms();

        return mouseX >= buttonX1 && mouseY >= buttonY1 && mouseX < buttonX2 && mouseY < buttonY2;
    }
}
 
Начинающий
Статус
Оффлайн
Регистрация
3 Янв 2025
Сообщения
140
Реакции[?]
3
Поинты[?]
1K
Код:
package im.expensive.another.screen;

import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.platform.GlStateManager;
import im.expensive.ui.mainmenu.MainScreen;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.client.gui.widget.button.Button;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.Session;
import net.minecraft.util.text.StringTextComponent;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.*;


public class AccountManagement extends Screen {

    private static final Logger LOGGER = LogManager.getLogger();
    private static final long DOUBLE_CLICK_INTERVAL = 250;
    private static final int ACCOUNT_LIST_START_Y = 45;
    private static final int ACCOUNT_LIST_ENTRY_HEIGHT = 20;
    private static final int MAX_LIST_HEIGHT = 400;
    private static final int LIST_WIDTH = 400;
    private static final int BUTTON_WIDTH = 100;
    private static final int BUTTON_HEIGHT = 20;
    private static final int TEXT_FIELD_HEIGHT = 20;
    private static final int COLOR_SELECTED = new Color(124, 124, 125, 255).getRGB();
    private static final int COLOR_BACKGROUND = new Color(0, 0, 0, 255).getRGB();
    private static final int COLOR_HIGHLIGHT = new Color(0, 0, 0, 100).getRGB();
    private static final int COLOR_WHITE = 0xFFFFFF;
    private static final int COLOR_GREEN = 0x00FF00;
    private static final int COLOR_HINT = 0xCCCCCC;
    private static final ResourceLocation STEVE_SKIN = new ResourceLocation("textures/entity/steve.png");
    private static final String ACCOUNTS_FILE_PATH = "Clouse/files/accounts.clouse";

    private long lastClickTime = 0;
    private boolean isScrolling = false;
    private int lastMouseY = 0;
    private int scrollOffset = 0;
    private Button loginButton;
    private Button deleteButton;
    private static List<Account> filteredAccounts = new ArrayList<>();
    private static final List<Account> accounts = new ArrayList<>();
    private Account selectedAccount = null;
    private static TextFieldWidget searchField;
    private TextFieldWidget fieldWidget;
    private int mouseY;


    public AccountManagement() {
        super(new StringTextComponent("Активный аккаунт"));
        loadAccounts();
    }

    private static class Account {
        String username;
        Account(String username) {
            this.username = username;
        }
    }

    @Override
    public void init() {
        int centerX = this.width / 2;
        int centerY = this.height / 2;
        int listX = centerX - LIST_WIDTH / 2;
        int searchFieldX = centerX - 100;

        // Поисковое текстовое поле для фильтрации аккаунтов
        searchField = new TextFieldWidget(font, searchFieldX, 20, 200, TEXT_FIELD_HEIGHT, new StringTextComponent(""));
        searchField.setResponder(this::filterAccounts);
        this.children.add(searchField);
        //Текст-заполнитель для searchField
        searchField.setSuggestion("");

        int buttonY = this.height - 35;
        int buttonSpacing = BUTTON_WIDTH + 5;
        // Добавить кнопку для действий
        loginButton = addButton(new Button(centerX - 2 * buttonSpacing , buttonY, BUTTON_WIDTH, BUTTON_HEIGHT, new StringTextComponent("Войти"), button -> loginSelectedAccount()));
        deleteButton = addButton(new Button(centerX - buttonSpacing, buttonY, BUTTON_WIDTH, BUTTON_HEIGHT, new StringTextComponent("Удалить"), button -> deleteSelectedAccount()));
        addButton(new Button(centerX, buttonY, BUTTON_WIDTH, BUTTON_HEIGHT, new StringTextComponent("Добавить аккаунт"), button -> Minecraft.getInstance().displayGuiScreen(new AddAccountScreen())));
        addButton(new Button(centerX + buttonSpacing, buttonY, BUTTON_WIDTH, BUTTON_HEIGHT, new StringTextComponent("Выйти"), button -> Minecraft.getInstance().displayGuiScreen(new MainScreen())));

        // Текстовое поле для ввода имени пользователя (скрыто по умолчанию)
        fieldWidget = new TextFieldWidget(this.font, centerX - 150, 100, 300, TEXT_FIELD_HEIGHT, new StringTextComponent("Никнейм"));
        fieldWidget.setVisible(false);
        fieldWidget.setMaxStringLength(16);
        this.children.add(fieldWidget);

        // Изначально показывать все аккаунты
        filteredAccounts = new ArrayList<>(accounts);

    }


    public void addAccount(String username) {
        if (!isValidUsername(username)) {
            LOGGER.warn("Попытка с недопустимым именем пользователя: " + username);
            return;
        }
        for (Account account : accounts) {
            if (account.username.equalsIgnoreCase(username)) {
                LOGGER.warn("Попытка с дублирующимся именем пользователя: " + username);
                return; // предотвратить добавление дубликатов имен пользователей
            }
        }
        accounts.add(new Account(username));
        saveAccounts();
    }


    @Override
    public void render(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) {
        this.renderBackground(matrixStack);
        super.render(matrixStack, mouseX, mouseY, partialTicks);


        loginButton.active = selectedAccount != null;
        deleteButton.active = selectedAccount != null;
        // Обновить подсказки кнопок
        updateButtonTooltips(loginButton, deleteButton, mouseX);

        String currentUsername = Minecraft.getInstance().getSession().getUsername();
        String screenTitle = "Текущий аккаунт - " + currentUsername + "";
        drawCenteredString(matrixStack, font, screenTitle, this.width / 2, 8, COLOR_WHITE);

        int listWidth = LIST_WIDTH;
        int listX = this.width / 2 - listWidth / 2;
        int listY = ACCOUNT_LIST_START_Y;
        int visibleAccounts = MAX_LIST_HEIGHT / ACCOUNT_LIST_ENTRY_HEIGHT;
        int startIndex = scrollOffset / ACCOUNT_LIST_ENTRY_HEIGHT;
        int endIndex = Math.min(filteredAccounts.size(), startIndex + visibleAccounts);
        int maxRenderY = this.height - 35 - ACCOUNT_LIST_ENTRY_HEIGHT;

        //Отрисовка фона списка аккаунтов
        fill(matrixStack, listX, listY, listX + listWidth, listY + MAX_LIST_HEIGHT, 0x80000000);

        if (!filteredAccounts.isEmpty()) {
            for (int i = startIndex; i < endIndex; i++) {
                int entryY = listY + (i - startIndex) * ACCOUNT_LIST_ENTRY_HEIGHT - (scrollOffset % ACCOUNT_LIST_ENTRY_HEIGHT);

                if (entryY + ACCOUNT_LIST_ENTRY_HEIGHT <= maxRenderY) {
                    Account account = filteredAccounts.get(i);
                    String accountName = account.username;
                    // Отрисовка выделения для выбранного аккаунта

                    if (selectedAccount != null && accountName.equals(selectedAccount.username)) {
                        fill(matrixStack, listX, entryY, listX + listWidth, entryY + ACCOUNT_LIST_ENTRY_HEIGHT, COLOR_SELECTED);
                        fill(matrixStack, listX + 1, entryY + 1, listX + listWidth - 1, entryY + ACCOUNT_LIST_ENTRY_HEIGHT - 1, COLOR_BACKGROUND);
                    }


                    //Отрисовка иконки головы игрока
                    Minecraft.getInstance().getTextureManager().bindTexture(STEVE_SKIN);
                    GlStateManager.enableBlend();
                    drawScaledCustomSizeModalRect(listX + 2, entryY + 2, 8, 8, 8, 8, 16, 16, 64, 64);
                    GlStateManager.disableBlend();


                    //Отрисовка имени аккаунта с разным цветом для аккаунта текущей сессии
                    int textColor = accountName.equals(currentUsername) ? COLOR_GREEN : COLOR_WHITE;
                    drawString(matrixStack, font, accountName, listX + 21, entryY + 6, textColor);
                }


                //Отрисовка полосы прокрутки
                if (filteredAccounts.size() > visibleAccounts) {
                    int scrollBarHeight = MAX_LIST_HEIGHT * visibleAccounts / filteredAccounts.size();
                    int scrollBarY = listY + (scrollOffset * (MAX_LIST_HEIGHT - scrollBarHeight)) / (filteredAccounts.size() * ACCOUNT_LIST_ENTRY_HEIGHT - MAX_LIST_HEIGHT);
                    fill(matrixStack, listX + listWidth + 2, scrollBarY, listX + listWidth + 6, scrollBarY + scrollBarHeight, COLOR_WHITE);
                }
                // Отрисовка выделения, если мышь находится над определенным аккаунтом
                if (mouseX >= listX && mouseX < listX + listWidth && mouseY >= entryY && mouseY < entryY + ACCOUNT_LIST_ENTRY_HEIGHT) {
                    fill(matrixStack, listX + 2, entryY + 2, listX + 18, entryY + 18, COLOR_HIGHLIGHT);
                }

            }

        } else {
            String noAccountsText = "Аккаунт не найден!";
            drawCenteredString(matrixStack, font, noAccountsText, this.width / 2, listY + 20, COLOR_WHITE);
        }
        //Отрисовка searchField и текста-заполнителя
        searchField.render(matrixStack, mouseX, mouseY, partialTicks);
        renderSearchFieldPlaceholder(matrixStack);
        //Отрисовка textField виджета
        if (fieldWidget.getVisible()) {
            fieldWidget.render(matrixStack, mouseX, mouseY, partialTicks);
        }
    }

    private void renderSearchFieldPlaceholder(MatrixStack matrixStack) {
        String searchFieldText = "Поиск аккаунта";
        int searchFieldX = this.width / 2 - this.font.getStringWidth(searchFieldText) / 2 - 60;
        int searchFieldY = 26;
        if (!searchField.isFocused() && searchField.getText().isEmpty()) {
            this.font.drawString(matrixStack, searchFieldText, searchFieldX, searchFieldY, COLOR_HINT);
        }
    }

    private void updateButtonTooltips(Button loginButton, Button deleteButton, int mouseX) {
        if (loginButton != null) {
            loginButton.setMessage(new StringTextComponent(selectedAccount != null ? "Войти" : "Войти"));
        }
        if (deleteButton != null) {
            deleteButton.setMessage(new StringTextComponent(selectedAccount != null ? "Удалить" : "Удалить"));
        }
        if (mouseOverButton(loginButton, mouseX)) {
            renderTooltip(new StringTextComponent("Войти в выбранный аккаунт"), mouseX, mouseY);
        }
        if (mouseOverButton(deleteButton, mouseX)) {
            renderTooltip(new StringTextComponent("Удалить выбранный аккаунт"), mouseX, mouseY);
        }
    }

    private void renderTooltip(StringTextComponent войтиВВыбранныйАккаунт, int mouseX, int mouseY) {

    }

    // Вспомогательный метод для проверки, находится ли мышь над кнопкой
    private boolean mouseOverButton(Button button, int mouseX) {
        return  button != null && mouseX >= button.x && mouseX < button.x + button.getWidth() &&
                mouseY >= button.y && mouseY < button.y + button.getHeightRealms();
    }
    @Override
    public boolean mouseClicked(double mouseX, double mouseY, int button) {
        int listWidth = LIST_WIDTH;
        int listX = this.width / 2 - listWidth / 2;

        int visibleAccounts = MAX_LIST_HEIGHT / ACCOUNT_LIST_ENTRY_HEIGHT;
        int startIndex = scrollOffset / ACCOUNT_LIST_ENTRY_HEIGHT;
        int endIndex = Math.min(filteredAccounts.size(), startIndex + visibleAccounts);
        int maxRenderY = this.height - 35 - ACCOUNT_LIST_ENTRY_HEIGHT;

        if (button == 0) { //Левая кнопка мыши
            long currentTime = System.currentTimeMillis();
            for (int i = startIndex; i < endIndex; i++) {
                int entryY = ACCOUNT_LIST_START_Y + (i - startIndex) * ACCOUNT_LIST_ENTRY_HEIGHT - (scrollOffset % ACCOUNT_LIST_ENTRY_HEIGHT);
                if (entryY + ACCOUNT_LIST_ENTRY_HEIGHT <= maxRenderY && mouseX >= listX && mouseX < listX + listWidth && mouseY >= entryY && mouseY < entryY + ACCOUNT_LIST_ENTRY_HEIGHT) {
                    selectedAccount = filteredAccounts.get(i);

                    if (currentTime - lastClickTime < DOUBLE_CLICK_INTERVAL) {
                        loginSelectedAccount();
                    }
                    lastClickTime = currentTime;
                    return true;
                }
            }
        }
        return super.mouseClicked(mouseX, mouseY, button);
    }
    @Override
    public boolean mouseReleased(double mouseX, double mouseY, int button) {
        if (this.isScrolling) {
            this.isScrolling = false;
            return true;
        }
        return super.mouseReleased(mouseX, mouseY, button);
    }

    @Override
    public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) {
        if (this.isScrolling) {
            int deltaYInt = (int) mouseY - this.lastMouseY;
            this.scrollOffset -= deltaYInt;
            this.scrollOffset = Math.max(0, Math.min(this.scrollOffset, filteredAccounts.size() * ACCOUNT_LIST_ENTRY_HEIGHT - MAX_LIST_HEIGHT));
            this.lastMouseY = (int) mouseY;
            return true;
        }
        return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY);
    }

    private void filterAccounts(String query) {
        if (query.isEmpty()) {
            filteredAccounts = new ArrayList<>(accounts);
        } else {
            filteredAccounts.clear();
            for (Account account : accounts) {
                if (account.username.toLowerCase().contains(query.toLowerCase())) {
                    filteredAccounts.add(account);
                }
            }
        }
    }

    private void loginSelectedAccount() {
        if (selectedAccount != null) {
            Minecraft.getInstance().session = new Session(selectedAccount.username, "", "", "mojang");

        }
    }
    @Override
    public boolean mouseScrolled(double mouseX, double mouseY, double delta) {
        if (isMouseOverScreen(mouseX, mouseY)) {
            scrollOffset -= (int) delta * ACCOUNT_LIST_ENTRY_HEIGHT;
            int maxScroll = Math.max(0, filteredAccounts.size() * ACCOUNT_LIST_ENTRY_HEIGHT - MAX_LIST_HEIGHT);
            scrollOffset = Math.max(0, Math.min(scrollOffset, maxScroll));
            return true;
        }
        return super.mouseScrolled(mouseX, mouseY, delta);
    }

    private boolean isMouseOverScreen(double mouseX, double mouseY) {
        int listWidth = LIST_WIDTH;
        int listX = this.width / 2 - listWidth / 2;
        int listY = ACCOUNT_LIST_START_Y;
        return mouseX >= listX && mouseX < listX + listWidth && mouseY >= listY && mouseY < listY + MAX_LIST_HEIGHT;
    }

    private void deleteSelectedAccount() {
        if (selectedAccount != null) {
            accounts.remove(selectedAccount);
            saveAccounts();
            selectedAccount = null;
        }
    }

    // Проверить, является ли имя пользователя допустимым
    private boolean isValidUsername(String username) {
        if (username == null || username.length() < 3 || username.length() > 16) {
            return false;
        }
        return username.matches("[a-zA-Z0-9-_]+");
    }

    // Сохранить аккаунты в файл
    private void saveAccounts() {
        try (PrintWriter out = new PrintWriter(Files.newBufferedWriter(Paths.get(ACCOUNTS_FILE_PATH)))) {
            Set<String> uniqueUsernames = new HashSet<>();
            for (Account account : accounts) {
                if (uniqueUsernames.add(account.username.toLowerCase()) && isValidUsername(account.username)) {
                    out.println(account.username);
                }
            }
        } catch (IOException e) {
            LOGGER.error("Не удалось сохранить аккаунты", e);
        }
    }


    // Загрузить аккаунты из файла
    private void loadAccounts() {
        File file = new File(ACCOUNTS_FILE_PATH);
        if (file.exists()) {
            try (Scanner scanner = new Scanner(file)) {
                accounts.clear();
                Set<String> uniqueUsernames = new HashSet<>();
                while (scanner.hasNextLine()) {
                    String username = scanner.nextLine();
                    if (uniqueUsernames.add(username.toLowerCase()) && isValidUsername(username)) {
                        accounts.add(new Account(username));
                    }
                }
            } catch (IOException e) {
                LOGGER.error("Не удалось загрузить аккаунты", e);
            }
        }
        if (searchField != null) {
            filterAccounts(searchField.getText());
        }
    }

    @Override
    public void onClose() {
        saveAccounts();
        super.onClose();
    }
}
Код:
 y += 34 - 1.5f;
        buttons.add(new Button(x + 30, y + 14, widthButton - 140, 68 - 45, "Account", () -> mc.displayGuiScreen(new AccountManagement())));
Привет а если я в дефолт MainMenu хочу сделать я в самом коде поменял с MainScreen на MainMenuScreen но как мне добавить кнопку я пробовал в MainMenuScreen но не смог написать
Привет а если я в дефолт MainMenu майна хочу сделать я в самом коде поменял с MainScreen на MainMenuScreen но как мне добавить кнопку я пробовал в MainMenuScreen но не смог написать
 
Сверху Снизу