public SlytherClient() {
   try {
     configuration = ConfigHandler.INSTANCE.readConfig(CONFIGURATION_FILE, ClientConfig.class);
     saveConfig();
   } catch (IOException e) {
     UIUtils.displayException("Unable to read config", e);
     Log.catching(e);
   }
   temporaryServerSelection = configuration.server;
   Reflections reflections = new Reflections("");
   Set<Class<?>> annotated = reflections.getTypesAnnotatedWith(Controller.class);
   for (Class<?> controller : annotated) {
     if (IController.class.isAssignableFrom(controller)) {
       try {
         Controller annotation = controller.getAnnotation(Controller.class);
         setController((IController) controller.getDeclaredConstructor().newInstance());
         Log.info("Using controller \"{}\" ({})", annotation.name(), controller.getSimpleName());
         break;
       } catch (Exception e) {
       }
     }
   }
   renderHandler = new RenderHandler(this);
   renderHandler.setup();
   setup();
 }
 private void setupDisplay() {
   int width = Display.getWidth();
   int height = Display.getHeight();
   GL11.glMatrixMode(GL11.GL_PROJECTION);
   GL11.glLoadIdentity();
   GL11.glOrtho(0, Display.getWidth(), Display.getHeight(), 0, 1, -1);
   GL11.glMatrixMode(GL11.GL_MODELVIEW);
   GL11.glScissor(0, 0, width, height);
   GL11.glViewport(0, 0, width, height);
   renderHandler.init();
 }
 public void closeAllGuis() {
   renderHandler.closeAllGuis();
 }
 public void closeGui(Gui gui) {
   renderHandler.closeGui(gui);
 }
 public void openGui(Gui gui) {
   renderHandler.openGui(gui);
 }
  @Override
  public void run() {
    double delta = 0;
    long previousTime = System.nanoTime();
    long timer = System.currentTimeMillis();
    int ups = 0;
    double nanoUpdates = 1000000000.0 / 30.0;

    GL11.glEnable(GL11.GL_TEXTURE_2D);
    GL11.glShadeModel(GL11.GL_SMOOTH);
    GL11.glDisable(GL11.GL_DEPTH_TEST);
    GL11.glDisable(GL11.GL_LIGHTING);

    GL11.glClearColor(0.0F, 0.0F, 0.0F, 0.0F);
    GL11.glClearDepth(1);

    GL11.glEnable(GL11.GL_BLEND);
    GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);

    setupDisplay();

    boolean doResize = false;

    while (!Display.isCloseRequested()) {
      if (Display.wasResized() && doResize) {
        setupDisplay();
      }
      doResize = true;

      long currentTime = System.nanoTime();
      double currentTickDelta = (currentTime - previousTime) / nanoUpdates;
      delta += currentTickDelta;
      frameDelta = (frameDelta + currentTickDelta) % 1.0;
      previousTime = currentTime;

      while (delta >= 1) {
        update();
        renderHandler.update();
        delta--;
        ups++;
      }

      GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
      GL11.glPushMatrix();

      GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);

      renderHandler.render();

      fps++;

      if (System.currentTimeMillis() - timer > 1000) {
        int bytesPerSecond = 0;
        int packetsPerSecond = 0;
        if (networkManager != null) {
          bytesPerSecond = networkManager.bytesPerSecond;
          packetsPerSecond = networkManager.packetsPerSecond;
          networkManager.bytesPerSecond = 0;
          networkManager.packetsPerSecond = 0;
        }
        Display.setTitle(
            "Slyther - FPS: "
                + fps
                + " - UPS: "
                + ups
                + " - BPS: "
                + bytesPerSecond
                + " - PPS: "
                + packetsPerSecond);
        fps = 0;

        timer += 1000;
        ups = 0;
      }

      GL11.glPopMatrix();
      Display.sync(60);
      Display.update();
    }
    if (networkManager != null && networkManager.isOpen()) {
      networkManager.closeConnection(ClientNetworkManager.SHUTDOWN_CODE, "");
    }
    try {
      ConfigHandler.INSTANCE.saveConfig(CONFIGURATION_FILE, configuration);
    } catch (IOException e) {
      Log.error("Failed to save config");
      Log.catching(e);
    }
    Display.destroy();
  }