BungeeMain / src / main / java / com / lifeknight / relaymcbungeemain / player / Party.java
Party.java
Raw
package com.lifeknight.relaymcbungeemain.player;

import com.lifeknight.relaymcbungeemain.Main;
import com.lifeknight.relaymcbungeemain.utilities.GroupUtils;
import com.lifeknight.relaymcbungeemain.utilities.MessageUtils;
import com.lifeknight.relayutils.basic.Miscellaneous;
import com.lifeknight.relayutils.basic.Text;
import com.lifeknight.relayutils.data.PartyData;
import com.lifeknight.relayutils.network.Command;
import com.lifeknight.relayutils.network.Recipient;
import com.lifeknight.relayutils.player.Group;
import com.lifeknight.relayutils.utilities.ComponentBuilder;
import net.md_5.bungee.api.event.PlayerDisconnectEvent;

import java.util.*;

import static net.md_5.bungee.api.ChatColor.*;

public class Party {
    public static final Map<UUID, Party> PARTIES = new HashMap<>();

    private final UUID uuid;
    private SmartPlayer owner;
    private final List<SmartPlayer> players;
    private final List<SmartPlayer> invited;

    private boolean allStartGame = false;
    private boolean allInvite = false;
    private boolean allRolePermissions = false;
    private boolean publicParty = false;
    private int maxPartySize = -1;

    private long lastOwnerDisconnectTime;

    public Party(SmartPlayer owner) {
        this.owner = owner;
        this.players = new ArrayList<>();
        this.players.add(owner);
        this.invited = new ArrayList<>();
        this.uuid = getNewUUID();
        PARTIES.put(this.uuid, this);
    }

    public static void onPlayerLeave(PlayerDisconnectEvent event) {
        SmartPlayer disconnecter = SmartPlayer.getSmartPlayer(event.getPlayer());
        if (disconnecter.isInParty()) {
            Party party = disconnecter.getCurrentParty();
            if (disconnecter.isPartyOwner()) {
                party.lastOwnerDisconnectTime = System.currentTimeMillis();
                if (party.players.size() == 1) {
                    party.disband(disconnecter);
                } else {
                    for (SmartPlayer smartPlayer1 : party.players) {
                        smartPlayer1.sendPartyInfoMessage("The party leader, %s%s, has disconnected. A random player will be promoted to party leader unless they rejoin within 5 minutes.", disconnecter.getFormattedName(), YELLOW);
                    }
                    Main.schedule(() -> {
                        if (System.currentTimeMillis() - party.lastOwnerDisconnectTime >= 1000L * 60L * 5L - 500 && party.players.contains(disconnecter) && !party.owner.isOnline()) {
                            party.publicParty = false;
                            if (party.players.size() >= 3) {
                                party.players.remove(disconnecter);
                                disconnecter.setCurrentParty(null);
                                SmartPlayer toPromote = null;
                                for (SmartPlayer player : party.players) {
                                    if (party.getSize() <= maxPartySizeForPlayer(player)) {
                                        toPromote = player;
                                        break;
                                    }
                                }

                                if (toPromote != null) {

                                    SmartPlayer finalToPromote = toPromote;
                                    party.players.forEach(smartPlayer1 -> {
                                        if (smartPlayer1 != finalToPromote) {
                                            smartPlayer1.sendPartyInfoMessage("The party leader, %s%s, has been offline for over 5 minutes. %s is now the party leader.", party.owner.getFormattedName(), YELLOW, finalToPromote.getFormattedName());
                                        } else {
                                            smartPlayer1.sendPartyInfoMessage("The party leader, %s%s, has been offline for over 5 minutes. You are now the party leader.", party.owner.getFormattedName(), YELLOW);
                                        }
                                    });
                                    party.owner = toPromote;
                                } else {
                                    party.players.forEach(smartPlayer1 -> smartPlayer1.sendPartyInfoMessage("The party leader, %s%s, has been offline for over 5 minutes, and no players can own the party with their rank's party capacity. Disbanding party.", disconnecter.getFormattedName(), YELLOW));
                                    party.broadcastDisbandMessage();
                                    party.destroy();
                                }
                                party.update();
                            } else {
                                party.players.forEach(smartPlayer1 -> smartPlayer1.sendPartyInfoMessage("The party leader, %s%s, has been offline for over 5 minutes. Disbanding party.", disconnecter.getFormattedName(), YELLOW));
                                party.broadcastDisbandMessage();
                                party.destroy();
                            }
                        }
                    }, 60L * 5L);
                }
            } else {
                for (SmartPlayer smartPlayer1 : party.players) {
                    smartPlayer1.sendPartyInfoMessage("%s%s has disconnected. They have five minutes to rejoin before they are kicked from the party.", disconnecter.getFormattedName(), YELLOW);
                }
                Main.schedule(() -> {
                    if (System.currentTimeMillis() - disconnecter.getLastDisconnectTime() >= 1000L * 60L * 5L - 500 && party.players.contains(disconnecter) && !disconnecter.isOnline()) {
                        if (party.players.size() >= 1) {
                            party.players.remove(disconnecter);
                            disconnecter.setCurrentParty(null);

                            party.players.forEach(smartPlayer1 -> smartPlayer1.sendPartyInfoMessage("%s%s has been removed from the party.", disconnecter.getFormattedName(), YELLOW));
                        } else {
                            party.broadcastDisbandMessage();
                            party.destroy();
                        }
                    }
                }, 60L * 5L);
            }
        }
    }

