Search in sources :

Example 1 with Pair

use of net.dv8tion.jda.internal.utils.tuple.Pair in project DiscordSRV by DiscordSRV.

the class VoiceModule method tick.

private void tick() {
    if (!lock.tryLock()) {
        DiscordSRV.debug(Debug.VOICE, "Skipping voice module tick, a tick is already in progress");
        return;
    }
    try {
        Category category = getCategory();
        if (category == null) {
            DiscordSRV.debug(Debug.VOICE, "Skipping voice module tick, category is null");
            return;
        }
        VoiceChannel lobbyChannel = getLobbyChannel();
        if (lobbyChannel == null) {
            DiscordSRV.debug(Debug.VOICE, "Skipping voice module tick, lobby channel is null");
            return;
        }
        // check that the permissions are correct
        Member selfMember = lobbyChannel.getGuild().getSelfMember();
        Role publicRole = lobbyChannel.getGuild().getPublicRole();
        long currentTime = System.currentTimeMillis();
        boolean log = lastLogTime + TimeUnit.SECONDS.toMillis(30) < currentTime;
        boolean stop = false;
        for (Permission permission : LOBBY_REQUIRED_PERMISSIONS) {
            if (!selfMember.hasPermission(lobbyChannel, permission)) {
                if (log)
                    DiscordSRV.error("The bot doesn't have the \"" + permission.getName() + "\" permission in the voice lobby (" + lobbyChannel.getName() + ")");
                stop = true;
            }
        }
        for (Permission permission : CATEGORY_REQUIRED_PERMISSIONS) {
            if (!selfMember.hasPermission(category, permission)) {
                if (log)
                    DiscordSRV.error("The bot doesn't have the \"" + permission.getName() + "\" permission in the voice category (" + category.getName() + ")");
                stop = true;
            }
        }
        // we can't function & would throw exceptions
        if (stop) {
            lastLogTime = currentTime;
            return;
        }
        PermissionOverride lobbyPublicRoleOverride = lobbyChannel.getPermissionOverride(publicRole);
        if (lobbyPublicRoleOverride == null) {
            lobbyChannel.createPermissionOverride(publicRole).deny(Permission.VOICE_SPEAK).queue();
        } else if (!lobbyPublicRoleOverride.getDenied().contains(Permission.VOICE_SPEAK)) {
            lobbyPublicRoleOverride.getManager().deny(Permission.VOICE_SPEAK).queue();
        }
        // remove networks that have no voice channel
        networks.removeIf(network -> network.getChannel() == null && network.isInitialized());
        Set<Player> alivePlayers = PlayerUtil.getOnlinePlayers().stream().filter(player -> !player.isDead()).collect(Collectors.toSet());
        Set<UUID> oldDirtyPlayers = dirtyPlayers;
        dirtyPlayers = new HashSet<>();
        for (UUID uuid : oldDirtyPlayers) {
            Player player = Bukkit.getPlayer(uuid);
            if (player == null)
                continue;
            Member member = getMember(player.getUniqueId());
            if (member == null) {
                DiscordSRV.debug(Debug.VOICE, "Player " + player.getName() + " isn't linked, skipping voice checks");
                continue;
            }
            if (member.getVoiceState() == null || member.getVoiceState().getChannel() == null) {
                DiscordSRV.debug(Debug.VOICE, "Player " + player.getName() + " is not connected to voice");
                continue;
            }
            VoiceChannel playerChannel = member.getVoiceState().getChannel();
            boolean isLobby = playerChannel.getId().equals(getLobbyChannel().getId());
            if (!isLobby && (playerChannel.getParent() == null || !playerChannel.getParent().getId().equals(getCategory().getId()))) {
                DiscordSRV.debug(Debug.VOICE, "Player " + player.getName() + " was not in the voice lobby or category");
                // cancel existing moves if they changed to a different channel
                Pair<String, CompletableFuture<Void>> pair = awaitingMoves.get(member.getId());
                if (pair != null)
                    pair.getRight().cancel(false);
                continue;
            }
            // add player to networks that they may have came into contact with
            // and combine multiple networks if the player is connecting them together
            networks.stream().filter(network -> network.isPlayerInRangeToBeAdded(player)).reduce((network1, network2) -> network1.size() > network2.size() ? network1.engulf(network2) : network2.engulf(network1)).filter(network -> !network.contains(player.getUniqueId())).ifPresent(network -> {
                DiscordSRV.debug(Debug.VOICE, player.getName() + " has entered network " + network + "'s influence, connecting");
                network.add(player.getUniqueId());
            });
            // remove player from networks that they lost connection to
            networks.stream().filter(network -> network.contains(player.getUniqueId())).filter(network -> !network.isPlayerInRangeToStayConnected(player)).forEach(network -> {
                DiscordSRV.debug(Debug.VOICE, "Player " + player.getName() + " lost connection to " + network + ", disconnecting");
                network.remove(player.getUniqueId());
                if (network.size() == 1)
                    network.clear();
            });
            // create networks if two players are within activation distance
            Set<UUID> playersWithinRange = alivePlayers.stream().filter(p -> networks.stream().noneMatch(network -> network.contains(p))).filter(p -> !p.equals(player)).filter(p -> p.getWorld().getName().equals(player.getWorld().getName())).filter(p -> horizontalDistance(p.getLocation(), player.getLocation()) <= getHorizontalStrength() && verticalDistance(p.getLocation(), player.getLocation()) <= getVerticalStrength()).filter(p -> {
                Member m = getMember(p.getUniqueId());
                return m != null && m.getVoiceState() != null && m.getVoiceState().getChannel() != null && m.getVoiceState().getChannel().getParent() != null && m.getVoiceState().getChannel().getParent().equals(category);
            }).map(Player::getUniqueId).collect(Collectors.toCollection(ConcurrentHashMap::newKeySet));
            if (playersWithinRange.size() > 0) {
                if (category.getChannels().size() == 50) {
                    DiscordSRV.debug(Debug.VOICE, "Can't create new voice network because category " + category.getName() + " is full of channels");
                    continue;
                }
                playersWithinRange.add(uuid);
                networks.add(new Network(playersWithinRange));
            }
        }
        // handle moving players between channels
        Set<Member> members = new HashSet<>(lobbyChannel.getMembers());
        for (Network network : getNetworks()) {
            VoiceChannel voiceChannel = network.getChannel();
            if (voiceChannel == null)
                continue;
            members.addAll(voiceChannel.getMembers());
        }
        for (Member member : members) {
            UUID uuid = getUniqueId(member);
            VoiceChannel playerChannel = member.getVoiceState().getChannel();
            Network playerNetwork = uuid != null ? networks.stream().filter(n -> n.contains(uuid)).findAny().orElse(null) : null;
            VoiceChannel shouldBeInChannel;
            if (playerNetwork != null) {
                if (playerNetwork.getChannel() == null) {
                    // isn't yet created, we can wait until next tick
                    continue;
                }
                shouldBeInChannel = playerNetwork.getChannel();
            } else {
                shouldBeInChannel = lobbyChannel;
            }
            Pair<String, CompletableFuture<Void>> awaitingMove = awaitingMoves.get(member.getId());
            // they're already where they're suppose to be
            if (awaitingMove != null && awaitingMove.getLeft().equals(shouldBeInChannel.getId()))
                continue;
            // if the cancel succeeded we can move them
            if (awaitingMove != null && !awaitingMove.getLeft().equals(shouldBeInChannel.getId()) && !awaitingMove.getRight().cancel(false))
                continue;
            // schedule a move to the channel they're suppose to be in, if they aren't there yet
            if (!playerChannel.getId().equals(shouldBeInChannel.getId())) {
                awaitingMoves.put(member.getId(), Pair.of(shouldBeInChannel.getId(), getGuild().moveVoiceMember(member, shouldBeInChannel).submit().whenCompleteAsync((v, t) -> awaitingMoves.remove(member.getId()))));
            }
        }
        // delete empty networks
        for (Network network : new HashSet<>(networks)) {
            if (!network.isEmpty())
                continue;
            VoiceChannel voiceChannel = network.getChannel();
            if (voiceChannel == null)
                continue;
            if (voiceChannel.getMembers().isEmpty()) {
                voiceChannel.delete().reason("Lost communication").queue();
                networks.remove(network);
            }
        }
    } finally {
        lock.unlock();
    }
}
Also used : net.dv8tion.jda.api.entities(net.dv8tion.jda.api.entities) java.util(java.util) Getter(lombok.Getter) Permission(net.dv8tion.jda.api.Permission) VoiceChannelDeleteEvent(net.dv8tion.jda.api.events.channel.voice.VoiceChannelDeleteEvent) GuildVoiceLeaveEvent(net.dv8tion.jda.api.events.guild.voice.GuildVoiceLeaveEvent) PlayerMoveEvent(org.bukkit.event.player.PlayerMoveEvent) CompletableFuture(java.util.concurrent.CompletableFuture) DiscordUtil(github.scarsz.discordsrv.util.DiscordUtil) Player(org.bukkit.entity.Player) StringUtils(org.apache.commons.lang3.StringUtils) EventHandler(org.bukkit.event.EventHandler) Pair(net.dv8tion.jda.internal.utils.tuple.Pair) Location(org.bukkit.Location) DiscordSRV(github.scarsz.discordsrv.DiscordSRV) Bukkit(org.bukkit.Bukkit) Listener(org.bukkit.event.Listener) PlayerJoinEvent(org.bukkit.event.player.PlayerJoinEvent) GuildVoiceMoveEvent(net.dv8tion.jda.api.events.guild.voice.GuildVoiceMoveEvent) ReentrantLock(java.util.concurrent.locks.ReentrantLock) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) ListenerAdapter(net.dv8tion.jda.api.hooks.ListenerAdapter) Collectors(java.util.stream.Collectors) OfflinePlayer(org.bukkit.OfflinePlayer) Debug(github.scarsz.discordsrv.Debug) TimeUnit(java.util.concurrent.TimeUnit) GuildVoiceJoinEvent(net.dv8tion.jda.api.events.guild.voice.GuildVoiceJoinEvent) PlayerUtil(github.scarsz.discordsrv.util.PlayerUtil) EventPriority(org.bukkit.event.EventPriority) PlayerTeleportEvent(org.bukkit.event.player.PlayerTeleportEvent) PlayerQuitEvent(org.bukkit.event.player.PlayerQuitEvent) NumberConversions(org.bukkit.util.NumberConversions) NotNull(org.jetbrains.annotations.NotNull) Player(org.bukkit.entity.Player) OfflinePlayer(org.bukkit.OfflinePlayer) CompletableFuture(java.util.concurrent.CompletableFuture) Permission(net.dv8tion.jda.api.Permission)

