1. Этот сайт использует файлы cookie. Продолжая пользоваться данным сайтом, Вы соглашаетесь на использование нами Ваших файлов cookie. Узнать больше.
  2. Вы находитесь в сообществе Rubukkit. Мы - администраторы серверов Minecraft, разрабатываем собственные плагины и переводим на различные языки плагины наших коллег из других стран.
    Скрыть объявление
Скрыть объявление
В преддверии глобального обновления, мы проводим исследования, которые помогут нам сделать опыт пользования форумом ещё удобнее. Помогите нам, примите участие!

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

Тема в разделе "Руководства, инструкции, утилиты", создана пользователем gamerforEA, 16 июн 2014.

  1. Автор темы
    gamerforEA

    gamerforEA Старожил Пользователь

    Баллы:
    143
    Skype:
    sk2000sk1
    Имя в Minecraft:
    gamerforEA_MCPC
    1. Открываем класс net.minecraft.client.gui.GuiMultiplayer.
    2. В конец метода initGui() добавляем:
      Код:
      this.mc.displayGuiScreen(new GuiMainMenu());
    3. Создаём класс PingTask и добавляем в него:
      Код:
      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. В самое начало ТЕЛА класса добавляем:
      Код:
      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() добавляем:
      Код:
      FMLClientHandler.instance().setupServerList();
    7. В начало метода updateScreen() добавляем:
      Код:
      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 добавляем:
      Код:
      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) заменяем:
      Код:
      this.buttonList.add(new GuiButton(2, this.width / 2 - 100, p_73969_1_ + p_73969_2_ * 1, I18n.format("menu.multiplayer", new Object[0])));
      на:
      Код:
      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) добавляем:
      Код:
      if (p_146284_1_.id == 100) this.ping();
    11. В методе из пункта 10 заменяем:
      Код:
      this.mc.displayGuiScreen(new GuiMultiplayer(this));
      на:
      Код:
      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, со следующим кодом:
      Код:
      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. Добавляем поля:
      Код:
      private ServerData sd = new ServerData("", "127.0.0.1");
      private GuiButton multiplayerButton;
      private Pinger pinger;
      
    7. Находим метод addSingleplayerMultiplayerButtons и меняем строку
      Код:
      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 и добавляем в его конец следующий код:
      Код:
      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. Добавляем следующий метод:
      Код:
      public void onGuiClosed() {
              this.pinger.finish();
          }
      
    10. Находим метод actionPerformed и меняем строку
      Код:
      this.mc.displayGuiScreen(new GuiMultiplayer(this));
      на следующий код:
      Код:
      this.mc.displayGuiScreen(new GuiConnecting(this, this.mc, this.sd));
    11. В этот же метод добавляем этот код:
      Код:
      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. Добавляем поля:
      Код:
      private ServerData sd = new ServerData("", "127.0.0.1");
      private GuiButton multiplayerButton;
      
    6. Находим метод addSingleplayerMultiplayerButtons и меняем строку
      Код:
      this.buttonList.add(new GuiButton(2, this.width / 2 - 100, par1 + par2 * 1, par3StringTranslate.translateKey("menu.multiplayer")));
      на этот код:
      Код:
      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 и меняем строку
      Код:
      this.mc.displayGuiScreen(new GuiMultiplayer(this));
      на следующий код:
      Код:
      this.mc.displayGuiScreen(new GuiConnecting(this, this.mc, this.sd));
    8. В этот же метод добавляем этот код:
      Код:
      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. Добавляем следующие поля:
      Код:
      private static int ticksCount = 0;
      private static int freezeTime = <время выключения, умноженное на 20>;
      
    3. Находим метод updateScreen и добавляем в него следующий код:
      Код:
      if (BUTTON.enabled == false) {
                   this.ticksCount++;
                  if (this.ticksCount == this.freezeTime) {
                      BUTTON.enabled = true;
                  }
      }
      
    4. Находим в методе actionPerformed обработчик нужной нам кнопки и добавляем в этот обработчик следующий код:
      Код:
      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.
     
    Последнее редактирование: 5 июн 2015
  2. Wndash

    Wndash Старожил Пользователь

    Баллы:
    173
    Скинь рабочий MCP для 1.6.4. У меня не пашет
     
  3. Автор темы
    gamerforEA

    gamerforEA Старожил Пользователь

    Баллы:
    143
    Skype:
    sk2000sk1
    Имя в Minecraft:
    gamerforEA_MCPC
    https://yadi.sk/d/vZ2NHqotTVTwL

    UPD:
    Добавил проверку на null и убрал вывод ошибки, когда клиент не может найти сервер.
     
  4. Wndash

    Wndash Старожил Пользователь

    Баллы:
    173
    Спасибо
     
  5. Автор темы
    gamerforEA

    gamerforEA Старожил Пользователь

    Баллы:
    143
    Skype:
    sk2000sk1
    Имя в Minecraft:
    gamerforEA_MCPC
    В обновлённой инструкции добавлена проверка на null.
     
  6. Wndash

    Wndash Старожил Пользователь

    Баллы:
    173
    А скрины результата есть? Просто у меня полная муть получилась
     
  7. Автор темы
    gamerforEA

    gamerforEA Старожил Пользователь

    Баллы:
    143
    Skype:
    sk2000sk1
    Имя в Minecraft:
    gamerforEA_MCPC
    Странно, у меня всё прекрасно работает. Про кик я не понял. Объясните (не забывайте про знаки препинания).
     
    Последнее редактирование: 17 июн 2014
  8. Wndash

    Wndash Старожил Пользователь

    Баллы:
    173
    Я на видео засветился
     
  9. Wndash

    Wndash Старожил Пользователь

    Баллы:
    173
    Переснимай давай!
     
  10. Wndash

    Wndash Старожил Пользователь

    Баллы:
    173
    Ноу
     
  11. NaPsTeR

    NaPsTeR Активный участник Пользователь

    Баллы:
    88
    Имя в Minecraft:
    kesha0129
    Для 1.5.2 такое сделать можно?
     
  12. Автор темы
    gamerforEA

    gamerforEA Старожил Пользователь

    Баллы:
    143
    Skype:
    sk2000sk1
    Имя в Minecraft:
    gamerforEA_MCPC
    Да. Сейчас подготовлю MCP, и будет инструкция для 1.5.2.
     
  13. NaPsTeR

    NaPsTeR Активный участник Пользователь

    Баллы:
    88
    Имя в Minecraft:
    kesha0129
    Жду :good:.
     
  14. Автор темы
    gamerforEA

    gamerforEA Старожил Пользователь

    Баллы:
    143
    Skype:
    sk2000sk1
    Имя в Minecraft:
    gamerforEA_MCPC
    Добавил инструкцию для 1.5.2 (отличий от 1.6.4 почти нет). Всё протестировал - работает.
     
  15. NaPsTeR

    NaPsTeR Активный участник Пользователь

    Баллы:
    88
    Имя в Minecraft:
    kesha0129
    Есть вопрос. На одном из клиентов видел кнопку "Обновить" которая неактивна некоторое время(6 секунд) после нажатия. Как сделать ее?
     
  16. Автор темы
    gamerforEA

    gamerforEA Старожил Пользователь

    Баллы:
    143
    Skype:
    sk2000sk1
    Имя в Minecraft:
    gamerforEA_MCPC
    Самое примитивное:
    1. При нажатии кнопки записываем в какое-нибудь поле текущее время.
    2. Каждое обновление интерфейса проверяем время и записываем его в какое-нибудь второе поле.
    3. Делаем проверку подобного типа:
      Код:
      if ((time1 + 6) == time2) {button.enabled = true;}
    Это самое простое. Для того, чтобы можно было такое использовать, необходимо добавить некоторые проверки.
    UPD: Сейчас сделаю нормальный код для выключения кнопки на указанное время.
    Добавил в шапку инструкцию по выключению кнопки на указанное время после нажатия (можно использовать для кнопки "Обновить").
     
    Последнее редактирование: 17 июн 2014
  17. NaPsTeR

    NaPsTeR Активный участник Пользователь

    Баллы:
    88
    Имя в Minecraft:
    kesha0129
    С таймером так и не получилось. Сделал все по инструкции, в итоге кнопка "Обновить" исчезла.:cry:
     
  18. Автор темы
    gamerforEA

    gamerforEA Старожил Пользователь

    Баллы:
    143
    Skype:
    sk2000sk1
    Имя в Minecraft:
    gamerforEA_MCPC
    Если бы всё делали правильно, то ничего бы не исчезло. Я делал проверку на нескольких кнопках. Ладно, сейчас запишу видео.
    Добавил в шапку видео-туториалы.
     
    Последнее редактирование: 18 июн 2014
  19. NaPsTeR

    NaPsTeR Активный участник Пользователь

    Баллы:
    88
    Имя в Minecraft:
    kesha0129
    Итого - Решил сделать таймер на кнопке обновить в GuiMultiplayer, в результате - таймер не работает. Код ниже
    Что я неправильно делаю?

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

    WCRAFT Старожил Пользователь

    Баллы:
    173
    Skype:
    worldplaytv
    Имя в Minecraft:
    World
    Дайте class файлы.
     

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