BungeeMain / src / main / java / com / lifeknight / relaymcbungeemain / utilities / Server.java
Server.java
Raw
package com.lifeknight.relaymcbungeemain.utilities;

import com.lifeknight.relaymcbungeemain.Main;
import com.lifeknight.relaymcbungeemain.network.MessageServerHandler;
import com.lifeknight.relaymcbungeemain.player.SmartPlayer;
import com.lifeknight.relaymcbungeemain.queue.GameServer;
import com.lifeknight.relaymcbungeemain.queue.ServerDetails;
import com.lifeknight.relayutils.RelayUtils;
import com.lifeknight.relayutils.basic.Miscellaneous;
import com.lifeknight.relayutils.game.GameDetails;
import com.lifeknight.relayutils.game.MainGame;
import com.lifeknight.relayutils.network.Command;
import com.lifeknight.relayutils.network.Recipient;
import com.lifeknight.relayutils.utilities.ComponentBuilder;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.chat.hover.content.Text;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;

import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;

public class Server {
    public static final List<Server> SERVERS = new ArrayList<>();

    private final String name;
    private final MainGame mainGame;
    private final ServerType serverType;
    private int memoryGB = 3;
    private boolean availableForPlayers = true;
    private boolean messageClientActive;

    public Server(String name, MainGame mainGame, ServerType serverType) {
        this.name = name;
        this.mainGame = mainGame;
        this.serverType = serverType;

        SERVERS.add(this);
    }

    public static void removeServer(ServerInfo serverInfo) {
        SERVERS.remove(getServer(serverInfo));
        Main.save();
    }

    public static boolean allHubsAreFull() {
        for (Server hubServer : Server.getHubServers()) {
            if (hubServer.hasSufficientSpace()) {
                return false;
            }
        }

        return true;
    }

    public String getName() {
        return this.name;
    }

    public boolean isHub() {
        return serverType == ServerType.HUB;
    }

    public ServerInfo getServerInfo() {
        ServerInfo serverInfo = ProxyServer.getInstance().getServerInfo(this.name);
        if (serverInfo == null && this.isHub()) {
            Main.warn("Null serverinfo for %s", this.name);
        }

        return serverInfo;
    }

    public Recipient getRecipient() {
        return Recipient.getRecipient(this.name);
    }

    public int getPlayerCount() {
        return this.getServerInfo() == null ? 0 : this.getServerInfo().getPlayers().size();
    }

    public boolean isEmpty() {
        return this.getPlayerCount() == 0;
    }

    private static final List<MainGame> IGNORABLE = Miscellaneous.getList(MainGame.DUELS);

    public boolean isViable(int playerCount) {
        if (IGNORABLE.contains(this.mainGame)) {
            return true;
        }

        if (RelayUtils.testing) {
            return true;
        }

        if (this.getPlayerCount() == 0) {
            return true;
        }

        if (this.isHub()) {
            return this.getPlayerCount() + playerCount <= RelayUtils.HUB_DEFAULT_MAX_SIZE;
        }

        if (this.mainGame == MainGame.MANHUNT) {
            return (this.getPlayerCount() + playerCount <= 6);
        }

        return (this.getPlayerCount() + playerCount <= 32);
    }

    public MainGame getMainGame() {
        return this.mainGame;
    }

    public int getMemoryGB() {
        return this.memoryGB;
    }

    public void setMemoryGB(int memoryGB) {
        this.memoryGB = memoryGB;
    }

    public InetSocketAddress getSocketAddress() {
        return this.getServerInfo() == null ? null : (InetSocketAddress) this.getServerInfo().getSocketAddress();
    }

    public Server getHub() {
        if (this.isHub()) {
            return getServerOfType(null, false);
        }

        return getServerOfType(this.mainGame, false);
    }

    public String getNameForInfo() {
        return this.mainGame == null ? "Main" : this.mainGame.getName();
    }

    public void sendMessage(Command command, Object... arguments) {
        if (this.isMessageClientActive()) {
            MessageUtils.createAndSend(this.getRecipient(), command, arguments);
        } else {
            Main.warn("Attempted to send %s message to %s, message client inactive.", command, this.name);
        }
    }

