Resync command

This commit is contained in:
Vankka 2022-04-10 16:52:30 +03:00
parent daf4b313a6
commit 58929ce957
No known key found for this signature in database
GPG Key ID: 6E50CB7A29B96AD0
4 changed files with 134 additions and 16 deletions

View File

@ -23,10 +23,7 @@ import com.discordsrv.common.DiscordSRV;
import com.discordsrv.common.command.game.abstraction.GameCommand;
import com.discordsrv.common.command.game.abstraction.GameCommandArguments;
import com.discordsrv.common.command.game.abstraction.GameCommandExecutor;
import com.discordsrv.common.command.game.command.subcommand.DebugCommand;
import com.discordsrv.common.command.game.command.subcommand.LinkCommand;
import com.discordsrv.common.command.game.command.subcommand.ReloadCommand;
import com.discordsrv.common.command.game.command.subcommand.VersionCommand;
import com.discordsrv.common.command.game.command.subcommand.*;
import com.discordsrv.common.command.game.sender.ICommandSender;
import com.discordsrv.common.component.util.ComponentUtil;
@ -42,6 +39,7 @@ public class DiscordSRVCommand implements GameCommandExecutor {
.then(DebugCommand.get(discordSRV))
.then(LinkCommand.get(discordSRV))
.then(ReloadCommand.get(discordSRV))
.then(ResyncCommand.get(discordSRV))
.then(VersionCommand.get(discordSRV));
}
return INSTANCE;

View File