    public static void tryJoin(SmartPlayer smartPlayer, String toJoinPlayerName) {
        if (smartPlayer.isInParty()) {
            smartPlayer.sendPartyErrorMessage("You are already in a party!");
            return;
        }

        SmartPlayer toJoin = SmartPlayer.getSmartPlayer(toJoinPlayerName);
        if (toJoin == null) {
            smartPlayer.sendPartyErrorMessage("No player found with the name of %s%s%s.", YELLOW, toJoinPlayerName, RED);
            return;
        } else if (!toJoin.isInParty()) {
            smartPlayer.sendPartyErrorMessage("No party for the player %s%s.", toJoin.getFormattedName(), RED);
            return;
        }

        Party party = toJoin.getCurrentParty();

        if (party.isAtMaxSize()) {
            smartPlayer.sendErrorMessage("The party you are trying to join has reached its maximum capacity!");
            return;
        }

        if (party.invited.contains(smartPlayer) || party.publicParty) {
            party.joinSuccess(smartPlayer);
        } else {
            smartPlayer.sendPartyErrorMessage("You have not been invited to this party or your invite to it has expired.");
        }
    }

    private void joinSuccess(SmartPlayer smartPlayer) {
        smartPlayer.getInvitedParties().remove(this);
        this.invited.remove(smartPlayer);
        if (smartPlayer.isInQueue()) {
            smartPlayer.leaveSingular();
        }
        this.players.add(smartPlayer);
        this.players.forEach(smartPlayer1 -> smartPlayer1.sendPartySuccessMessage("%s%s has joined the party.", smartPlayer.getFormattedName(), GREEN));
        this.broadcastJoinMessage(smartPlayer.getUUID(), smartPlayer.getName());
        smartPlayer.setCurrentParty(this);
    }

    public boolean isAtMaxSize() {
        return this.getSize() >= maxPartySizeForPlayer(this.owner) || (this.publicParty && this.maxPartySize != -1 && this.getSize() >= this.maxPartySize);
    }