Example 2 with Pair

use of net.dv8tion.jda.internal.utils.tuple.Pair in project RtaB6 by Telnaior.

the class RaceDeal method startGame.

@Override
void startGame() {
    casesLeft = 26;
    round = 0;
    // Start by adding the fixed values
    valueList = new ArrayList<Pair<Integer, SpecialType>>(casesLeft);
    valueList.add(Pair.of(applyBaseMultiplier(-10_000_000), SpecialType.CASH));
    // Just like the regular DoND minigame, this isn't multiplied
    valueList.add(Pair.of(1, SpecialType.CASH));
    // Lowest Red Value
    valueList.add(Pair.of(applyBaseMultiplier(1_000_000), SpecialType.CASH));
    // +999% Boost
    valueList.add(Pair.of(applyBaseMultiplier(9_990_000), SpecialType.MAX_BOOST));
    valueList.add(Pair.of(applyBaseMultiplier(100_000_000), SpecialType.CASH));
    // All Bonus Games - this may be undervalued but it'll push them to win it
    valueList.add(Pair.of(applyBaseMultiplier(123_456_789), SpecialType.BONUS_GAMES));
    // $1,000,000,000 - the value of which is reduced by the player's bank
    valueList.add(Pair.of(1_000_000_000 - getCurrentPlayer().money, SpecialType.BILLION));
    int negativeToAdd = 6;
    int blueToAdd = 5;
    int redToAdd = 8;
    // Calculate mystery chance value as the average of all players' cash amounts
    mysteryChanceBase = 0;
    for (Player next : players) mysteryChanceBase += next.money / players.size();
    // Finally, average it with the current player's money
    mysteryChanceBase = (mysteryChanceBase + getCurrentPlayer().money) / 2;
    // Minimum value to make sure Mystery Chance is interesting / playable
    mysteryChanceBase = Math.max(mysteryChanceBase, 1_234_567);
    mysteryChance = false;
    // And this becomes the amount they stand to gain/lose on average
    int mysteryChanceValue = mysteryChanceBase - getCurrentPlayer().money;
    // Then add it, replacing a random value as relevant
    valueList.add(Pair.of(mysteryChanceValue, SpecialType.MYSTERY_CHANCE));
    if (mysteryChanceValue > 1_000_000)
        redToAdd--;
    else
        negativeToAdd--;
    // Now shuffle the random values and use them to fill the gaps
    Collections.shuffle(randomNegativeValues);
    Collections.shuffle(randomBlueValues);
    Collections.shuffle(randomRedValues);
    for (int i = 0; i < negativeToAdd; i++) valueList.add(Pair.of(applyBaseMultiplier(randomNegativeValues.get(i)), SpecialType.CASH));
    for (int i = 0; i < blueToAdd; i++) valueList.add(Pair.of(applyBaseMultiplier(randomBlueValues.get(i)), SpecialType.CASH));
    for (int i = 0; i < redToAdd; i++) valueList.add(Pair.of(applyBaseMultiplier(randomRedValues.get(i)), SpecialType.CASH));
    // Finally, sort the board
    valueList.sort(new AscendingValueSorter());
    // Now shuffle the values into the cases
    caseList = new ArrayList<Integer>(casesLeft);
    for (int i = 0; i < casesLeft; i++) caseList.add(i);
    Collections.shuffle(caseList);
    openedCases = new boolean[casesLeft];
    // No case selected yet
    chosenCase = -1;
    casesToOpen = -1;
    acceptedOffer = false;
    // Alright, we got ourselves organised, give them the achievement for making it here and tell them what's happening
    Achievement.TWENTY.check(getCurrentPlayer());
    LinkedList<String> output = new LinkedList<>();
    output.add("For reaching a streak bonus of x20, you have earned the right to play the final bonus game!");
    output.add("Race Deal is a lot like regular Deal or No Deal, except the stakes are a lot higher.");
    output.add("In fact, one of the twenty-six cases in front of you contains one billion dollars!");
    output.add("There are also some negative values, however, so be extra careful not to get stuck with one of them.");
    output.add("In addition, there are three cases that will award other prizes in lieu of cash.");
    output.add("Winning +999% Boost will max out your boost, and award you a small monetary prize based on the excess.");
    output.add("Winning 4 Bonus Games will give you the opportunity to play Supercash, Digital Fortress, Spectrum, and Hypercube in turn.");
    output.add("Finally, if won, Mystery Chance will remove and replace your *entire cash bank* with a new value decided at random. " + "This could earn you hundreds of millions, or *cost* you the same. Win it at your own risk.");
    output.add("You will choose six cases to open before the first offer, and each future round will require one case less " + "until the final six cases are opened one at a time.");
    output.add("Before that, however, you must first decide which case you want to be yours.");
    output.add("There will not be any opportunity to change your case later, so choose wisely and good luck!");
    sendSkippableMessages(output);
    sendMessage(generateBoard());
    getInput();
}
Also used : Player(tel.discord.rtab.Player) LinkedList(java.util.LinkedList) Pair(net.dv8tion.jda.internal.utils.tuple.Pair)

