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