    public void tryInvite(SmartPlayer inviter, String playerToInvite) {
        if (this.isAtMaxSize()) {
            if (this.isOwner(inviter)) {
                if (inviter.getHighestGroup() != Group.CHAMPION) {
                    int currentMax = maxPartySizeForPlayer(this.owner);
                    Group higherGroup = Group.CHAMPION;
                    int higherMax = GroupUtils.maxPlayersForPartyOwner(higherGroup, 1);
                    inviter.sendErrorMessage("Your party is at its maximum capacity, %s%s%s players. Upgrade your rank to %s%s to get %s%s%s slots!",
                            YELLOW, currentMax, RED,
                            higherGroup.getColor() + higherGroup.getGroupName(), RED,
                            YELLOW, higherMax, RED);
                } else {
                    inviter.sendErrorMessage("This party has reached its maximum capacity for your Premium tier!");
                }
            } else {
                inviter.sendErrorMessage("This party has reached its maximum capacity for the leaders rank!");
            }

            return;
        }

        if (this.allInvite || this.isOwner(inviter)) {
            SmartPlayer invitedPlayer = SmartPlayer.getSmartPlayer(playerToInvite);
            if (invitedPlayer == null) {
                if (SmartPlayer.isNickname(playerToInvite)) {
                    inviter.sendErrorMessage("You cannot invite that player to the party!");
                } else {
                    inviter.sendPartyErrorMessage("No player found with the name of %s%s%s.", YELLOW, playerToInvite, RED);
                }
                return;
            } else if (!invitedPlayer.isOnline()) {
                inviter.sendPartyErrorMessage("That player is not online!");
                return;
            }
            if (this.equals(invitedPlayer.getCurrentParty())) {
                inviter.sendPartyErrorMessage("%s%s is already in the party!", invitedPlayer.getFormattedName(), RED);
            } else if (inviter.eitherAreBlocked(invitedPlayer)) {
                inviter.sendPartyErrorMessage("You cannot invite that player to the party!");
            } else {
                if (invitedPlayer.inviteToParty(inviter, this.owner.equals(inviter), this)) {
                    this.invited.add(invitedPlayer);
                    inviter.sendSuccessMessage("Invited %s%s to the party. They have 60 seconds to accept.", invitedPlayer.getFormattedName(), GREEN);
                    for (SmartPlayer player : this.players) {
                        if (player != inviter) {
                            player.sendPartyInfoMessage("%s%s invited %s%s to the party. They have 60 seconds to accept.", inviter.getFormattedName(), YELLOW, invitedPlayer.getFormattedName(), YELLOW);
                        }
                    }
                    Main.schedule(() -> {
                        invitedPlayer.getInvitedParties().remove(this);
                        if (this.invited.remove(invitedPlayer)) {
                            inviter.sendPartyErrorMessage("The party invite to %s%s has expired.", invitedPlayer.getFormattedName(), RED);
                        }
                    }, 60);
                } else {
                    inviter.sendPartyErrorMessage("You cannot invite that player to the party!");
                }
            }
        } else {
            inviter.sendErrorMessage("Only the party leader can invite players!");
        }
    }

    private boolean isOwner(SmartPlayer smartPlayer) {
        return smartPlayer.equals(this.owner);
    }

    public boolean isAllStartGame() {
        return this.allStartGame;
    }

    public void setAllStartGame(boolean allStartGame) {
        this.allStartGame = allStartGame;
    }

    public boolean isAllInvite() {
        return this.allInvite;
    }

    public void setAllInvite(boolean allInvite) {
        this.allInvite = allInvite;
    }

    public int getSize() {
        return this.players.size();
    }

    public boolean hasOfflinePlayers() {
        for (SmartPlayer smartPlayer : this.players) {
            if (!smartPlayer.isOnline()) return true;
        }
        return false;
    }

    public SmartPlayer getOwner() {
        return this.owner;
    }

    private static UUID getNewUUID() {
        UUID uuid = UUID.randomUUID();

        if (!PARTIES.containsKey(uuid)) {
            return uuid;
        }

        return getNewUUID();
    }

    public List<SmartPlayer> getPlayers() {
        return this.players;
    }

    public boolean canStartGame(SmartPlayer smartPlayer) {
        return this.isOwner(smartPlayer) || this.allStartGame;
    }