@ -0,0 +1,113 @@
/*
* This file is part of DiscordSRV, licensed under the GPLv3 License
* Copyright (c) 2016-2022 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.discordsrv.common.command.game.command.subcommand;
import com.discordsrv.common.DiscordSRV;
import com.discordsrv.common.command.game.abstraction.GameCommand;
import com.discordsrv.common.command.game.abstraction.GameCommandArguments;
import com.discordsrv.common.command.game.abstraction.GameCommandExecutor;
import com.discordsrv.common.command.game.sender.ICommandSender;
import com.discordsrv.common.future.util.CompletableFutureUtil;
import com.discordsrv.common.groupsync.GroupSyncModule;
import com.discordsrv.common.groupsync.enums.GroupSyncCause;
import com.discordsrv.common.groupsync.enums.GroupSyncResult;
import com.discordsrv.common.player.IPlayer;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.format.NamedTextColor;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
public class ResyncCommand implements GameCommandExecutor {
private static GameCommand INSTANCE;
public static GameCommand get(DiscordSRV discordSRV) {
if (INSTANCE == null) {
INSTANCE = GameCommand.literal("resync")
.requiredPermission("discordsrv.admin.resync")
.executor(new ResyncCommand(discordSRV));
}
return INSTANCE;
}
private final DiscordSRV discordSRV;
public ResyncCommand(DiscordSRV discordSRV) {
this.discordSRV = discordSRV;
}
@Override
public void execute(ICommandSender sender, GameCommandArguments arguments) {
GroupSyncModule module = discordSRV.getModule(GroupSyncModule.class);
if (module == null) {
sender.sendMessage(Component.text("GroupSync module has not initialized correctly.", NamedTextColor.RED));
return;
}
sender.sendMessage(Component.text("Synchronizing online players", NamedTextColor.GRAY));
long startTime = System.currentTimeMillis();
CompletableFutureUtil.combine(resyncOnlinePlayers(module))
.whenComplete((results, t) -> {
EnumMap<GroupSyncResult, AtomicInteger> resultCounts = new EnumMap<>(GroupSyncResult.class);
int total = 0;
for (Set<GroupSyncResult> result : results) {
for (GroupSyncResult singleResult : result) {
total++;
resultCounts.computeIfAbsent(singleResult, key -> new AtomicInteger(0)).getAndIncrement();
}
}
String resultHover;
if (total == 0) {
resultHover = "Nothing done";
} else {
resultHover = total + " result" + (total == 1 ? "" : "s") + ":\n\n" +
resultCounts.entrySet().stream()
.map(entry -> entry.getKey().toString() + ": " + entry.getValue().get())
.collect(Collectors.joining("\n"));
}
long time = System.currentTimeMillis() - startTime;
sender.sendMessage(
Component.text("Synchronization completed in ", NamedTextColor.GRAY)
.append(Component.text(time + "ms", NamedTextColor.GREEN))
.append(Component.text(" (", NamedTextColor.GRAY))
.append(Component.text(total, NamedTextColor.GREEN))
.append(Component.text(" result" + (total == 1 ? "" : "s") + ")", NamedTextColor.GRAY))
.hoverEvent(HoverEvent.showText(Component.text(resultHover)))
);
});
}
private List<CompletableFuture<Set<GroupSyncResult>>> resyncOnlinePlayers(GroupSyncModule module) {
List<CompletableFuture<Set<GroupSyncResult>>> futures = new ArrayList<>();
for (IPlayer player : discordSRV.playerProvider().allPlayers()) {
futures.add(module.resync(player.uniqueId(), GroupSyncCause.COMMAND));
}
return futures;
}
}

View File

@ -23,6 +23,7 @@ import com.discordsrv.api.discord.api.entity.guild.DiscordRole;
import com.discordsrv.api.discord.events.member.role.DiscordMemberRoleAddEvent;
import com.discordsrv.api.discord.events.member.role.DiscordMemberRoleRemoveEvent;
import com.discordsrv.api.event.bus.Subscribe;
import com.discordsrv.api.module.type.PermissionDataProvider;
import com.discordsrv.common.DiscordSRV;
import com.discordsrv.common.config.main.GroupSyncConfig;
import com.discordsrv.common.debug.DebugGenerateEvent;
@ -34,8 +35,8 @@ import com.discordsrv.common.groupsync.enums.GroupSyncResult;
import com.discordsrv.common.groupsync.enums.GroupSyncSide;
import com.discordsrv.common.logging.NamedLogger;
import com.discordsrv.common.module.type.AbstractModule;
import com.discordsrv.api.module.type.PermissionDataProvider;
import com.discordsrv.common.player.IPlayer;
import com.discordsrv.common.player.event.PlayerConnectedEvent;
import com.github.benmanes.caffeine.cache.Cache;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.Nullable;
@ -237,29 +238,29 @@ public class GroupSyncModule extends AbstractModule<DiscordSRV> {
// Resync user
public void resync(UUID player, GroupSyncCause cause) {
lookupLinkedAccount(player).whenComplete((userId, t) -> {
public CompletableFuture<Set<GroupSyncResult>> resync(UUID player, GroupSyncCause cause) {
return lookupLinkedAccount(player).thenCompose(userId -> {
if (userId == null) {
return;
return CompletableFuture.completedFuture(Collections.emptySet());
}
resync(player, userId, cause);
return CompletableFutureUtil.combine(resync(player, userId, cause));
});
}
public void resync(long userId, GroupSyncCause cause) {
lookupLinkedAccount(userId).whenComplete((player, t) -> {
public CompletableFuture<Set<GroupSyncResult>> resync(long userId, GroupSyncCause cause) {
return lookupLinkedAccount(userId).thenCompose(player -> {
if (player == null) {
return;
return CompletableFuture.completedFuture(Collections.emptySet());
}
resync(player, userId, cause);
return CompletableFutureUtil.combine(resync(player, userId, cause));
});
}
public void resync(UUID player, long userId, GroupSyncCause cause) {
public Collection<CompletableFuture<GroupSyncResult>> resync(UUID player, long userId, GroupSyncCause cause) {
if (noPermissionProvider() || (!discordSRV.playerProvider().player(player).isPresent() && !supportsOffline())) {
return;
return Collections.emptyList();
}
Map<GroupSyncConfig.PairConfig, CompletableFuture<GroupSyncResult>> futures = new LinkedHashMap<>();
@ -268,6 +269,7 @@ public class GroupSyncModule extends AbstractModule<DiscordSRV> {
}
logSummary(player, cause, futures);
return futures.values();
}
private void resyncPair(GroupSyncConfig.PairConfig pair, GroupSyncCause cause) {
@ -378,6 +380,11 @@ public class GroupSyncModule extends AbstractModule<DiscordSRV> {
// Listeners & methods to indicate something changed
@Subscribe
public void onPlayerConnected(PlayerConnectedEvent event) {
resync(event.player().uniqueId(), GroupSyncCause.GAME_JOIN);
}
@Subscribe
public void onDiscordMemberRoleAdd(DiscordMemberRoleAddEvent event) {
event.getRoles().forEach(role -> roleChanged(event.getMember().getId(), role.getId(), false));

View File

@ -48,7 +48,7 @@ public class SynchronizationSummary {
public String toString() {
int count = pairs.size();
StringBuilder message = new StringBuilder(
"Group synchronization (of " + count + " pairs) for " + player + " (" + cause + ")");
"Group synchronization (of " + count + " pair" + (count == 1 ? "" : "s") + ") for " + player + " (" + cause + ")");
for (Map.Entry<GroupSyncResult, Set<GroupSyncConfig.PairConfig>> entry : pairs.entrySet()) {
message.append(count == 1 ? ": " : "\n")