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()); } }