    public void tryWarp(SmartPlayer smartPlayer) {
        if (this.isOwner(smartPlayer)) {
            if (Miscellaneous.match(this.players, SmartPlayer::isInLimboQueue) == null) {
                if (smartPlayer.isOnHub()) {
                    for (SmartPlayer toWarp : this.players) {
                        if (toWarp != smartPlayer && !toWarp.isOnSameServer(smartPlayer)) {
                            toWarp.sendToPlayer(smartPlayer);
                            toWarp.sendPartyInfoMessage("%s%s warped you to their server.", smartPlayer.getFormattedName(), YELLOW);
                        }
                    }
                    smartPlayer.sendSuccessMessage("Warped players in your party to your lobby.");
                } else {
                    smartPlayer.sendPartyErrorMessage("You can only warp in lobbies!");
                }
            } else {
                smartPlayer.sendErrorMessage("You cannot warp while a party member is in limbo!");
            }
        } else {
            smartPlayer.sendPartyErrorMessage("Only party leaders can use this command!");
        }
    }

    public void tryDisband(SmartPlayer smartPlayer) {
        if (this.isOwner(smartPlayer)) {
            this.disband(smartPlayer);
        } else {
            smartPlayer.sendPartyErrorMessage("Only party leaders can use this command!");
        }
    }

    private void disband(SmartPlayer disbander) {
        for (SmartPlayer smartPlayer : this.players) {
            if (!disbander.equals(smartPlayer)) {
                smartPlayer.sendPartyInfoMessage("%s%s has disbanded the party.", GOLD + disbander.getFormattedName(), YELLOW);
            }
        }
        disbander.sendPartySuccessMessage("Disbanded party.");
        this.broadcastDisbandMessage();
        this.destroy();
    }

    private void destroy() {
        this.players.forEach(smartPlayer -> smartPlayer.setCurrentParty(null));
        Main.schedule(() -> this.players.forEach(SmartPlayer::sendPartyData), 1);

        PARTIES.remove(this.uuid);
        this.players.clear();
        this.invited.clear();
        this.owner = null;
    }

    public void tryKick(SmartPlayer smartPlayer, String toKickPlayerName) {
        if (this.isOwner(smartPlayer)) {
            SmartPlayer toKick = SmartPlayer.getSmartPlayer(toKickPlayerName);

            if (toKick == null) {
                smartPlayer.sendPartyErrorMessage("No player found with the name of %s%s%s.", YELLOW, toKickPlayerName, RED);
            } else if (!this.players.contains(toKick)) {
                smartPlayer.sendPartyErrorMessage("%s%s is not in your party.", toKick.getFormattedName(), RED);
            } else {
                this.removePlayerFromParty(toKick);
                smartPlayer.sendPartySuccessMessage("Removed %s%s from the party.", toKick.getFormattedName(), GREEN);
                for (SmartPlayer player : this.players) {
                    if (player != smartPlayer) {
                        player.sendPartyInfoMessage("%s%s was kicked from the party by %s%s.", toKick.getFormattedName(), YELLOW, smartPlayer.getFormattedName(), YELLOW);
                    }
                }
                toKick.sendPartyErrorMessage("You were kicked from the party by %s%s.", smartPlayer.getFormattedName(), RED);
                this.broadcastLeaveMessage(toKick.getUUID(), toKick.getName());
            }
        } else {
            smartPlayer.sendPartyErrorMessage("Only party leaders can use this command!");
        }
    }

    public void tryKickOffline(SmartPlayer smartPlayer) {
        if (this.isOwner(smartPlayer)) {
            List<SmartPlayer> offlinePlayers = this.getOfflinePlayers();

            if (offlinePlayers.isEmpty()) {
                smartPlayer.sendPartyInfoMessage("There are no offline players in your party.");
            } else {
                for (SmartPlayer offlinePlayer : offlinePlayers) {
                    this.removePlayerFromParty(offlinePlayer);
                }

                this.update();
                String separated = Text.separateWithCommas(offlinePlayers, SmartPlayer::getFormattedName);

                this.tellAll("%s %s%s removed from the party.", separated, YELLOW, offlinePlayers.size() == 1 ? "has been" : "have been");
            }
        } else {
            smartPlayer.sendPartyErrorMessage("Only party leaders can use this command!");
        }
    }