    public boolean canSend() {
        return this.isActive() && this.hasServerInfo() && this.hasSufficientSpace();
    }

    public boolean hasSufficientSpace() {
        if (this.isHub()) {
            return this.getPlayerCount() < RelayUtils.HUB_DEFAULT_MAX_SIZE;
        }

        return true;
    }

    public boolean hasServerInfo() {
        return this.getServerInfo() != null;
    }

    public void setAvailableForPlayers(boolean availableForPlayers) {
        this.availableForPlayers = availableForPlayers;
    }

    public boolean isActive() {
        return this.availableForPlayers && this.messageClientActive;
    }

    public boolean isMessageClientActive() {
        return this.messageClientActive && MessageServerHandler.CHANNELS.containsKey(this.name);
    }

    public void setMessageClientActive(boolean messageClientActive) {
        this.messageClientActive = messageClientActive;
    }

    public void start() {
        Main.info("Sent instructions via pterodactyl to start server %s.", this.getName());
    }

    public static Server getServer(String name) {
        if (name == null) {
            return null;
        }
        return Miscellaneous.match(SERVERS, server -> name.equalsIgnoreCase(server.name));
    }

    public static Server getServer(ServerInfo serverInfo) {
        if (serverInfo == null) {
            return null;
        }

        for (Server server : SERVERS) {
            if (serverInfo.equals(server.getServerInfo())) return server;
        }

        return new Server(serverInfo.getName(), null, ServerType.LIMBO);
    }

    public static Server getServerFromIP(String ip) {
        int port = 25565;
        if (ip.contains(":")) {
            String[] data = ip.split(":");
            try {
                port = Integer.parseInt(data[1]);
            } catch (Exception exception) {
                Main.error("Could not parse port: %s", ip);
            }
            ip = data[0];
        }
        ProxyServer proxyServer = ProxyServer.getInstance();
        if (proxyServer.getServers() != null) {
            for (ServerInfo serverInfo : ProxyServer.getInstance().getServers().values()) {
                InetSocketAddress serverAddress = (InetSocketAddress) serverInfo.getSocketAddress();
                if (serverAddress != null) {
                    InetAddress inetAddress = serverAddress.getAddress();
                    if (inetAddress != null) {
                        String ip2 = inetAddress.getHostAddress();
                        if (ip.equals(ip2) && port == serverAddress.getPort()) {
                            return getServer(serverInfo);
                        }
                    }
                }
            }
        }

        return null;
    }

    public static void clear() {
        SERVERS.clear();
    }

    public static List<Server> getAvailableServersOfType(MainGame mainGame, boolean gameSever) {
        List<Server> applicableServers = new ArrayList<>();

        for (Server server : SERVERS) {
            if (!server.isLimbo() && server.canSend() && server.mainGame == mainGame && ((gameSever && !server.isHub()) || (!gameSever && server.isHub()))) {
                applicableServers.add(server);
            }
        }

        if (applicableServers.isEmpty() && mainGame != null) {
            //Main.info("Applicable servers empty (1): %s %s", mainGame, gameSever);
            applicableServers = getAvailableServersOfType(null, false);
        }

        if (applicableServers.isEmpty()) {
            //Main.info("Applicable servers empty (2): %s %s", mainGame, gameSever);
            for (Server server : SERVERS) {
                if (!server.isLimbo() && server.messageClientActive && server.availableForPlayers && server.mainGame == mainGame && ((gameSever && !server.isHub()) || (!gameSever && server.isHub()))) {
                    applicableServers.add(server);
                }
            }
        }

        return applicableServers;
    }

    public static List<Server> getServersOfType(MainGame mainGame, boolean gameSever) {
        return Miscellaneous.filter(SERVERS, server -> server.mainGame == mainGame && ((gameSever && !server.isHub()) || (!gameSever && server.isHub())));
    }

    public static Server getServerOfType(MainGame mainGame, boolean gameServer) {
        return Miscellaneous.getFirstEntry(getAvailableServersOfType(mainGame, gameServer));
    }

    public static List<Server> getHubServers() {
        List<Server> hubServers = new ArrayList<>();

        for (Server server : SERVERS) {
            if (server.isHub()) {
                Miscellaneous.addIfAbsent(hubServers, server);
            }
        }

        return hubServers;
    }

