@Override
  public void configChanged(InstanceStorage<Object> confs) {
    // Player tracking
    if (confs.get(PluginConf.class).PlayerTracking.Enabled) {
      if (connectionListener == null) {
        registerListener(this.connectionListener = new ConnectionListener());
        getLogger().log(DEBUG, "Registered proxy player tracking listener.");
      }
    } else if (connectionListener != null) {
      unregisterListener(connectionListener);
      this.connectionListener = null;
      getLogger().log(DEBUG, "Unregistered proxy player tracking listener.");
    }

    // Plugin statistics
    if (confs.get(PluginConf.class).Stats) {
      if (metrics == null)
        try {
          this.metrics = new BungeeMetricsLite(this);
          metrics.start();
        } catch (Throwable e) {
          getLogger()
              .log(DEBUG, "Failed to enable plugin statistics: " + Helper.causedException(e));
        }
    } else if (metrics != null)
      try {
        metrics.stop();
        this.metrics = null;
      } catch (Throwable e) {
        getLogger().log(DEBUG, "Failed to disable plugin statistics: " + Helper.causedException(e));
      }
  }
 public void writeComments(Appendable appendable, String... comments) throws IOException {
   if (!Helper.isNullOrEmpty(comments))
     for (String line : comments) { // Write all comment lines
       if (!line.equals("\\")) appendable.append(COMMENT_PREFIX).append(line);
       newLine(appendable);
     }
 }
  private static Iterator<String> getRandomPlayers(Collection<ProxiedPlayer> players) {
    if (Helper.isNullOrEmpty(players)) return null;

    List<String> result = new ArrayList<>(players.size());

    for (ProxiedPlayer player : players) {
      result.add(player.getName());
    }

    return Randoms.shuffle(result).iterator();
  }
  private static void findProperties(Class<?> clazz, Map<String, Property> properties) {
    Class<?> superClass = clazz.getSuperclass(); // Process super classes first
    if (superClass != null) findProperties(superClass, properties);

    for (Field field : clazz.getDeclaredFields()) {
      int modifiers = field.getModifiers();
      if (!Modifier.isStatic(modifiers)
          && !Modifier.isTransient(modifiers)
          && !properties.containsKey(field.getName())) {
        properties.put(Helper.toLowerCase(field.getName()), new FieldProperty(field));
      }
    }
  }
    @EventHandler
    public void onProxyPing(ProxyPingEvent event) {
      if (event.getResponse() == null) return; // Check if response is not empty

      PendingConnection con = event.getConnection();
      StatusRequest request = core.createRequest(con.getAddress().getAddress());

      request.setProtocolVersion(con.getVersion());
      InetSocketAddress host = con.getVirtualHost();
      if (host != null) {
        ServerInfo forcedHost = AbstractReconnectHandler.getForcedHost(con);
        request.setTarget(host, forcedHost != null ? forcedHost.getName() : null);
      }

      final ServerPing ping = event.getResponse();
      final ServerPing.Players players = ping.getPlayers();
      final ServerPing.Protocol version = ping.getVersion();

      StatusResponse response =
          request.createResponse(
              core.getStatus(),
              // Return unknown player counts if it has been hidden
              new ResponseFetcher() {
                @Override
                public Integer getOnlinePlayers() {
                  return players != null ? players.getOnline() : null;
                }

                @Override
                public Integer getMaxPlayers() {
                  return players != null ? players.getMax() : null;
                }

                @Override
                public int getProtocolVersion() {
                  return version != null ? version.getProtocol() : 0;
                }
              });

      // Description
      String message = response.getDescription();
      if (message != null) ping.setDescription(message);

      if (version != null) {
        // Version name
        message = response.getVersion();
        if (message != null) version.setName(message);
        // Protocol version
        Integer protocol = response.getProtocolVersion();
        if (protocol != null) version.setProtocol(protocol);
      }

      // Favicon
      FaviconSource favicon = response.getFavicon();
      if (favicon != null) {
        Optional<Favicon> icon = faviconCache.getUnchecked(favicon);
        if (icon.isPresent()) ping.setFavicon(icon.get());
      }

      if (players != null) {
        if (response.hidePlayers()) {
          ping.setPlayers(null);
        } else {
          // Online players
          Integer count = response.getOnlinePlayers();
          if (count != null) players.setOnline(count);
          // Max players
          count = response.getMaxPlayers();
          if (count != null) players.setMax(count);

          // Player hover
          message = response.getPlayerHover();
          if (message != null) {
            if (response.useMultipleSamples()) {
              count = response.getDynamicSamples();
              List<String> lines =
                  count != null
                      ? Helper.splitLinesCached(message, count)
                      : Helper.splitLinesCached(message);

              ServerPing.PlayerInfo[] sample = new ServerPing.PlayerInfo[lines.size()];
              for (int i = 0; i < sample.length; i++)
                sample[i] = new ServerPing.PlayerInfo(lines.get(i), StatusManager.EMPTY_UUID);

              players.setSample(sample);
            } else
              players.setSample(
                  new ServerPing.PlayerInfo[] {
                    new ServerPing.PlayerInfo(message, StatusManager.EMPTY_UUID)
                  });
          }
        }
      }
    }