Example 3 with Pair

use of net.dv8tion.jda.internal.utils.tuple.Pair in project DiscordSRV by Scarsz.

the class VoiceModule method tick.

private void tick() {
    if (!lock.tryLock()) {
        DiscordSRV.debug(Debug.VOICE, "Skipping voice module tick, a tick is already in progress");
        return;
    }
    try {
        Category category = getCategory();
        if (category == null) {
            DiscordSRV.debug(Debug.VOICE, "Skipping voice module tick, category is null");
            return;
        }
        VoiceChannel lobbyChannel = getLobbyChannel();
        if (lobbyChannel == null) {
            DiscordSRV.debug(Debug.VOICE, "Skipping voice module tick, lobby channel is null");
            return;
        }
        // check that the permissions are correct
        Member selfMember = lobbyChannel.getGuild().getSelfMember();
        Role publicRole = lobbyChannel.getGuild().getPublicRole();
        long currentTime = System.currentTimeMillis();
        boolean log = lastLogTime + TimeUnit.SECONDS.toMillis(30) < currentTime;
        boolean stop = false;
        for (Permission permission : LOBBY_REQUIRED_PERMISSIONS) {
            if (!selfMember.hasPermission(lobbyChannel, permission)) {
                if (log)
                    DiscordSRV.error("The bot doesn't have the \"" + permission.getName() + "\" permission in the voice lobby (" + lobbyChannel.getName() + ")");
                stop = true;
            }
        }
        for (Permission permission : CATEGORY_REQUIRED_PERMISSIONS) {
            if (!selfMember.hasPermission(category, permission)) {
                if (log)
                    DiscordSRV.error("The bot doesn't have the \"" + permission.getName() + "\" permission in the voice category (" + category.getName() + ")");
                stop = true;
            }
        }
        // we can't function & would throw exceptions
        if (stop) {
            lastLogTime = currentTime;
            return;
        }
        PermissionOverride lobbyPublicRoleOverride = lobbyChannel.getPermissionOverride(publicRole);
        if (lobbyPublicRoleOverride == null) {
            lobbyChannel.createPermissionOverride(publicRole).deny(Permission.VOICE_SPEAK).queue();
        } else if (!lobbyPublicRoleOverride.getDenied().contains(Permission.VOICE_SPEAK)) {
            lobbyPublicRoleOverride.getManager().deny(Permission.VOICE_SPEAK).queue();
        }
        // remove networks that have no voice channel
        networks.removeIf(network -> network.getChannel() == null && network.isInitialized());
        Set<Player> alivePlayers = PlayerUtil.getOnlinePlayers().stream().filter(player -> !player.isDead()).collect(Collectors.toSet());
        Set<UUID> oldDirtyPlayers = dirtyPlayers;
        dirtyPlayers = new HashSet<>();
        for (UUID uuid : oldDirtyPlayers) {
            Player player = Bukkit.getPlayer(uuid);
            if (player == null)
                continue;
            Member member = getMember(player.getUniqueId());
            if (member == null) {
                DiscordSRV.debug(Debug.VOICE, "Player " + player.getName() + " isn't linked, skipping voice checks");
                continue;
            }
            if (member.getVoiceState() == null || member.getVoiceState().getChannel() == null) {
                DiscordSRV.debug(Debug.VOICE, "Player " + player.getName() + " is not connected to voice");
                continue;
            }
            VoiceChannel playerChannel = member.getVoiceState().getChannel();
            boolean isLobby = playerChannel.getId().equals(getLobbyChannel().getId());
            if (!isLobby && (playerChannel.getParent() == null || !playerChannel.getParent().getId().equals(getCategory().getId()))) {
                DiscordSRV.debug(Debug.VOICE, "Player " + player.getName() + " was not in the voice lobby or category");
                // cancel existing moves if they changed to a different channel
                Pair<String, CompletableFuture<Void>> pair = awaitingMoves.get(member.getId());
                if (pair != null)
                    pair.getRight().cancel(false);
                continue;
            }
            // add player to networks that they may have came into contact with
            // and combine multiple networks if the player is connecting them together
            networks.stream().filter(network -> network.isPlayerInRangeToBeAdded(player)).reduce((network1, network2) -> network1.size() > network2.size() ? network1.engulf(network2) : network2.engulf(network1)).filter(network -> !network.contains(player.getUniqueId())).ifPresent(network -> {
                DiscordSRV.debug(Debug.VOICE, player.getName() + " has entered network " + network + "'s influence, connecting");
                network.add(player.getUniqueId());
            });
            // remove player from networks that they lost connection to
            networks.stream().filter(network -> network.contains(player.getUniqueId())).filter(network -> !network.isPlayerInRangeToStayConnected(player)).forEach(network -> {
                DiscordSRV.debug(Debug.VOICE, "Player " + player.getName() + " lost connection to " + network + ", disconnecting");
                network.remove(player.getUniqueId());
                if (network.size() == 1)
                    network.clear();
            });
            // create networks if two players are within activation distance
            Set<UUID> playersWithinRange = alivePlayers.stream().filter(p -> networks.stream().noneMatch(network -> network.contains(p))).filter(p -> !p.equals(player)).filter(p -> p.getWorld().getName().equals(player.getWorld().getName())).filter(p -> horizontalDistance(p.getLocation(), player.getLocation()) <= getHorizontalStrength() && verticalDistance(p.getLocation(), player.getLocation()) <= getVerticalStrength()).filter(p -> {
                Member m = getMember(p.getUniqueId());
                return m != null && m.getVoiceState() != null && m.getVoiceState().getChannel() != null && m.getVoiceState().getChannel().getParent() != null && m.getVoiceState().getChannel().getParent().equals(category);
            }).map(Player::getUniqueId).collect(Collectors.toCollection(ConcurrentHashMap::newKeySet));
            if (playersWithinRange.size() > 0) {
                if (category.getChannels().size() == 50) {
                    DiscordSRV.debug(Debug.VOICE, "Can't create new voice network because category " + category.getName() + " is full of channels");
                    continue;
                }
                playersWithinRange.add(uuid);
                networks.add(new Network(playersWithinRange));
            }
        }
        // handle moving players between channels
        Set<Member> members = new HashSet<>(lobbyChannel.getMembers());
        for (Network network : getNetworks()) {
            VoiceChannel voiceChannel = network.getChannel();
            if (voiceChannel == null)
                continue;
            members.addAll(voiceChannel.getMembers());
        }
        for (Member member : members) {
            UUID uuid = getUniqueId(member);
            VoiceChannel playerChannel = member.getVoiceState().getChannel();
            Network playerNetwork = uuid != null ? networks.stream().filter(n -> n.contains(uuid)).findAny().orElse(null) : null;
            VoiceChannel shouldBeInChannel;
            if (playerNetwork != null) {
                if (playerNetwork.getChannel() == null) {
                    // isn't yet created, we can wait until next tick
                    continue;
                }
                shouldBeInChannel = playerNetwork.getChannel();
            } else {
                shouldBeInChannel = lobbyChannel;
            }
            Pair<String, CompletableFuture<Void>> awaitingMove = awaitingMoves.get(member.getId());
            // they're already where they're suppose to be
            if (awaitingMove != null && awaitingMove.getLeft().equals(shouldBeInChannel.getId()))
                continue;
            // if the cancel succeeded we can move them
            if (awaitingMove != null && !awaitingMove.getLeft().equals(shouldBeInChannel.getId()) && !awaitingMove.getRight().cancel(false))
                continue;
            // schedule a move to the channel they're suppose to be in, if they aren't there yet
            if (!playerChannel.getId().equals(shouldBeInChannel.getId())) {
                awaitingMoves.put(member.getId(), Pair.of(shouldBeInChannel.getId(), getGuild().moveVoiceMember(member, shouldBeInChannel).submit().whenCompleteAsync((v, t) -> awaitingMoves.remove(member.getId()))));
            }
        }
        // delete empty networks
        for (Network network : new HashSet<>(networks)) {
            if (!network.isEmpty())
                continue;
            VoiceChannel voiceChannel = network.getChannel();
            if (voiceChannel == null)
                continue;
            if (voiceChannel.getMembers().isEmpty()) {
                voiceChannel.delete().reason("Lost communication").queue();
                networks.remove(network);
            }
        }
    } finally {
        lock.unlock();
    }
}
Also used : net.dv8tion.jda.api.entities(net.dv8tion.jda.api.entities) java.util(java.util) Getter(lombok.Getter) Permission(net.dv8tion.jda.api.Permission) VoiceChannelDeleteEvent(net.dv8tion.jda.api.events.channel.voice.VoiceChannelDeleteEvent) GuildVoiceLeaveEvent(net.dv8tion.jda.api.events.guild.voice.GuildVoiceLeaveEvent) PlayerMoveEvent(org.bukkit.event.player.PlayerMoveEvent) CompletableFuture(java.util.concurrent.CompletableFuture) DiscordUtil(github.scarsz.discordsrv.util.DiscordUtil) Player(org.bukkit.entity.Player) StringUtils(org.apache.commons.lang3.StringUtils) EventHandler(org.bukkit.event.EventHandler) Pair(net.dv8tion.jda.internal.utils.tuple.Pair) Location(org.bukkit.Location) DiscordSRV(github.scarsz.discordsrv.DiscordSRV) Bukkit(org.bukkit.Bukkit) Listener(org.bukkit.event.Listener) PlayerJoinEvent(org.bukkit.event.player.PlayerJoinEvent) GuildVoiceMoveEvent(net.dv8tion.jda.api.events.guild.voice.GuildVoiceMoveEvent) ReentrantLock(java.util.concurrent.locks.ReentrantLock) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) ListenerAdapter(net.dv8tion.jda.api.hooks.ListenerAdapter) Collectors(java.util.stream.Collectors) OfflinePlayer(org.bukkit.OfflinePlayer) Debug(github.scarsz.discordsrv.Debug) TimeUnit(java.util.concurrent.TimeUnit) GuildVoiceJoinEvent(net.dv8tion.jda.api.events.guild.voice.GuildVoiceJoinEvent) PlayerUtil(github.scarsz.discordsrv.util.PlayerUtil) EventPriority(org.bukkit.event.EventPriority) PlayerTeleportEvent(org.bukkit.event.player.PlayerTeleportEvent) PlayerQuitEvent(org.bukkit.event.player.PlayerQuitEvent) NumberConversions(org.bukkit.util.NumberConversions) NotNull(org.jetbrains.annotations.NotNull) Player(org.bukkit.entity.Player) OfflinePlayer(org.bukkit.OfflinePlayer) CompletableFuture(java.util.concurrent.CompletableFuture) Permission(net.dv8tion.jda.api.Permission)

