Войти или зарегистрироваться
  • Вы находитесь в сообществе Rubukkit. Мы - администраторы серверов Minecraft, разрабатываем собственные плагины и переводим на различные языки плагины наших коллег из других стран.

Туториал Делаем кнопки "Зайти на сервер", "Обновить" и отображение кол-ва игроков в гл. меню.

gamerforEA

Старожил
Пользователь
Баллы
143
Имя в Minecraft
gamerforEA_MCPC
  1. Открываем класс net.minecraft.client.gui.GuiMultiplayer.
  2. В конец метода initGui() добавляем:
    Java:
    this.mc.displayGuiScreen(new GuiMainMenu());
  3. Создаём класс PingTask и добавляем в него:
    Java:
    public class PingTask extends FutureTask<PingTask.AdvServerData>
    {
        private boolean isOnline = false;
    
        public PingTask(final String ip, final OldServerPinger pinger)
        {
            super(new Callable<PingTask.AdvServerData>()
            {
                @Override
                public AdvServerData call()
                {
                    AdvServerData data = new AdvServerData(ip);
                    try
                    {
                        pinger.func_147224_a(data);
                        data.isOnline = true;
                    }
                    catch (Exception e)
                    {
                        data.isOnline = false;
                    }
                    return data;
                }
            });
        }
       
        public static class AdvServerData extends ServerData
        {
            public boolean isOnline;
    
            public AdvServerData(String ip)
            {
                super("", ip);
            }
        }
    }
  4. Открываем класс net.minecraft.client.gui.GuiMainMenu.
  5. В самое начало ТЕЛА класса добавляем:
    Java:
    private static final String defText = "Зайти на сервер";
    private static final String disabledText = "Сервер выключен";
    private static final String pingingText = "Пингование сервера...";
    private static final String ip = "mc.hypixel.net:25565";
    private OldServerPinger pinger = new OldServerPinger();
    private PingTask pingTask;
    private GuiButton joinButton;
  6. В конец метода GuiMainMenu() добавляем:
    Java:
    FMLClientHandler.instance().setupServerList();
  7. В начало метода updateScreen() добавляем:
    Java:
    this.pinger.func_147223_a();
    if (this.pingTask != null && this.pingTask.isDone())
    {
        try
        {
            AdvServerData data = this.pingTask.get();
            if (data.isOnline)
            {
                if (Strings.isNullOrEmpty(data.populationInfo)) this.joinButton.displayString = pingingText;
                else
                {
                    this.joinButton.displayString = defText + " [" + data.populationInfo + "§f]";
                    this.pingTask = null;
                }
            }
            else this.joinButton.displayString = disabledText;
        }
        catch (Exception e)
        {
        }
    }
  8. После метода из пункта 7 добавляем:
    Java:
    public void onGuiClosed()
    {
        this.pinger.func_147226_b();
    }
    
    private void ping()
    {
        if (this.pingTask != null && !this.pingTask.isCancelled()) this.pingTask.cancel(false);
        Thread t = new Thread(this.pingTask = new PingTask(ip, this.pinger));
        t.setDaemon(true);
        t.start();
        this.joinButton.displayString = pingingText;
    }
  9. В методе addSingleplayerMultiplayerButtons(int, int) заменяем:
    Java:
    this.buttonList.add(new GuiButton(2, this.width / 2 - 100, p_73969_1_ + p_73969_2_ * 1, I18n.format("menu.multiplayer", new Object[0])));
    на:
    Java:
    boolean needPing = this.joinButton == null;
    this.buttonList.add(this.joinButton = new GuiButton(2, this.width / 2 - 100, p_73969_1_ + p_73969_2_, needPing ? pingingText : this.joinButton.displayString));
    if (needPing) this.ping();
    GuiButton updateButton = new GuiButton(100, this.width / 2 + 102, p_73969_1_ + p_73969_2_, "Обновить");
    updateButton.width = 50;
    this.buttonList.add(updateButton);
  10. В начале метода actionPerformed(GuiButton) добавляем:
    Java:
    if (p_146284_1_.id == 100) this.ping();
  11. В методе из пункта 10 заменяем:
    Java:
    this.mc.displayGuiScreen(new GuiMultiplayer(this));
    на:
    Java:
    FMLClientHandler.instance().connectToServer(new GuiMultiplayer(this), new AdvServerData(ip));

  1. Устанавливаем MCP (этому я учить не буду).
  2. В папке 'src/minecraft/net/minecraft/client/gui' открываем файл 'GuiMultiplayer'.
  3. Находим метод func_74017_b и заменяем private на public.
  4. Создаём класс Pinger, расширяющий класс Thread, со следующим кодом:
    Java:
    private volatile boolean finishedThread = false;
        private volatile boolean finishedPing = false;
        private volatile boolean offline = false;
        private volatile boolean sdWasUsed = false;
        private volatile boolean ping = false;
        private volatile ServerData sd;
       
        public Pinger() {
            this.setDaemon(true);
            this.setName("Pinger");
        }
       
        @Override
        public void run() {
            do if(this.finishedThread) return;
            else if(this.ping) {
                this.ping = false;
                this.offline = false;
                this.finishedPing = false;
                this.sdWasUsed = false;
                try {
                    GuiMultiplayer.func_74017_b(this.sd);
                } catch (Exception e) {
                    this.offline = true;
                }
                this.finishedPing = true;
            }
            while(true);
        }
       
        public void finish() {
            this.finishedThread = true;
        }
       
        public void setServerData(ServerData sd) {
            this.sdWasUsed = false;
            this.sd = sd;
        }
       
        public ServerData getServerData() {
            this.sdWasUsed = true;
            return this.sd;
        }
       
        public void ping() {
            this.ping = true;
        }
       
        public boolean isFinished() {
            return this.finishedPing;
        }
       
        public boolean isOffline() {
            return this.offline;
        }
       
        public boolean isUsed() {
            return this.sdWasUsed;
        }
  5. В папке с 'GuiMultiplayer' открываем файл 'GuiMainMenu'.
  6. Добавляем поля:
    Java:
    private ServerData sd = new ServerData("", "127.0.0.1");
    private GuiButton multiplayerButton;
    private Pinger pinger;
  7. Находим метод addSingleplayerMultiplayerButtons и меняем строку
    Java:
    this.multiplayerButton = new GuiButton(2, this.width / 2 - 100, par1 + par2 * 1, "Сервер выключен");
    if(this.pinger == null || !this.pinger.isAlive())
    {
           this.pinger = new Pinger();
           this.pinger.start();
           this.pinger.setServerData(this.sd);
           this.pinger.ping();
    }
    this.buttonList.add(multiplayerButton);
    GuiButton updateButton = new GuiButton(21, this.width / 2 + 102, par1 + par2 * 1, "Обновить");
    updateButton.width = 50;
    this.buttonList.add(updateButton);
  8. Находим метод updateScreen и добавляем в его конец следующий код:
    Java:
    if(this.pinger.isAlive()) {
                if(!this.pinger.isUsed()) {
                    if(this.pinger.isFinished()) {
                        this.sd = this.pinger.getServerData();
                        if(!this.pinger.isOffline()) {
                            this.multiplayerButton.displayString = "§fЗайти на сервер [" + this.sd.populationInfo + "§f]";
                        } else {
                            this.multiplayerButton.displayString = "Сервер выключен";
                        }
                    }
                }
            }
  9. Добавляем следующий метод:
    Java:
    public void onGuiClosed() {
            this.pinger.finish();
        }
  10. Находим метод actionPerformed и меняем строку
    Java:
    this.mc.displayGuiScreen(new GuiMultiplayer(this));
    на следующий код:
    Java:
    this.mc.displayGuiScreen(new GuiConnecting(this, this.mc, this.sd));
  11. В этот же метод добавляем этот код:
    Java:
    if (par1GuiButton.id == 21) {
                this.pinger.ping();
    }

  1. Устанавливаем MCP (этому я учить не буду).
  2. В папке 'src/minecraft/net/minecraft/client/gui' открываем файл 'GuiMultiplayer'.
  3. Находим метод func_74017_b и заменяем private на public.
  4. В этой же папке открываем файл 'GuiMainMenu'.
  5. Добавляем поля:
    Java:
    private ServerData sd = new ServerData("", "127.0.0.1");
    private GuiButton multiplayerButton;
  6. Находим метод addSingleplayerMultiplayerButtons и меняем строку
    Java:
    this.buttonList.add(new GuiButton(2, this.width / 2 - 100, par1 + par2 * 1, par3StringTranslate.translateKey("menu.multiplayer")));
    на этот код:
    Java:
    this.multiplayerButton = new GuiButton(2, this.width / 2 - 100, par1 + par2 * 1, "");
    try {
                GuiMultiplayer.func_74017_b(sd);
                 this.multiplayerButton.displayString = "§fЗайти на сервер [" + this.sd.populationInfo + "§f]";
    } catch (IOException e) {
                 this.multiplayerButton.displayString = "Сервер выключен";
    }
    this.buttonList.add(this.multiplayerButton);
    GuiButton updateButton = new GuiButton(21, this.width / 2 + 102, par1 + par2 * 1, "Обновить");
    updateButton.width = 50;
    this.buttonList.add(updateButton);
  7. Находим метод actionPerformed и меняем строку
    Java:
    this.mc.displayGuiScreen(new GuiMultiplayer(this));
    на следующий код:
    Java:
    this.mc.displayGuiScreen(new GuiConnecting(this, this.mc, this.sd));
  8. В этот же метод добавляем этот код:
    Java:
    if (par1GuiButton.id == 21) {            
    try {                
    GuiMultiplayer.func_74017_b(this.sd);                
    this.multiplayerButton.displayString = "§fЗайти на сервер [" + sd.populationInfo + "§f]";            
    } catch (IOException e) {                
    this.multiplayerButton.displayString = "Сервер выключен";            
    }
    }

  1. Находим класс GUI, в котором мы хотим добавить выключение кнопки.
  2. Добавляем следующие поля:
    Java:
    private static int ticksCount = 0;
    private static int freezeTime = <время выключения, умноженное на 20>;
  3. Находим метод updateScreen и добавляем в него следующий код:
    Java:
    if (BUTTON.enabled == false) {
                 this.ticksCount++;
                if (this.ticksCount == this.freezeTime) {
                    BUTTON.enabled = true;
                }
    }
  4. Находим в методе actionPerformed обработчик нужной нам кнопки и добавляем в этот обработчик следующий код:
    Java:
    this.ticksCount = 0;
    BUTTON.enabled = false;