    public List<SmartPlayer> getOfflinePlayers() {
        List<SmartPlayer> offlinePlayers = new ArrayList<>();
        for (SmartPlayer player : this.players) {
            if (!player.isOnline()) {
                offlinePlayers.add(player);
            }
        }

        return offlinePlayers;
    }

    public void tryPromote(SmartPlayer smartPlayer, String toPromotePlayerName) {
        if (this.isOwner(smartPlayer)) {
            SmartPlayer toPromote = SmartPlayer.getSmartPlayer(toPromotePlayerName);

            if (toPromote == null) {
                smartPlayer.sendPartyErrorMessage("No player found with the name of %s%s%s.", YELLOW, toPromotePlayerName, RED);
            } else if (!this.players.contains(toPromote)) {
                smartPlayer.sendPartyErrorMessage("%s%s is not in your party.", toPromote.getFormattedName(), RED);
            } else {
                int maxForPromoted = GroupUtils.maxPlayersForPartyOwner(toPromote.getHighestGroup(), toPromote.getChampionTier());
                if (this.getSize() > maxForPromoted) {
                    smartPlayer.sendErrorMessage("The player you are trying to transfer party ownership to cannot have more than %s%s%s players in their party with their rank!",
                            YELLOW, maxForPromoted, RED);
                    return;
                }
                this.owner = toPromote;
                this.maxPartySize = -1;
                smartPlayer.sendPartySuccessMessage("%s%s has been promoted to party leader.", toPromote.getFormattedName(), GREEN);
                toPromote.sendPartyInfoMessage("You have been promoted to party leader.");
                this.update();
            }
        } else {
            smartPlayer.sendPartyErrorMessage("Only party leaders can use this command!");
        }
    }

    public void listPlayers(SmartPlayer smartPlayer) {
        ComponentBuilder componentBuilder = new ComponentBuilder();
        componentBuilder.gradientLine(ComponentBuilder.RED, ComponentBuilder.RED_ORANGE, ComponentBuilder.RED).newLine();

        componentBuilder.append(GOLD).append("Leader > ").append((this.owner.isOnline() ? GREEN : RED)).append('●').append(' ').append(this.owner.getFormattedName());
        if (this.players.size() != 1) {
            componentBuilder.newLine();
        }

        for (int i = 0; i < this.players.size(); i++) {
            SmartPlayer partyMember = this.players.get(i);
            if (!this.isOwner(partyMember)) {
                componentBuilder.append((partyMember.isOnline() ? GREEN : RED)).append('●').append(' ').append(partyMember.getFormattedName());
                if (i != this.players.size() - 1) {
                    componentBuilder.append(' ');
                }
            }
        }

        componentBuilder.newLine().gradientLine(ComponentBuilder.RED, ComponentBuilder.RED_ORANGE, ComponentBuilder.RED);
        smartPlayer.sendMessage(componentBuilder);
    }

    public void leave(SmartPlayer smartPlayer) {
        if (this.getSize() == 2) {
            if (this.isOwner(smartPlayer)) {
                this.disband(smartPlayer);
            } else {
                for (SmartPlayer player : this.players) {
                    player.sendPartyInfoMessage("The party was disbanded because %s%s left.", smartPlayer.getFormattedName(), YELLOW);
                }
                //this.broadcastDisbandMessage();
                this.destroy();
            }
        } else if (this.getSize() == 1) {
            this.disband(smartPlayer);
        } else {
            this.removePlayerFromParty(smartPlayer);
            if (this.isOwner(smartPlayer)) {
                this.owner = Miscellaneous.getRandomEntry(this.players);
                this.players.forEach(smartPlayer1 -> {
                    if (!this.isOwner(smartPlayer1)) {
                        smartPlayer1.sendPartyInfoMessage("%s%s left the party. %s%s has been promoted to the party leader.",
                                smartPlayer.getFormattedName(), YELLOW,
                                this.owner.getFormattedName(), YELLOW);
                    }
                });
                this.owner.sendPartyInfoMessage("%s%s left the party. You have been promoted to the party leader.", smartPlayer.getFormattedName(), YELLOW);
                smartPlayer.sendPartyInfoMessage("You left the party.");
            } else {
                smartPlayer.sendPartySuccessMessage("Left %s%s party.", Text.getPossessiveName(this.owner.getFormattedName()), GREEN);
                this.players.forEach(smartPlayer1 -> {
                    smartPlayer1.sendPartyInfoMessage("%s%s left the party.", smartPlayer.getFormattedName(), YELLOW);
                });
            }
            this.broadcastLeaveMessage(smartPlayer.getUUID(), smartPlayer.getName());
        }
    }