Example 4 with Pair

use of net.dv8tion.jda.internal.utils.tuple.Pair in project Sx4 by sx4-discord-bot.

the class DiscordCommand method onCommand.

public void onCommand(Sx4CommandEvent event, @Argument(value = "user", nullDefault = true) Member member, @Argument(value = "text | message id", endless = true) @Limit(max = 250) Or<MessageArgument, String> option, @Option(value = "light", description = "Sets the discord theme to light") boolean light) {
    if (member == null && option.hasSecond()) {
        event.replyFailure("You need to provide a user when not giving a message").queue();
        return;
    }
    this.getContext(option, member).thenAccept(pair -> {
        Member effectiveMember = pair.getLeft();
        User user = effectiveMember.getUser();
        String text = pair.getRight();
        Request request = new ImageRequest(event.getConfig().getImageWebserverUrl("discord")).addField("name", effectiveMember.getEffectiveName()).addField("avatar", user.getEffectiveAvatarUrl()).addField("bot", user.isBot()).addField("dark_theme", !light).addField("colour", effectiveMember.getColorRaw()).addField("text", text).addAllFields(this.getMentions(event.getShardManager(), event.getGuild(), text)).build(event.getConfig().getImageWebserver());
        event.getHttpClient().newCall(request).enqueue((HttpCallback) response -> ImageUtility.getImageMessage(event, response).queue());
    });
}
Also used : Document(org.bson.Document) net.dv8tion.jda.api.entities(net.dv8tion.jda.api.entities) Request(okhttp3.Request) ShardManager(net.dv8tion.jda.api.sharding.ShardManager) ImageRequest(com.sx4.bot.entities.image.ImageRequest) HttpCallback(com.sx4.bot.http.HttpCallback) ImageUtility(com.sx4.bot.utility.ImageUtility) Sx4Command(com.sx4.bot.core.Sx4Command) MessageArgument(com.sx4.bot.entities.argument.MessageArgument) Permission(net.dv8tion.jda.api.Permission) SearchUtility(com.sx4.bot.utility.SearchUtility) Set(java.util.Set) CompletableFuture(java.util.concurrent.CompletableFuture) HashSet(java.util.HashSet) ModuleCategory(com.sx4.bot.category.ModuleCategory) Pair(net.dv8tion.jda.internal.utils.tuple.Pair) Matcher(java.util.regex.Matcher) Sx4CommandEvent(com.sx4.bot.core.Sx4CommandEvent) Option(com.jockie.bot.core.option.Option) Or(com.sx4.bot.entities.argument.Or) Argument(com.jockie.bot.core.argument.Argument) Limit(com.sx4.bot.annotations.argument.Limit) ImageRequest(com.sx4.bot.entities.image.ImageRequest) Request(okhttp3.Request) ImageRequest(com.sx4.bot.entities.image.ImageRequest)