Вместо BUTTON необходимо вставить указатель на объект GuiButton (например, minecraftRealmsButton).


П - проблема, Р - решение.

П: Forge "ругается" на невалидные классы.
Р: Необходимо добавить следующие JVM флаги:
Код:
-Dfml.ignoreInvalidMinecraftCertificates=true -Dfml.ignorePatchDiscrepancies=true

П: ForgeGradle не обфусцирует классы.
Р: Классы можно обфусцировать вручную с помощью BON.

П: ForgeGradle превращает кириллицу в иероглифы.
Р: В файл build.gradle после строки "apply plugin: 'forge'" добавляем следующий текст:
Код:
[ compileJava, compileTestJava ]*.options*.encoding = 'UTF-8'

ВНИМАНИЕ: После какого-то обновление Forge требуется написать новую реализацию под 1.7.10.
 
Последнее редактирование:
=(
M31zYVB.png
В обновлённой инструкции добавлена проверка на null.
 
А скрины результата есть? Просто у меня полная муть получилась
 
На:
1sZeljo.png

=======================================================================
GtwDBuE.png
Кстати кнопка "Обновить" не работает, и можно ли как то убрать что при кике и не только ты оказывался в главном меню а не в мультиплеере.
Странно, у меня всё прекрасно работает. Про кик я не понял. Объясните (не забывайте про знаки препинания).
 
Последнее редактирование:
Добавил инструкцию для 1.5.2 (отличий от 1.6.4 почти нет). Всё протестировал - работает.
 
Добавил инструкцию для 1.5.2 (отличий от 1.6.4 почти нет). Всё протестировал - работает.
Есть вопрос. На одном из клиентов видел кнопку "Обновить" которая неактивна некоторое время(6 секунд) после нажатия. Как сделать ее?
 
Есть вопрос. На одном из клиентов видел кнопку "Обновить" которая неактивна некоторое время(6 секунд) после нажатия. Как сделать ее?
Самое примитивное:
  1. При нажатии кнопки записываем в какое-нибудь поле текущее время.
  2. Каждое обновление интерфейса проверяем время и записываем его в какое-нибудь второе поле.
  3. Делаем проверку подобного типа:
    Код:
    if ((time1 + 6) == time2) {button.enabled = true;}
Это самое простое. Для того, чтобы можно было такое использовать, необходимо добавить некоторые проверки.
UPD: Сейчас сделаю нормальный код для выключения кнопки на указанное время.
Добавил в шапку инструкцию по выключению кнопки на указанное время после нажатия (можно использовать для кнопки "Обновить").
 
Последнее редактирование:
Самое примитивное:
  1. При нажатии кнопки записываем в какое-нибудь поле текущее время.
  2. Каждое обновление интерфейса проверяем время и записываем его в какое-нибудь второе поле.
  3. Делаем проверку подобного типа:
    Код:
    if ((time1 + 6) == time2) {button.enabled = true;}
Это самое простое. Для того, чтобы можно было такое использовать, необходимо добавить некоторые проверки.
UPD: Сейчас сделаю нормальный код для выключения кнопки на указанное время.
Добавил в шапку инструкцию по выключению кнопки на указанное время после нажатия (можно использовать для кнопки "Обновить").
С таймером так и не получилось. Сделал все по инструкции, в итоге кнопка "Обновить" исчезла.:cry:
 
С таймером так и не получилось. Сделал все по инструкции, в итоге кнопка "Обновить" исчезла.:cry:
Если бы всё делали правильно, то ничего бы не исчезло. Я делал проверку на нескольких кнопках. Ладно, сейчас запишу видео.
Добавил в шапку видео-туториалы.
 
Последнее редактирование:
Если бы всё делали правильно, то ничего бы не исчезло. Я делал проверку на нескольких кнопках. Ладно, сейчас запишу видео.
Добавил в шапку видео-туториалы.
Итого - Решил сделать таймер на кнопке обновить в GuiMultiplayer, в результате - таймер не работает. Код ниже
Что я неправильно делаю?

UPD^: Небольшая странность, при перемещении
Код:
                ticksCount = 0;
                refreshbutton.enabled = false;
в самый верх метода actionPerformed таймер работает, но кнопка не выполняет никаких действий.
 

Поделиться этой страницей

Назад
Верх