package com.alttd.velocitychat.commands; import com.alttd.chat.util.Utility; import com.alttd.velocitychat.commands.vote_to_mute.ActiveVoteToMute; import com.alttd.velocitychat.commands.vote_to_mute.VoteToMuteStarter; import com.mojang.brigadier.arguments.IntegerArgumentType; import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.builder.RequiredArgumentBuilder; import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.tree.LiteralCommandNode; import com.velocitypowered.api.command.BrigadierCommand; import com.velocitypowered.api.command.CommandMeta; import com.velocitypowered.api.command.CommandSource; import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.ProxyServer; import com.velocitypowered.api.proxy.ServerConnection; import com.velocitypowered.api.proxy.server.RegisteredServer; import jdk.jshell.execution.Util; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; import java.time.Duration; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.IntStream; public class VoteToMuteHelper { private static final Component prefix = Utility.parseMiniMessage("[VoteMute]"); public VoteToMuteHelper(ProxyServer proxyServer) { RequiredArgumentBuilder playerNode = RequiredArgumentBuilder .argument("player", StringArgumentType.string()) .suggests((context, builder) -> { List possiblePlayers; if (context.getSource() instanceof Player player) { Optional currentServer = player.getCurrentServer(); if (currentServer.isPresent()) { possiblePlayers = getEligiblePlayers(currentServer.get().getServer()); } else { possiblePlayers = getEligiblePlayers(proxyServer); } } else { possiblePlayers = getEligiblePlayers(proxyServer); } Collection possibleValues = possiblePlayers.stream() .map(Player::getUsername) .toList(); if (possibleValues.isEmpty()) return Suggestions.empty(); String remaining = builder.getRemaining().toLowerCase(); possibleValues.stream() .filter(str -> str.toLowerCase().startsWith(remaining)) .map(StringArgumentType::escapeIfRequired) .forEach(builder::suggest); return builder.buildFuture(); }) .executes(context -> { sendHelpMessage(context.getSource()); return 1; }); RequiredArgumentBuilder yesNoNode = RequiredArgumentBuilder. argument("yesNo", StringArgumentType.string()) .suggests(((commandContext, suggestionsBuilder) -> { List yesNoValues = Arrays.asList("yes", "no"); String remaining = suggestionsBuilder.getRemaining().toLowerCase(); yesNoValues.stream() .filter((String str) -> str.toLowerCase().startsWith(remaining)) .map(StringArgumentType::escapeIfRequired) .forEach(suggestionsBuilder::suggest); return suggestionsBuilder.buildFuture(); })); LiteralArgumentBuilder pageNode = LiteralArgumentBuilder .literal("page") .requires(commandSource -> commandSource.hasPermission("chat.vote-to-mute")) .then(RequiredArgumentBuilder.argument("page number", IntegerArgumentType.integer(1)) .suggests(((commandContext, suggestionsBuilder) -> { if (!(commandContext.getSource() instanceof Player player)) { return suggestionsBuilder.buildFuture(); } Optional instance = VoteToMuteStarter.getInstance(player.getUniqueId()); if (instance.isEmpty()) { return suggestionsBuilder.buildFuture(); } VoteToMuteStarter voteToMuteStarter = instance.get(); String remaining = suggestionsBuilder.getRemaining().toLowerCase(); int totalPages = voteToMuteStarter.getTotalPages(); IntStream.range(1, totalPages + 1) .mapToObj(String::valueOf) .filter((String str) -> str.toLowerCase().startsWith(remaining)) .map(StringArgumentType::escapeIfRequired) .forEach(suggestionsBuilder::suggest); return suggestionsBuilder.buildFuture(); })) .executes(commandContext -> { if (!(commandContext.getSource() instanceof Player player)) { commandContext.getSource().sendMessage(Utility.parseMiniMessage("Only players can use this command.")); return 1; } Optional instance = VoteToMuteStarter.getInstance(player.getUniqueId()); if (instance.isEmpty()) { commandContext.getSource().sendMessage(Utility.parseMiniMessage("You don't have an active vote to mute.")); return 1; } int pageNumber = commandContext.getArgument("page number", Integer.class); instance.get().showPage(pageNumber); return 1; }) ).executes(commandContext -> { sendHelpMessage(commandContext.getSource()); return 1; }); LiteralArgumentBuilder enterMessagesNode = LiteralArgumentBuilder .literal("messages") .requires(commandSource -> commandSource.hasPermission("chat.vote-to-mute")) .then(RequiredArgumentBuilder.argument("list of messages", StringArgumentType.greedyString()) .executes(commandContext -> { if (!(commandContext.getSource() instanceof Player player)) { commandContext.getSource().sendMessage(Utility.parseMiniMessage("Only players can use this command.")); return 1; } Optional instance = VoteToMuteStarter.getInstance(player.getUniqueId()); if (instance.isEmpty()) { commandContext.getSource().sendMessage(Utility.parseMiniMessage("You don't have an active vote to mute.")); return 1; } String listOfPages = commandContext.getArgument("list of messages", String.class); if (!listOfPages.matches("([1-9][0-9]*, )*[1-9][0-9]*")) { commandContext.getSource().sendMessage(Utility.parseMiniMessage("Please make sure to format the command correctly.")); return 1; } VoteToMuteStarter voteToMuteStarter = instance.get(); List collect = Arrays.stream(listOfPages.split(", ")) .map(Integer::parseInt) .collect(Collectors.toList()); Optional max = collect.stream().max(Integer::compare); if (max.isEmpty()) { commandContext.getSource().sendMessage(Utility.parseMiniMessage("Some of your selected messages do not exist.")); return 1; } int highestLogEntry = max.get(); if (voteToMuteStarter.getTotalLogEntries() < highestLogEntry) { commandContext.getSource().sendMessage(Utility.parseMiniMessage("Some of your selected messages do not exist.")); return 1; } Optional currentServer = player.getCurrentServer(); if (currentServer.isEmpty()) { sendHelpMessage(commandContext.getSource()); return 1; } Component chatLogs = voteToMuteStarter.getChatLogsAndClose(collect); RegisteredServer server = currentServer.get().getServer(); long count = getTotalEligiblePlayers(server, voteToMuteStarter.countLowerRanks()); new ActiveVoteToMute(voteToMuteStarter.getVotedPlayer(), server, proxyServer, Duration.ofMinutes(5), (int) count, voteToMuteStarter.countLowerRanks(), chatLogs, player) .start(); return 1; }) ).executes(commandContext -> { sendHelpMessage(commandContext.getSource()); return 1; }); LiteralArgumentBuilder voteNode = LiteralArgumentBuilder .literal("vote") .then(playerNode .then(yesNoNode .executes(commandContext -> { if (!(commandContext.getSource() instanceof Player player)) { commandContext.getSource().sendMessage(Utility.parseMiniMessage( "Only players are allowed to vote")); return 1; } String playerName = commandContext.getArgument("player", String.class); Optional optionalActiveVoteToMute = ActiveVoteToMute.getInstance(playerName); if (optionalActiveVoteToMute.isEmpty()) { commandContext.getSource().sendMessage(Utility.parseMiniMessage( "This player does not have an active vote to mute them.")); return 1; } ActiveVoteToMute activeVoteToMute = optionalActiveVoteToMute.get(); if (!activeVoteToMute.countLowerRanks()) { if (!player.hasPermission("chat.vote-to-mute")) { player.sendMessage(Utility.parseMiniMessage("You are not eligible to vote.")); return 1; } } String vote = commandContext.getArgument("yesNo", String.class); switch (vote.toLowerCase()) { case "yes" -> { activeVoteToMute.vote(player.getUniqueId(), true); commandContext.getSource().sendMessage(Utility.parseMiniMessage( "You voted to mute. Thanks for voting, staff will be online soon to review!")); player.getCurrentServer().ifPresent(serverConnection -> notifyEligiblePlayers(serverConnection.getServer(), activeVoteToMute)); } case "no" -> { activeVoteToMute.vote(player.getUniqueId(), false); commandContext.getSource().sendMessage(Utility.parseMiniMessage( "You voted not to mute. Thanks for voting, staff will be online soon to review!")); } default -> commandContext.getSource().sendMessage(Utility.parseMiniMessage( " is not a valid vote option", Placeholder.parsed("vote", vote))); } return 1; })).executes(context -> { sendHelpMessage(context.getSource()); return 1; })).executes(context -> { sendHelpMessage(context.getSource()); return 1; }); LiteralCommandNode command = LiteralArgumentBuilder .literal("votetomutehelper") .requires(commandSource -> commandSource.hasPermission("chat.backup-vote-to-mute")) .requires(commandSource -> commandSource instanceof Player) .then(voteNode) .then(pageNode) .then(enterMessagesNode) .executes(context -> { sendHelpMessage(context.getSource()); return 1; }) .build(); BrigadierCommand brigadierCommand = new BrigadierCommand(command); CommandMeta.Builder metaBuilder = proxyServer.getCommandManager().metaBuilder(brigadierCommand); CommandMeta meta = metaBuilder.build(); proxyServer.getCommandManager().register(meta, brigadierCommand); } private int getTotalEligiblePlayers(RegisteredServer server, boolean countLowerRanks) { return (int) server.getPlayersConnected().stream() .filter(player -> countLowerRanks ? player.hasPermission("chat.backup-vote-to-mute") : player.hasPermission("chat.vote-to-mute")) .count(); } private void notifyEligiblePlayers(RegisteredServer server, ActiveVoteToMute activeVoteToMute) { Component message = Utility.parseMiniMessage(" out of players have voted to mute ", Placeholder.component("prefix", prefix), Placeholder.parsed("voted_for", String.valueOf(activeVoteToMute.getVotedFor())), Placeholder.parsed("total_votes", String.valueOf(activeVoteToMute.getTotalEligibleVoters())), Placeholder.parsed("player", activeVoteToMute.getVotedPlayer().getUsername())); boolean countLowerRanks = activeVoteToMute.countLowerRanks(); server.getPlayersConnected().stream() .filter(player -> countLowerRanks ? player.hasPermission("chat.backup-vote-to-mute") : player.hasPermission("chat.vote-to-mute")) .forEach(player -> player.sendMessage(message)); } private void sendHelpMessage(CommandSource commandSource) { commandSource.sendMessage(Utility.parseMiniMessage("Use: /votetomutehelper .")); } private List getEligiblePlayers(ProxyServer proxyServer) { return proxyServer.getAllPlayers().stream() .filter(player -> player.hasPermission("chat.affected-by-vote-to-mute")) .collect(Collectors.toList()); } private List getEligiblePlayers(RegisteredServer registeredServer) { return registeredServer.getPlayersConnected().stream() .filter(player -> player.hasPermission("chat.affected-by-vote-to-mute")) .collect(Collectors.toList()); } }