Example 5 with Pair

use of net.dv8tion.jda.internal.utils.tuple.Pair in project skoice by carlodrift.

the class Main method tick.

private void tick() {
    if (!lock.tryLock()) {
        // debug(Debug.VOICE, "Skipping voice module tick, a tick is already in progress");
        return;
    }
    try {
        Category category = getCategory();
        if (category == null) {
            // debug(Debug.VOICE, "Skipping voice module tick, category is null");
            return;
        }
        VoiceChannel lobbyChannel = getLobbyChannel();
        if (lobbyChannel == null) {
            // debug(Debug.VOICE, "Skipping voice module tick, lobby channel is null");
            return;
        }
        // check that the permissions are correct
        Member selfMember = lobbyChannel.getGuild().getSelfMember();
        Role publicRole = lobbyChannel.getGuild().getPublicRole();
        long currentTime = System.currentTimeMillis();
        boolean stop = false;
        for (Permission permission : LOBBY_REQUIRED_PERMISSIONS) {
            if (!selfMember.hasPermission(lobbyChannel, permission)) {
                // if (log) .error("The bot doesn't have the \"" + permission.getName() + "\" permission in the voice lobby (" + lobbyChannel.getName() + ")");
                stop = true;
            }
        }
        for (Permission permission : CATEGORY_REQUIRED_PERMISSIONS) {
            if (!selfMember.hasPermission(category, permission)) {
                // if (log) .error("The bot doesn't have the \"" + permission.getName() + "\" permission in the voice category (" + category.getName() + ")");
                stop = true;
            }
        }
        // we can't function & would throw exceptions
        if (stop) {
            return;
        }
        PermissionOverride lobbyPublicRoleOverride = lobbyChannel.getPermissionOverride(publicRole);
        if (lobbyPublicRoleOverride == null) {
            lobbyChannel.createPermissionOverride(publicRole).deny(Permission.VOICE_SPEAK).queue();
        } else if (!lobbyPublicRoleOverride.getDenied().contains(Permission.VOICE_SPEAK)) {
            lobbyPublicRoleOverride.getManager().deny(Permission.VOICE_SPEAK).queue();
        }
        // remove networks that have no voice channel
        networks.removeIf(network -> network.getChannel() == null && network.isInitialized());
        Set<Player> alivePlayers = getOnlinePlayers().stream().filter(player -> !player.isDead()).collect(Collectors.toSet());
        Set<UUID> oldDirtyPlayers = dirtyPlayers;
        dirtyPlayers = new HashSet<>();
        for (UUID uuid : oldDirtyPlayers) {
            Player player = Bukkit.getPlayer(uuid);
            if (player == null)
                continue;
            Member member = getMember(player.getUniqueId());
            if (member == null) {
                // debug(Debug.VOICE, "Player " + player.getName() + " isn't linked, skipping voice checks");
                continue;
            }
            if (member.getVoiceState() == null || member.getVoiceState().getChannel() == null) {
                // .debug(Debug.VOICE, "Player " + player.getName() + " is not connected to voice");
                continue;
            }
            VoiceChannel playerChannel = member.getVoiceState().getChannel();
            boolean isLobby = playerChannel.getId().equals(getLobbyChannel().getId());
            if (!isLobby && (playerChannel.getParent() == null || !playerChannel.getParent().getId().equals(getCategory().getId()))) {
                // .debug(Debug.VOICE, "Player " + player.getName() + " was not in the voice lobby or category");
                // member.mute(false).queue();
                // cancel existing moves if they changed to a different channel
                Pair<String, CompletableFuture<Void>> pair = awaitingMoves.get(member.getId());
                if (pair != null)
                    pair.getRight().cancel(false);
                continue;
            }
            // add player to networks that they may have came into contact with
            // and combine multiple networks if the player is connecting them together
            networks.stream().filter(network -> network.isPlayerInRangeToBeAdded(player)).reduce((network1, network2) -> network1.size() > network2.size() ? network1.engulf(network2) : network2.engulf(network1)).filter(network -> !network.contains(player.getUniqueId())).ifPresent(network -> {
                // debug(Debug.VOICE, player.getName() + " has entered network " + network + "'s influence, connecting");
                network.add(player.getUniqueId());
            });
            // remove player from networks that they lost connection to
            networks.stream().filter(network -> network.contains(player.getUniqueId())).filter(network -> !network.isPlayerInRangeToStayConnected(player)).forEach(network -> {
                // .debug(Debug.VOICE, "Player " + player.getName() + " lost connection to " + network + ", disconnecting");
                network.remove(player.getUniqueId());
                if (network.size() == 1)
                    network.clear();
            });
            // create networks if two players are within activation distance
            Set<UUID> playersWithinRange = alivePlayers.stream().filter(p -> networks.stream().noneMatch(network -> network.contains(p))).filter(p -> !p.equals(player)).filter(p -> p.getWorld().getName().equals(player.getWorld().getName())).filter(p -> horizontalDistance(p.getLocation(), player.getLocation()) <= getHorizontalStrength() && verticalDistance(p.getLocation(), player.getLocation()) <= getVerticalStrength()).filter(p -> {
                Member m = getMember(p.getUniqueId());
                return m != null && m.getVoiceState() != null && m.getVoiceState().getChannel() != null && m.getVoiceState().getChannel().getParent() != null && m.getVoiceState().getChannel().getParent().equals(category);
            }).map(Player::getUniqueId).collect(Collectors.toCollection(ConcurrentHashMap::newKeySet));
            if (!playersWithinRange.isEmpty()) {
                if (category.getChannels().size() == 50) {
                    // .debug(Debug.VOICE, "Can't create new voice network because category " + category.getName() + " is full of channels");
                    continue;
                }
                playersWithinRange.add(uuid);
                networks.add(new Network(playersWithinRange));
            }
        }
        // handle moving players between channels
        Set<Member> members = new HashSet<>(lobbyChannel.getMembers());
        for (Network network : getNetworks()) {
            VoiceChannel voiceChannel = network.getChannel();
            if (voiceChannel == null)
                continue;
            members.addAll(voiceChannel.getMembers());
        }
        for (Member member : members) {
            UUID uuid = getUniqueId(member);
            VoiceChannel playerChannel = member.getVoiceState().getChannel();
            Network playerNetwork = uuid != null ? networks.stream().filter(n -> n.contains(uuid)).findAny().orElse(null) : null;
            VoiceChannel shouldBeInChannel;
            if (playerNetwork != null) {
                if (playerNetwork.getChannel() == null) {
                    // isn't yet created, we can wait until next tick
                    continue;
                }
                shouldBeInChannel = playerNetwork.getChannel();
            } else {
                shouldBeInChannel = lobbyChannel;
            }
            Pair<String, CompletableFuture<Void>> awaitingMove = awaitingMoves.get(member.getId());
            // they're already where they're suppose to be
            if (awaitingMove != null && awaitingMove.getLeft().equals(shouldBeInChannel.getId()))
                continue;
            // if the cancel succeeded we can move them
            if (awaitingMove != null && !awaitingMove.getLeft().equals(shouldBeInChannel.getId()) && !awaitingMove.getRight().cancel(false))
                continue;
            // schedule a move to the channel they're suppose to be in, if they aren't there yet
            if (!playerChannel.getId().equals(shouldBeInChannel.getId())) {
                awaitingMoves.put(member.getId(), Pair.of(shouldBeInChannel.getId(), getGuild().moveVoiceMember(member, shouldBeInChannel).submit().whenCompleteAsync((v, t) -> awaitingMoves.remove(member.getId()))));
            }
        }
        // delete empty networks
        for (Network network : new HashSet<>(networks)) {
            if (!network.isEmpty())
                continue;
            VoiceChannel voiceChannel = network.getChannel();
            if (voiceChannel == null)
                continue;
            if (voiceChannel.getMembers().isEmpty()) {
                voiceChannel.delete().reason("Lost communication").queue();
                networks.remove(network);
            }
        }
    } finally {
        lock.unlock();
    }
}
Also used : LoginException(javax.security.auth.login.LoginException) net.dv8tion.jda.api.entities(net.dv8tion.jda.api.entities) java.util(java.util) JDA(net.dv8tion.jda.api.JDA) Permission(net.dv8tion.jda.api.Permission) VoiceChannelDeleteEvent(net.dv8tion.jda.api.events.channel.voice.VoiceChannelDeleteEvent) GuildVoiceLeaveEvent(net.dv8tion.jda.api.events.guild.voice.GuildVoiceLeaveEvent) PlayerMoveEvent(org.bukkit.event.player.PlayerMoveEvent) CompletableFuture(java.util.concurrent.CompletableFuture) Player(org.bukkit.entity.Player) StringUtils(org.apache.commons.lang3.StringUtils) GatewayIntent(net.dv8tion.jda.api.requests.GatewayIntent) EventHandler(org.bukkit.event.EventHandler) Skoice(net.clementraynaud.Skoice) Pair(net.dv8tion.jda.internal.utils.tuple.Pair) Location(org.bukkit.Location) JDABuilder(net.dv8tion.jda.api.JDABuilder) Server(org.bukkit.Server) CacheFlag(net.dv8tion.jda.api.utils.cache.CacheFlag) Method(java.lang.reflect.Method) Bukkit(org.bukkit.Bukkit) Listener(org.bukkit.event.Listener) MemberCachePolicy(net.dv8tion.jda.api.utils.MemberCachePolicy) GuildMessageReceivedEvent(net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent) PlayerJoinEvent(org.bukkit.event.player.PlayerJoinEvent) CommandSender(org.bukkit.command.CommandSender) GuildVoiceMoveEvent(net.dv8tion.jda.api.events.guild.voice.GuildVoiceMoveEvent) ReentrantLock(java.util.concurrent.locks.ReentrantLock) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) ListenerAdapter(net.dv8tion.jda.api.hooks.ListenerAdapter) IOException(java.io.IOException) CommandExecutor(org.bukkit.command.CommandExecutor) Collectors(java.util.stream.Collectors) OfflinePlayer(org.bukkit.OfflinePlayer) GuildVoiceJoinEvent(net.dv8tion.jda.api.events.guild.voice.GuildVoiceJoinEvent) EventPriority(org.bukkit.event.EventPriority) PlayerTeleportEvent(org.bukkit.event.player.PlayerTeleportEvent) PlayerQuitEvent(org.bukkit.event.player.PlayerQuitEvent) Command(org.bukkit.command.Command) NumberConversions(org.bukkit.util.NumberConversions) ChunkingFilter(net.dv8tion.jda.api.utils.ChunkingFilter) NotNull(org.jetbrains.annotations.NotNull) Player(org.bukkit.entity.Player) OfflinePlayer(org.bukkit.OfflinePlayer) CompletableFuture(java.util.concurrent.CompletableFuture) Permission(net.dv8tion.jda.api.Permission)

