content: package net.minecraft.client.gui;
  
  import com.google.common.base.Charsets;
  import com.google.common.util.concurrent.ThreadFactoryBuilder;
  import io.netty.buffer.ByteBuf;
  import io.netty.buffer.ByteBufInputStream;
  import io.netty.buffer.Unpooled;
  import io.netty.handler.codec.base64.Base64;
  import net.minecraft.client.Minecraft;
  import net.minecraft.client.multiplayer.ServerData;
  import net.minecraft.client.multiplayer.ServerList;
  import net.minecraft.client.renderer.GlStateManager;
  import net.minecraft.client.renderer.texture.DynamicTexture;
  import net.minecraft.client.renderer.texture.TextureUtil;
  import net.minecraft.util.EnumChatFormatting;
  import net.minecraft.util.ResourceLocation;
  import org.apache.commons.lang3.Validate;
  import org.apache.logging.log4j.LogManager;
  import org.apache.logging.log4j.Logger;
  
  import java.awt.image.BufferedImage;
  import java.net.UnknownHostException;
  import java.util.List;
  import java.util.concurrent.*;
  
  public class ServerListEntryNormal implements GuiListExtended.IGuiListEntry {
      private static final Logger logger = LogManager.getLogger();
      //private static final ThreadPoolExecutor field_148302_b = new ScheduledThreadPoolExecutor(5, (new ThreadFactoryBuilder()).setNameFormat("Server Pinger #%d").setDaemon(true).build());
      private static final int serverCountCache = new ServerList(Minecraft.getMinecraft()).countServers();
      private static final int MAX_THREAD_COUNT_PINGER = 50;
      private static final int MAX_THREAD_COUNT_TIMEOUT = 100;
      private static final int SERVER_TIME_OUT = 10;
      private static final ThreadPoolExecutor field_148302_b = new ScheduledThreadPoolExecutor(Math.min(serverCountCache + 5, MAX_THREAD_COUNT_PINGER), (new ThreadFactoryBuilder()).setNameFormat("Server Pinger #%d").setDaemon(true).build());
  
      private static final ResourceLocation UNKNOWN_SERVER = new ResourceLocation("textures/misc/unknown_server.png");
      private static final ResourceLocation SERVER_SELECTION_BUTTONS = new ResourceLocation("textures/gui/server_selection.png");
      private final GuiMultiplayer owner;
      private final Minecraft mc;
      private final ServerData server;
      private final ResourceLocation serverIcon;
      private String field_148299_g;
      private DynamicTexture field_148305_h;
      private long field_148298_f;
  
      protected ServerListEntryNormal(GuiMultiplayer p_i45048_1_, ServerData serverIn) {
          this.owner = p_i45048_1_;
          this.server = serverIn;
          this.mc = Minecraft.getMinecraft();
          this.serverIcon = new ResourceLocation("servers/" + serverIn.serverIP + "/icon");
          this.field_148305_h = (DynamicTexture) this.mc.getTextureManager().getTexture(this.serverIcon);
      }
  
      private final ScheduledExecutorService timeoutExecutor = Executors.newScheduledThreadPool(Math.min(serverCountCache + 5, MAX_THREAD_COUNT_TIMEOUT));
  
      private static int runningTaskCount = 0;
  
      private void setServerFail(String error) {
          server.pingToServer = -1L;
          server.serverMOTD = error;
      }
  
      public Future<?> pingServer() {
          if (runningTaskCount > serverCountCache * 2) {
              setServerFail(EnumChatFormatting.DARK_RED + "Timed out");
              return field_148302_b.submit(() -> {
              });
          }
  
          Runnable pingThread = new Thread() {
              @Override
              public void run() {
                  try {
                      owner.getOldServerPinger().ping(server);
                  } catch (UnknownHostException e) {
                      throw new RuntimeException(e);
                  }
              }
          };
  
          final Future<?> future = timeoutExecutor.submit(pingThread);
          runningTaskCount++;
  
          return field_148302_b.submit(new Runnable() {
              public void run() {
                  try {
                      future.get(SERVER_TIME_OUT, TimeUnit.SECONDS);
                  } catch (TimeoutException e1) {
                      setServerFail(EnumChatFormatting.DARK_RED + "Timed out");
                  } catch (ExecutionException e2) {
                      if (e2.getCause() instanceof UnknownHostException)
                          setServerFail(EnumChatFormatting.DARK_RED + "Can't resolve hostname");
                      else
                          setServerFail(EnumChatFormatting.DARK_RED + "Can't connect to server.");
  
                  } catch (Exception e3) {
                      setServerFail(EnumChatFormatting.DARK_RED + "Can't connect to server.");
                  }
                  runningTaskCount--;
              }
          });
      }
  
      public void drawEntry(int slotIndex, int x, int y, int listWidth, int slotHeight, int mouseX, int mouseY, boolean isSelected) {
          if (!this.server.field_78841_f) {
              this.server.field_78841_f = true;
              this.server.pingToServer = -2L;
              this.server.serverMOTD = "";
              this.server.populationInfo = "";
              //TODO watch, new server pinger
              field_148302_b.submit((Runnable) pingServer());
              /*field_148302_b.submit(new Runnable()
              {
                  public void run()
                  {
                      try
                      {
                          ServerListEntryNormal.this.owner.getOldServerPinger().ping(ServerListEntryNormal.this.server);
                      }
                      catch (UnknownHostException var2)
                      {
                          ServerListEntryNormal.this.server.pingToServer = -1L;
                          ServerListEntryNormal.this.server.serverMOTD = EnumChatFormatting.DARK_RED + "Can\'t resolve hostname";
                      }
                      catch (Exception var3)
                      {
                          ServerListEntryNormal.this.server.pingToServer = -1L;
                          ServerListEntryNormal.this.server.serverMOTD = EnumChatFormatting.DARK_RED + "Can\'t connect to server.";
                      }
                  }
              });*/
          }
  
          boolean flag = this.server.version > 47;
          boolean flag1 = this.server.version < 47;
          boolean flag2 = flag || flag1;
          this.mc.fontRendererObj.drawString(this.server.serverName, x + 32 + 3, y + 1, 16777215);
          List<String> list = this.mc.fontRendererObj.listFormattedStringToWidth(this.server.serverMOTD, listWidth - 32 - 2);
  
          for (int i = 0; i < Math.min(list.size(), 2); ++i) {
              this.mc.fontRendererObj.drawString(list.get(i), x + 32 + 3, y + 12 + this.mc.fontRendererObj.FONT_HEIGHT * i, 8421504);
          }
  
          String s2 = flag2 ? EnumChatFormatting.DARK_RED + this.server.gameVersion : this.server.populationInfo;
          int j = this.mc.fontRendererObj.getStringWidth(s2);
          this.mc.fontRendererObj.drawString(s2, x + listWidth - j - 15 - 2, y + 1, 8421504);
          int k = 0;
          String s = null;
          int l;
          String s1;
  
          if (flag2) {
              l = 5;
              s1 = flag ? "Client out of date!" : "Server out of date!";
              s = this.server.playerList;
          } else if (this.server.field_78841_f && this.server.pingToServer != -2L) {
              if (this.server.pingToServer < 0L) {
                  l = 5;
              } else if (this.server.pingToServer < 150L) {
                  l = 0;
              } else if (this.server.pingToServer < 300L) {
                  l = 1;
              } else if (this.server.pingToServer < 600L) {
                  l = 2;
              } else if (this.server.pingToServer < 1000L) {
                  l = 3;
              } else {
                  l = 4;
              }
  
              if (this.server.pingToServer < 0L) {
                  s1 = "(no connection)";
              } else {
                  s1 = this.server.pingToServer + "ms";
                  s = this.server.playerList;
              }
          } else {
              k = 1;
              l = (int) (Minecraft.getSystemTime() / 100L + (long) (slotIndex * 2L) & 7L);
  
              if (l > 4) {
                  l = 8 - l;
              }
  
              s1 = "Pinging...";
          }
  
          GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
          this.mc.getTextureManager().bindTexture(Gui.icons);
          Gui.drawModalRectWithCustomSizedTexture(x + listWidth - 15, y, (float) (k * 10), (float) (176 + l * 8), 10, 8, 256.0F, 256.0F);
  
          if (this.server.getBase64EncodedIconData() != null && !this.server.getBase64EncodedIconData().equals(this.field_148299_g)) {
              this.field_148299_g = this.server.getBase64EncodedIconData();
              this.prepareServerIcon();
              this.owner.getServerList().saveServerList();
          }
  
          if (this.field_148305_h != null) {
              this.drawTextureAt(x, y, this.serverIcon);
          } else {
              this.drawTextureAt(x, y, UNKNOWN_SERVER);
          }
  
          int i1 = mouseX - x;
          int j1 = mouseY - y;
  
          if (i1 >= listWidth - 15 && i1 <= listWidth - 5 && j1 >= 0 && j1 <= 8) {
              this.owner.setHoveringText(s1);
          } else if (i1 >= listWidth - j - 15 - 2 && i1 <= listWidth - 15 - 2 && j1 >= 0 && j1 <= 8) {
              this.owner.setHoveringText(s);
          }
  
          if (this.mc.gameSettings.touchscreen || isSelected) {
              this.mc.getTextureManager().bindTexture(SERVER_SELECTION_BUTTONS);
              Gui.drawRect(x, y, x + 32, y + 32, -1601138544);
              GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
              int k1 = mouseX - x;
              int l1 = mouseY - y;
  
              if (this.func_178013_b()) {
                  if (k1 < 32 && k1 > 16) {
                      Gui.drawModalRectWithCustomSizedTexture(x, y, 0.0F, 32.0F, 32, 32, 256.0F, 256.0F);
                  } else {
                      Gui.drawModalRectWithCustomSizedTexture(x, y, 0.0F, 0.0F, 32, 32, 256.0F, 256.0F);
                  }
              }
  
              if (this.owner.func_175392_a(this, slotIndex)) {
                  if (k1 < 16 && l1 < 16) {
                      Gui.drawModalRectWithCustomSizedTexture(x, y, 96.0F, 32.0F, 32, 32, 256.0F, 256.0F);
                  } else {
                      Gui.drawModalRectWithCustomSizedTexture(x, y, 96.0F, 0.0F, 32, 32, 256.0F, 256.0F);
                  }
              }
  
              if (this.owner.func_175394_b(this, slotIndex)) {
                  if (k1 < 16 && l1 > 16) {
                      Gui.drawModalRectWithCustomSizedTexture(x, y, 64.0F, 32.0F, 32, 32, 256.0F, 256.0F);
                  } else {
                      Gui.drawModalRectWithCustomSizedTexture(x, y, 64.0F, 0.0F, 32, 32, 256.0F, 256.0F);
                  }
              }
          }
      }
  
      protected void drawTextureAt(int p_178012_1_, int p_178012_2_, ResourceLocation p_178012_3_) {
          this.mc.getTextureManager().bindTexture(p_178012_3_);
          GlStateManager.enableBlend();
          Gui.drawModalRectWithCustomSizedTexture(p_178012_1_, p_178012_2_, 0.0F, 0.0F, 32, 32, 32.0F, 32.0F);
          GlStateManager.disableBlend();
      }
  
      private boolean func_178013_b() {
          return true;
      }
  
      private void prepareServerIcon() {
          if (this.server.getBase64EncodedIconData() == null) {
              this.mc.getTextureManager().deleteTexture(this.serverIcon);
              this.field_148305_h = null;
          } else {
              ByteBuf bytebuf = Unpooled.copiedBuffer(this.server.getBase64EncodedIconData(), Charsets.UTF_8);
              ByteBuf bytebuf1 = Base64.decode(bytebuf);
              BufferedImage bufferedimage;
              label101:
              {
                  try {
                      bufferedimage = TextureUtil.readBufferedImage(new ByteBufInputStream(bytebuf1));
                      Validate.validState(bufferedimage.getWidth() == 64, "Must be 64 pixels wide");
                      Validate.validState(bufferedimage.getHeight() == 64, "Must be 64 pixels high");
                      break label101;
                  } catch (Throwable throwable) {
                      logger.error("Invalid icon for server " + this.server.serverName + " (" + this.server.serverIP + ")", throwable);
                      this.server.setBase64EncodedIconData(null);
                  } finally {
                      bytebuf.release();
                      bytebuf1.release();
                  }
  
                  return;
              }
  
              if (this.field_148305_h == null) {
                  this.field_148305_h = new DynamicTexture(bufferedimage.getWidth(), bufferedimage.getHeight());
                  this.mc.getTextureManager().loadTexture(this.serverIcon, this.field_148305_h);
              }
  
              bufferedimage.getRGB(0, 0, bufferedimage.getWidth(), bufferedimage.getHeight(), this.field_148305_h.getTextureData(), 0, bufferedimage.getWidth());
              this.field_148305_h.updateDynamicTexture();
          }
      }
  
      public boolean mousePressed(int slotIndex, int p_148278_2_, int p_148278_3_, int p_148278_4_, int p_148278_5_, int p_148278_6_) {
          if (p_148278_5_ <= 32) {
              if (p_148278_5_ < 32 && p_148278_5_ > 16 && this.func_178013_b()) {
                  this.owner.selectServer(slotIndex);
                  this.owner.connectToSelected();
                  return true;
              }
  
              if (p_148278_5_ < 16 && p_148278_6_ < 16 && this.owner.func_175392_a(this, slotIndex)) {
                  this.owner.func_175391_a(this, slotIndex, GuiScreen.isShiftKeyDown());
                  return true;
              }
  
              if (p_148278_5_ < 16 && p_148278_6_ > 16 && this.owner.func_175394_b(this, slotIndex)) {
                  this.owner.func_175393_b(this, slotIndex, GuiScreen.isShiftKeyDown());
                  return true;
              }
          }
  
          this.owner.selectServer(slotIndex);
  
          if (Minecraft.getSystemTime() - this.field_148298_f < 250L) {
              this.owner.connectToSelected();
          }
  
          this.field_148298_f = Minecraft.getSystemTime();
          return false;
      }
  
      public void setSelected(int p_178011_1_, int p_178011_2_, int p_178011_3_) {
      }
  
      public void mouseReleased(int slotIndex, int x, int y, int mouseEvent, int relativeX, int relativeY) {
      }
  
      public ServerData getServerData() {
          return this.server;
      }
  }
  