package com.alttd.chat.commands; import com.alttd.chat.ChatPlugin; import com.alttd.chat.config.Config; import com.alttd.chat.database.Queries; import com.alttd.chat.managers.ChatUserManager; import com.alttd.chat.managers.PartyManager; import com.alttd.chat.objects.ChatUser; import com.alttd.chat.objects.Party; import com.alttd.chat.util.Utility; import com.google.common.io.ByteArrayDataOutput; import com.google.common.io.ByteStreams; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; import org.bukkit.command.TabCompleter; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitRunnable; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.*; import java.util.stream.Collectors; public class ChatParty implements CommandExecutor, TabCompleter { @Override public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { if(!(sender instanceof Player player)) { // must be a player return true; } if (args.length == 0) { helpMessage(sender); return true; } new BukkitRunnable() { @Override public void run() { switch (args[0].toLowerCase()) { case "create" -> { if (args.length < 3 || !args[1].matches("[\\w]{3,16}") || !args[2].matches("[\\w]{3,16}")) { invalidMessage(sender, CommandUsage.CREATE); break; } if (PartyManager.getParty(args[1]) != null) { sender.sendMessage(MiniMessage.get().parse("A chat party with this name already exists.")); break; } Party party = Queries.addParty(player.getUniqueId(), args[1], args[2]); // party.addUser(ChatUserManager.getChatUser(player.getUniqueId())); //Removed until we can get nicknames to translate to colors correctly party.addUser(ChatUserManager.getChatUser(player.getUniqueId()), player.getName()); PartyManager.addParty(party); sender.sendMessage(MiniMessage.get().parse("You created a chat party called: '" + party.getPartyName() + "' with the password: '" + party.getPartyPassword() + "'")); update(player, party.getPartyId()); } case "invite" -> { if (args.length < 2) { invalidMessage(sender, CommandUsage.INVITE); break; } Party party = PartyManager.getParty(player.getUniqueId()); if (party == null) { sender.sendMessage(MiniMessage.get().parse("You're not in a chat party.")); break; } if (!party.getOwnerUuid().equals(player.getUniqueId())) { sender.sendMessage(MiniMessage.get().parse("You don't own this chat party.")); break; } Player target = Bukkit.getPlayer(args[1]); if (target == null || !target.isOnline()) { sender.sendMessage(MiniMessage.get().parse("The player must be on the same server to receive an invite.")); break; } target.sendMessage(MiniMessage.get().parse("You received an invite to join " + party.getPartyName() + " click this message to accept.")); sender.sendMessage(MiniMessage.get().parse("You send a chat party invite to " + target.getName() + "!")); } case "join" -> { if (args.length < 3 || !args[1].matches("[\\w]{3,16}") || !args[2].matches("[\\w]{3,16}")) { invalidMessage(sender, CommandUsage.JOIN); break; } Party party = PartyManager.getParty(args[1]); if (party == null) { sender.sendMessage(MiniMessage.get().parse("This chat party does not exist.")); break; } if (!party.getPartyPassword().equals(args[2])) { sender.sendMessage(MiniMessage.get().parse("Invalid password.")); break; } // party.addUser(ChatUserManager.getChatUser(player.getUniqueId())); //Removed until we can get nicknames to translate to colors correctly party.addUser(ChatUserManager.getChatUser(player.getUniqueId()), player.getName()); sender.sendMessage(MiniMessage.get().parse("You joined " + party.getPartyName() + "!")); update(player, party.getPartyId()); } case "leave" -> { Party party = PartyManager.getParty(player.getUniqueId()); if (party == null) { sender.sendMessage(MiniMessage.get().parse("You're not in a chat party.")); break; } party.removeUser(player.getUniqueId()); if (party.getOwnerUuid().equals(player.getUniqueId())) { if (party.getPartyUsers().size() > 0) { UUID uuid = party.newOwner(); sender.sendMessage(MiniMessage.get().parse("Since you own this chat party a new party owner will be chosen.")); ChatPlugin.getInstance().getChatHandler().partyMessage(party, player, "" + player.getName() + " left the chat party, the new party owner is " + party.getUserDisplayName(uuid)); } else { party.delete(); } } else { sender.sendMessage(MiniMessage.get().parse("You have left the chat party!")); } update(player, party.getPartyId()); } case "remove" -> { if (args.length < 2) { invalidMessage(sender, CommandUsage.REMOVE); break; } Party party = PartyManager.getParty(player.getUniqueId()); if (party == null) { sender.sendMessage(MiniMessage.get().parse("You're not in a chat party.")); break; } if (!party.getOwnerUuid().equals(player.getUniqueId())) { sender.sendMessage("You don't own this chat party."); break; } OfflinePlayer offlinePlayerIfCached = Bukkit.getOfflinePlayerIfCached((args[1])); if (offlinePlayerIfCached == null) { sender.sendMessage(MiniMessage.get().parse("Unable to find this player.")); return; } party.removeUser(ChatUserManager.getChatUser(offlinePlayerIfCached.getUniqueId())); if (offlinePlayerIfCached.getUniqueId().equals(party.getOwnerUuid())) { sender.sendMessage(MiniMessage.get().parse("You can't remove yourself, please leave instead.")); return; } if (offlinePlayerIfCached.isOnline()) { Objects.requireNonNull(offlinePlayerIfCached.getPlayer()) .sendMessage(MiniMessage.get().parse("You were removed from the '" + party.getPartyName() + "' chat party.")); } sender.sendMessage(MiniMessage.get().parse("You removed " + offlinePlayerIfCached.getName() + " from the chat party!")); update(player, party.getPartyId()); } case "info" -> { Party party = PartyManager.getParty(player.getUniqueId()); if (party == null) { sender.sendMessage(MiniMessage.get().parse("You're not in a chat party.")); break; } StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("Chat party info:\n") .append("Name: ").append(party.getPartyName()).append("\n") .append(party.getOwnerUuid().equals(player.getUniqueId()) ? "Password: " + party.getPartyPassword() + "\n" : "") .append("Owner: ").append(party.getUserDisplayName(party.getOwnerUuid())).append("\n") .append("Members: "); for (String displayName : party.getPartyUsers().values()) { stringBuilder.append(displayName).append(", "); } stringBuilder.delete(stringBuilder.length() - 2, stringBuilder.length()); sender.sendMessage(Utility.applyColor(stringBuilder.toString())); } // TODO: 08/08/2021 add a way to change the password and owner (and name?) default -> { helpMessage(sender); } } } }.runTaskAsynchronously(ChatPlugin.getInstance()); return false; } private void invalidMessage(CommandSender sender, CommandUsage commandUsage) { sender.sendMessage(MiniMessage.get().parse("Invalid command, proper usage: %command%.".replaceAll("%command%", commandUsage.message))); } private void helpMessage(CommandSender sender) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("Chat party commands:"); for (CommandUsage commandUsage : CommandUsage.values()) { stringBuilder.append("\n- ").append(commandUsage.message); } stringBuilder.append(""); sender.sendMessage(MiniMessage.get().parse(stringBuilder.toString())); } @Override public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { List possibleValues = new ArrayList<>(); String current = args.length > 0 ? args[args.length - 1].toLowerCase() : ""; if (args.length <= 1) { possibleValues.add("create"); possibleValues.add("invite"); possibleValues.add("join"); possibleValues.add("leave"); possibleValues.add("remove"); possibleValues.add("info"); return finalizeSuggest(possibleValues, current); } switch (args[0].toLowerCase()) { case "invite","remove" -> { Bukkit.getOnlinePlayers().stream().filter(p -> !p.getName().equals(sender.getName())).forEach(p -> possibleValues.add(p.getName())); } } return finalizeSuggest(possibleValues, current.toLowerCase()); } public List finalizeSuggest(List possibleValues, String remaining) { List finalValues = new ArrayList<>(); for (String str : possibleValues) { if (str.toLowerCase().startsWith(remaining)) { finalValues.add(str); } } return finalValues; } private void update(Player player, int partyId) { // FIXME: 08/08/2021 This only updates members btw and should be replaced with per change messages ByteArrayDataOutput out = ByteStreams.newDataOutput(); out.writeUTF("tmppartyupdate"); out.writeUTF(String.valueOf(partyId)); player.sendPluginMessage(ChatPlugin.getInstance(), Config.MESSAGECHANNEL, out.toByteArray()); } private enum CommandUsage { CREATE("/chatparty create <#FFE800>A chat party name must be 3-16 characters'> " + "A chat party password must be 3-16 characters\n" + "When choosing a password keep in mind staff can see it and you might need to share it with other players!'>"), INVITE("/chatparty invite "), JOIN("/chatparty join "), LEAVE("If the chat party owner leaves the server will choose a new chat party owner'>/chatparty leave"), REMOVE("/chatparty remove "), INFO("/chatparty info"); private final String message; CommandUsage(String message) { this.message = message; } } }