    public void tellAllExcept(SmartPlayer smartPlayer, String format, Object... data) {
        for (SmartPlayer player : this.players) {
            if (player != smartPlayer) {
                player.sendMessage(format, data);
            }
        }
    }

    public void tellNonOwner(String format, Object... data) {
        this.tellAllExcept(this.getOwner(), format, data);
    }

    public void tellAll(String format, Object... data) {
        for (SmartPlayer player : this.players) {
            player.sendMessage(format, data);
        }
    }

    public void onUpdate() {
        Main.synchronous(() -> {
            for (SmartPlayer player : this.players) {
                player.updateQueueScoreboard();
                player.sendPartyData();
            }
        });
    }

    private void broadcastJoinMessage(UUID playerJoinUUID, String playerJoinName) {
        this.onUpdate();
        /*MessageUtils.createAndBroadcast(Recipient.NONE, Command.PARTY_JOIN, playerJoinUUID.toString(), playerJoinName,
                this.toString());*/
    }

    private void broadcastLeaveMessage(UUID playerLeavingUUID, String playerLeavingName) {
        this.onUpdate();
        /*MessageUtils.createAndBroadcast(Recipient.NONE, Command.PARTY_LEAVE, playerLeavingUUID.toString(), playerLeavingName,
                this.toString());*/
    }

    private void broadcastSettingsMessage() {
        /*MessageUtils.createAndBroadcast(Recipient.NONE, Command.PARTY_SETTINGS,
                this.toString());*/
    }

    private void broadcastDisbandMessage() {
        this.onUpdate();
        MessageUtils.createAndBroadcast(Recipient.NONE, Command.PARTY_DISBAND,
                this.uuid.toString());
    }

    private void update() {
        this.broadcastSettingsMessage();
    }

    public void toggleAllInvite(SmartPlayer smartPlayer) {
        if (this.isOwner(smartPlayer)) {
            this.allInvite = !this.allInvite;
            smartPlayer.sendSuccessMessage("All invite is now %s%s.", this.allInvite ? GREEN + "ON" : RED + "OFF", GREEN);
            this.broadcastSettingsMessage();
        } else {
            smartPlayer.sendPartyErrorMessage("Only party leaders can use this command!");
        }
    }

    public void toggleAllPlay(SmartPlayer smartPlayer) {
        if (this.isOwner(smartPlayer)) {
            this.allStartGame = !this.allStartGame;
            smartPlayer.sendSuccessMessage("All queue is now %s%s.", this.allStartGame ? GREEN + "ON" : RED + "OFF", GREEN);
            this.broadcastSettingsMessage();
        } else {
            smartPlayer.sendPartyErrorMessage("Only party leaders can use this command!");
        }
    }

    public void toggleAllRolePermissions(SmartPlayer smartPlayer) {
        if (this.isOwner(smartPlayer)) {
            this.allRolePermissions = !this.allRolePermissions;
            smartPlayer.sendSuccessMessage("All role permissions is now %s%s.", this.allRolePermissions ? GREEN + "ON" : RED + "OFF", GREEN);
            this.broadcastSettingsMessage();
        } else {
            smartPlayer.sendPartyErrorMessage("Only party leaders can use this command!");
        }
    }