Aggregations

Pair (net.dv8tion.jda.internal.utils.tuple.Pair)6 CompletableFuture (java.util.concurrent.CompletableFuture)4 Collectors (java.util.stream.Collectors)4 Permission (net.dv8tion.jda.api.Permission)4 net.dv8tion.jda.api.entities (net.dv8tion.jda.api.entities)4 java.util (java.util)3 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)3 TimeUnit (java.util.concurrent.TimeUnit)3 ReentrantLock (java.util.concurrent.locks.ReentrantLock)3 VoiceChannelDeleteEvent (net.dv8tion.jda.api.events.channel.voice.VoiceChannelDeleteEvent)3 GuildVoiceJoinEvent (net.dv8tion.jda.api.events.guild.voice.GuildVoiceJoinEvent)3 GuildVoiceLeaveEvent (net.dv8tion.jda.api.events.guild.voice.GuildVoiceLeaveEvent)3 GuildVoiceMoveEvent (net.dv8tion.jda.api.events.guild.voice.GuildVoiceMoveEvent)3 ListenerAdapter (net.dv8tion.jda.api.hooks.ListenerAdapter)3 StringUtils (org.apache.commons.lang3.StringUtils)3 Bukkit (org.bukkit.Bukkit)3 Location (org.bukkit.Location)3 OfflinePlayer (org.bukkit.OfflinePlayer)3 Player (org.bukkit.entity.Player)3 EventHandler (org.bukkit.event.EventHandler)3