    public static List<Server> getGameServers() {
        List<Server> gameServers = new ArrayList<>();

        for (Server server : SERVERS) {
            if (!server.isHub()) {
                Miscellaneous.addIfAbsent(gameServers, server);
            }
        }

        return gameServers;
    }

    public static void create(String name, MainGame mainGame, ServerType serverType) {
        if (getServer(name) == null) {
            new Server(name, mainGame, serverType);
        }
    }

    public int getAvailability() {
        if (!this.availableForPlayers || !this.messageClientActive) {
            return 0;
        }

        if (this.isHub()) {
            if (this.getPlayerCount() >= RelayUtils.HUB_DEFAULT_MAX_SIZE) {
                return 1;
            } else if (this.getPlayerCount() >= RelayUtils.HUB_EXTENDED_MAX_SIZE) {
                return 0;
            }

            return -1;
        }

        GameServer gameServer = GameServer.getGameServer(this.getRecipient());
        if (gameServer != null) {
            ServerDetails serverDetails = gameServer.getServerDetails();
            double fullCount = 0;
            double used = 0;
            for (GameDetails gameDetail : serverDetails.gameDetails) {
                if (!gameDetail.isAvailable()) {
                    used++;
                }
                fullCount++;
            }

            if (used / fullCount >= 0.75) {
                return 1;
            } else if (used / fullCount >= 0.25) {
                return 0;
            }

            return -1;
        }

        return 0;
    }

    public BaseComponent getComponent() {
        ComponentBuilder componentBuilder = new ComponentBuilder("   ");
        TextComponent hover = new TextComponent(RelayUtils.format("%s[%s%s%s] ", ChatColor.GRAY, this.getChatColorForName(), this.getName(), ChatColor.GRAY));
        hover.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(new BaseComponent[]{this.getHover()})));
        componentBuilder.appendComponent(hover);
        List<SmartPlayer> players = this.getPlayers();
        for (int i = 0; i < players.size(); i++) {
            SmartPlayer smartPlayer = players.get(i);
            componentBuilder.command(smartPlayer.getFormattedNameColor() + smartPlayer.getName(), "/spectate " + smartPlayer.getName(), "Spectate " + smartPlayer.getFormattedName() + ChatColor.WHITE + ".");
            if (i != players.size() - 1) {
                componentBuilder.append(", ");
            }
        }

        return componentBuilder.getResult();
    }

    public BaseComponent getHover() {
        if (this.isHub()) {
            return new ComponentBuilder("%s%d%s/%d", this.getChatColorForName().toString(), this.getPlayerCount(), ChatColor.WHITE, RelayUtils.HUB_DEFAULT_MAX_SIZE).getResult();
        }

        GameServer gameServer = GameServer.getGameServer(this.getRecipient());
        if (gameServer != null) {
            return gameServer.getServerDetails().getComponent();
        }

        return new TextComponent(this.getPlayerCount() + " players");
    }

    public List<ProxiedPlayer> getProxiedPlayers() {
        return this.getServerInfo() == null ? new ArrayList<>() : Miscellaneous.getList(this.getServerInfo().getPlayers());
    }

    public List<SmartPlayer> getPlayers() {
        return Miscellaneous.processList(this.getProxiedPlayers(), SmartPlayer::getSmartPlayer);
    }

    public ChatColor getChatColorForName() {
        return switch (this.getAvailability()) {
            case -1 -> ChatColor.GREEN;
            case 0 -> ChatColor.YELLOW;
            default -> ChatColor.RED;
        };

    }

    public static Server getLimboServer() {
        Server best = null;
        for (Server limboServer : getLimboServers()) {
            if (limboServer.messageClientActive && limboServer.availableForPlayers) {
                if (best == null || limboServer.getPlayerCount() < best.getPlayerCount()) {
                    best = limboServer;
                }
            }
        }

        if (best != null) {
            return best;
        }

        return Miscellaneous.getRandomEntry(getLimboServers());
    }

    public static List<Server> getLimboServers() {
        return Miscellaneous.filter(SERVERS, server -> server.serverType == ServerType.LIMBO);
    }

    public boolean isLimbo() {
        return this.serverType == ServerType.LIMBO;
    }
}