    public void togglePublic(SmartPlayer smartPlayer) {
        if (this.isOwner(smartPlayer)) {
            if (smartPlayer.isInGroupOrHigher(Group.CHAMPION)) {
                this.publicParty = !this.publicParty;
                smartPlayer.sendSuccessMessage("Public is now %s%s.", this.publicParty ? GREEN + "ON" : RED + "OFF", GREEN);
            } else {
                smartPlayer.sendChampionPurchaseMessage();
            }
        } else {
            smartPlayer.sendErrorMessage("Only party leaders can use this command!");
        }
    }

    public void updateMaxSize(SmartPlayer smartPlayer, int maxPartySize) {
        if (this.isOwner(smartPlayer)) {
            if (smartPlayer.isInGroupOrHigher(Group.CHAMPION)) {
                if (this.publicParty) {
                    if (maxPartySize < this.getSize() || maxPartySize > maxPartySizeForPlayer(smartPlayer)) {
                        smartPlayer.sendPartyErrorMessage("Maximum party size cannot be less than your current party size or greater than the maximum party size for your rank!");
                    } else {
                        this.maxPartySize = maxPartySize;
                        smartPlayer.sendPartySuccessMessage("The maximum size for this party is now %s%d%s.", YELLOW, maxPartySize, GREEN);
                    }
                } else {
                    smartPlayer.sendPartyErrorMessage("Maximum party size can only be modified for public parties.");
                }
            } else {
                smartPlayer.sendChampionPurchaseMessage();
            }
        } else {
            smartPlayer.sendPartyErrorMessage("Only party leaders can use this command!");
        }
    }

    public void partyChatMessage(SmartPlayer smartPlayer, String message) {
        if (smartPlayer.canSendMessage(message)) {
            smartPlayer.onSendMessage(message, ChatType.PARTY);
            ComponentBuilder start = new ComponentBuilder(ComponentBuilder.RED).append("Party > ").append(smartPlayer.getComponentFormattedName()).color(WHITE).append(": ");
            for (SmartPlayer player : this.players) {
                player.sendChatMessage(start, smartPlayer, message);
            }
        }
    }

    public void removePlayerFromParty(SmartPlayer smartPlayer) {
        this.players.remove(smartPlayer);
        smartPlayer.setCurrentParty(null);
        if (smartPlayer.isInQueue()) {
            smartPlayer.leaveSingular();
            smartPlayer.sendPartyData();
        }
        int queuedPlayers = 0;
        for (SmartPlayer player : this.players) {
            if (player.isInQueue()) {
                queuedPlayers++;
            }
        }

        if (queuedPlayers != 0 && queuedPlayers < 2) {
            for (SmartPlayer player : this.players) {
                if (player.isInQueue()) {
                    player.leaveSingular();
                }
            }
        }

    }

    public List<UUID> getNonOwnerPlayers() {
        return Miscellaneous.processList(Miscellaneous.without(this.players, this.owner), SmartPlayer::getUUID);
    }

    public String toString() {
        return this.getPartyData().toString();
    }

    public PartyData getPartyData() {
        return new PartyData(this.uuid, this.owner.getUUID(), this.getNonOwnerPlayers(), this.allRolePermissions);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Party party = (Party) o;

        return this.uuid.equals(party.uuid);
    }

    @Override
    public int hashCode() {
        return uuid != null ? uuid.hashCode() : 0;
    }

    public static boolean allPlayersInParty(List<SmartPlayer> smartPlayers) {
        return getParty(smartPlayers) != null;
    }

    public static Party getParty(List<SmartPlayer> smartPlayers) {
        for (Party value : PARTIES.values()) {
            if (value.players.containsAll(smartPlayers)) return value;
        }

        return null;
    }

    public static int maxPartySizeForPlayer(SmartPlayer smartPlayer) {
        return GroupUtils.maxPlayersForPartyOwner(smartPlayer.getHighestGroup(), smartPlayer.getChampionTier());
    }
}