Fix commands, don't run enable/reload async anymore

This commit is contained in:
Vankka 2023-06-22 19:46:20 +03:00
parent daee555fed
commit cc5f8c2d26
No known key found for this signature in database
GPG Key ID: 6E50CB7A29B96AD0
8 changed files with 81 additions and 144 deletions

View File

@ -208,7 +208,7 @@ public class BukkitDiscordSRV extends ServerDiscordSRV<DiscordSRVBukkitBootstrap
}
@Override
protected List<ReloadResult> reload(Set<ReloadFlag> flags, boolean initial) throws Throwable {
public List<ReloadResult> reload(Set<ReloadFlag> flags, boolean initial) throws Throwable {
List<ReloadResult> results = super.reload(flags, initial);
if (flags.contains(ReloadFlag.TRANSLATIONS)) {

View File

@ -21,30 +21,21 @@ package com.discordsrv.bukkit.command.game.handler;
import com.discordsrv.bukkit.BukkitDiscordSRV;
import com.discordsrv.common.command.game.abstraction.GameCommand;
import com.discordsrv.common.command.game.handler.util.BrigadierUtil;
import com.discordsrv.common.command.game.sender.ICommandSender;
import com.mojang.brigadier.tree.LiteralCommandNode;
import me.lucko.commodore.Commodore;
import me.lucko.commodore.CommodoreProvider;
import org.bukkit.command.CommandSender;
import org.bukkit.command.PluginCommand;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.function.Function;
/**
* No avoiding basic handler on bukkit. Unfortunately it isn't possible to use brigadier for executing.
* No avoiding basic handler on Bukkit. Commodore only sends the command tree to the client, nothing else.
*/
public class CommodoreHandler extends AbstractBukkitCommandExecutor {
public class CommodoreHandler extends BukkitBasicCommandHandler {
private final Commodore commodore;
private final Function<?, ICommandSender> senderFunction;
public CommodoreHandler(BukkitDiscordSRV discordSRV) {
super(discordSRV);
this.commodore = CommodoreProvider.getCommodore(discordSRV.plugin());
this.senderFunction = wrapper -> sender((CommandSender) wrapper); // This is probably wrong...
}
@Override
@ -59,38 +50,11 @@ public class CommodoreHandler extends AbstractBukkitCommandExecutor {
handler.registerCommand(command);
pluginCommand.setExecutor(this);
pluginCommand.setTabCompleter(this);
List<LiteralCommandNode<?>> nodes = getAliases(command, pluginCommand);
discordSRV.scheduler().runOnMainThread(() -> {
for (LiteralCommandNode<?> node : nodes) {
commodore.register(node);
}
LiteralCommandNode<?> commandNode = BrigadierUtil.convertToBrigadier(command, null);
commodore.register(pluginCommand, commandNode);
});
}
private List<LiteralCommandNode<?>> getAliases(GameCommand command, PluginCommand pluginCommand) {
String commandName = pluginCommand.getName();
String pluginName = pluginCommand.getPlugin().getName().toLowerCase(Locale.ROOT);
List<String> allAliases = new ArrayList<>();
allAliases.add(commandName);
allAliases.addAll(pluginCommand.getAliases());
List<LiteralCommandNode<?>> nodes = new ArrayList<>();
for (String alias : allAliases) {
if (alias.equals(commandName)) {
LiteralCommandNode<?> node = BrigadierUtil.convertToBrigadier(command, senderFunction);
if (node.getRedirect() != null) {
throw new IllegalStateException("Cannot register a redirected node!");
}
nodes.add(node);
} else {
nodes.add(BrigadierUtil.convertToBrigadier(GameCommand.literal(alias).redirect(command), senderFunction));
}
// plugin:command
nodes.add(BrigadierUtil.convertToBrigadier(GameCommand.literal(pluginName + ":" + alias).redirect(command), senderFunction));
}
return nodes;
}
}

View File

@ -27,8 +27,8 @@ import com.discordsrv.common.api.util.ApiInstanceUtil;
import com.discordsrv.common.bootstrap.IBootstrap;
import com.discordsrv.common.channel.ChannelConfigHelper;
import com.discordsrv.common.channel.ChannelLockingModule;
import com.discordsrv.common.channel.TimedUpdaterModule;
import com.discordsrv.common.channel.GlobalChannelLookupModule;
import com.discordsrv.common.channel.TimedUpdaterModule;
import com.discordsrv.common.command.discord.DiscordCommandModule;
import com.discordsrv.common.command.game.GameCommandModule;
import com.discordsrv.common.command.game.commands.subcommand.reload.ReloadResults;
@ -48,7 +48,6 @@ import com.discordsrv.common.discord.connection.jda.JDAConnectionManager;
import com.discordsrv.common.event.bus.EventBusImpl;
import com.discordsrv.common.exception.StorageException;
import com.discordsrv.common.function.CheckedFunction;
import com.discordsrv.common.function.CheckedRunnable;
import com.discordsrv.common.groupsync.GroupSyncModule;
import com.discordsrv.common.invite.DiscordInviteModule;
import com.discordsrv.common.linking.LinkProvider;
@ -100,7 +99,6 @@ import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.ReentrantLock;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
@ -114,7 +112,6 @@ import java.util.jar.Manifest;
public abstract class AbstractDiscordSRV<B extends IBootstrap, C extends MainConfig, CC extends ConnectionConfig> implements DiscordSRV {
private final AtomicReference<Status> status = new AtomicReference<>(Status.INITIALIZED);
private CompletableFuture<Void> enableFuture;
// DiscordSRVApi
private EventBusImpl eventBus;
@ -147,9 +144,6 @@ public abstract class AbstractDiscordSRV<B extends IBootstrap, C extends MainCon
.configure(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES, false)
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// Internal
private final ReentrantLock lifecycleLock = new ReentrantLock();
public AbstractDiscordSRV(B bootstrap) {
ApiInstanceUtil.setInstance(this);
this.bootstrap = bootstrap;
@ -483,63 +477,35 @@ public abstract class AbstractDiscordSRV<B extends IBootstrap, C extends MainCon
// Lifecycle
protected CompletableFuture<Void> invokeLifecycle(CheckedRunnable<?> runnable) {
return invokeLifecycle(() -> {
try {
lifecycleLock.lock();
runnable.run();
} finally {
lifecycleLock.unlock();
}
return null;
}, "Failed to enable", true);
}
protected <T> CompletableFuture<T> invokeLifecycle(CheckedRunnable<T> runnable, String message, boolean enable) {
return CompletableFuture.supplyAsync(() -> {
if (status().isShutdown()) {
// Already shutdown/shutting down, don't bother
return null;
}
try {
return runnable.run();
} catch (Throwable t) {
if (status().isShutdown() && t instanceof NoClassDefFoundError) {
// Already shutdown, ignore errors for classes that already got unloaded
return null;
}
if (enable) {
setStatus(Status.FAILED_TO_START);
disable();
}
logger().error(message, t);
}
return null;
}, scheduler().executorService());
}
@Override
public final CompletableFuture<Void> invokeEnable() {
return enableFuture = invokeLifecycle(() -> {
public final void runEnable() {
try {
this.enable();
waitForStatus(Status.CONNECTED);
eventBus().publish(new DiscordSRVReadyEvent());
return null;
});
eventBus.publish(new DiscordSRVReadyEvent());
} catch (Throwable t) {
logger.error("Failed to enable", t);
setStatus(Status.FAILED_TO_START);
}
}
@Override
public final CompletableFuture<Void> invokeDisable() {
if (enableFuture != null && !enableFuture.isDone()) {
logger().warning("Start cancelled");
enableFuture.cancel(true);
}
return CompletableFuture.runAsync(this::disable, scheduler().executorService());
}
@Override
public final CompletableFuture<List<ReloadResult>> invokeReload(Set<ReloadFlag> flags, boolean silent) {
return invokeLifecycle(() -> reload(flags, silent), "Failed to reload", false);
public final List<ReloadResult> runReload(Set<ReloadFlag> flags, boolean silent) {
try {
return reload(flags, silent);
} catch (Throwable e) {
if (silent) {
throw new RuntimeException(e);
} else {
logger.error("Failed to reload", e);
}
return Collections.singletonList(ReloadResults.FAILED);
}
}
@OverridingMethodsMustInvokeSuper
@ -577,8 +543,8 @@ public abstract class AbstractDiscordSRV<B extends IBootstrap, C extends MainCon
// Initial load
try {
invokeReload(ReloadFlag.ALL, true).get();
} catch (ExecutionException e) {
runReload(ReloadFlag.ALL, true);
} catch (RuntimeException e) {
throw e.getCause();
}
@ -621,7 +587,7 @@ public abstract class AbstractDiscordSRV<B extends IBootstrap, C extends MainCon
}
@OverridingMethodsMustInvokeSuper
protected List<ReloadResult> reload(Set<ReloadFlag> flags, boolean initial) throws Throwable {
public List<ReloadResult> reload(Set<ReloadFlag> flags, boolean initial) throws Throwable {
if (!initial) {
logger().info("Reloading DiscordSRV...");
}

View File

@ -148,8 +148,8 @@ public interface DiscordSRV extends DiscordSRVApi {
ObjectMapper json();
// Lifecycle
CompletableFuture<Void> invokeEnable();
void runEnable();
List<ReloadResult> runReload(Set<ReloadFlag> flags, boolean silent);
CompletableFuture<Void> invokeDisable();
CompletableFuture<List<ReloadResult>> invokeReload(Set<ReloadFlag> flags, boolean silent);
}

View File

@ -51,13 +51,24 @@ public abstract class ServerDiscordSRV<B extends IBootstrap, C extends MainConfi
}
public final CompletableFuture<Void> invokeServerStarted() {
return invokeLifecycle(() -> {
return CompletableFuture.supplyAsync(() -> {
if (status().isShutdown()) {
// Already shutdown/shutting down, don't bother
return null;
}
this.serverStarted();
try {
this.serverStarted();
} catch (Throwable t) {
if (status().isShutdown() && t instanceof NoClassDefFoundError) {
// Already shutdown, ignore errors for classes that already got unloaded
return null;
}
setStatus(Status.FAILED_TO_START);
disable();
logger().error("Failed to start", t);
}
return null;
});
}, scheduler().executorService());
}
@OverridingMethodsMustInvokeSuper

View File

@ -90,14 +90,14 @@ public class LifecycleManager {
if (!completableFuture.isDone()) {
return;
}
discordSRVSupplier.get().invokeEnable();
discordSRVSupplier.get().runEnable();
}
public void reload(DiscordSRV discordSRV) {
if (discordSRV == null) {
return;
}
discordSRV.invokeReload(DiscordSRVApi.ReloadFlag.DEFAULT_FLAGS, false);
discordSRV.runReload(DiscordSRVApi.ReloadFlag.DEFAULT_FLAGS, false);
}
public void disable(DiscordSRV discordSRV) {

View File

@ -79,52 +79,47 @@ public class ReloadCommand implements GameCommandExecutor, GameCommandSuggester
return;
}
discordSRV.invokeReload(flags, false).whenComplete((results, t) -> {
if (t != null) {
discordSRV.logger().error("Failed to reload", t);
List<DiscordSRVApi.ReloadResult> results = discordSRV.runReload(flags, false);
for (DiscordSRV.ReloadResult result : results) {
String res = result.name();
if (res.equals(ReloadResults.FAILED.name())) {
sender.sendMessage(
Component.text()
.append(Component.text("Reload failed.", NamedTextColor.DARK_RED, TextDecoration.BOLD))
.append(Component.text("Please check the server console/log for more details."))
);
return;
}
for (DiscordSRV.ReloadResult result : results) {
String res = result.name();
if (res.equals(ReloadResults.SECURITY_FAILED.name())) {
sender.sendMessage(Component.text(
"DiscordSRV is disabled due to a security check failure. "
+ "Please check console for more details", NamedTextColor.DARK_RED));
} else if (res.equals(ReloadResults.SUCCESS.name())) {
sender.sendMessage(Component.text("Reload successful", NamedTextColor.GRAY));
} else if (res.equals(ReloadResults.RESTART_REQUIRED.name())) {
sender.sendMessage(Component.text("Some changes require a server restart"));
} else if (res.equals(ReloadResults.STORAGE_CONNECTION_FAILED.name())) {
sender.sendMessage(Component.text("Storage connection failed, please check console for details.", NamedTextColor.RED));
} else if (res.equals(ReloadResults.DISCORD_CONNECTION_FAILED.name())) {
sender.sendMessage(Component.text("Discord connection failed, please check console for details.", NamedTextColor.RED));
} else if (res.equals(ReloadResults.DISCORD_CONNECTION_RELOAD_REQUIRED.name())) {
String command = "discordsrv reload " + DiscordSRVApi.ReloadFlag.DISCORD_CONNECTION.name().toLowerCase(Locale.ROOT) + " -confirm";
Component child;
if (sender instanceof IPlayer) {
child = Component.text("[Click to reload Discord connection]", NamedTextColor.DARK_RED)
.clickEvent(ClickEvent.runCommand("/" + command))
.hoverEvent(HoverEvent.showText(Component.text("/" + command)));
} else {
child = Component.text("Run ", NamedTextColor.DARK_RED)
.append(Component.text(command, NamedTextColor.GRAY))
.append(Component.text(" to reload the Discord connection"));
}
sender.sendMessage(
Component.text()
.append(Component.text("Some changes require a Discord connection reload. ", NamedTextColor.GRAY))
.append(child)
);
} else if (res.equals(ReloadResults.SECURITY_FAILED.name())) {
sender.sendMessage(Component.text(
"DiscordSRV is disabled due to a security check failure. "
+ "Please check console for more details", NamedTextColor.DARK_RED));
} else if (res.equals(ReloadResults.SUCCESS.name())) {
sender.sendMessage(Component.text("Reload successful", NamedTextColor.GRAY));
} else if (res.equals(ReloadResults.RESTART_REQUIRED.name())) {
sender.sendMessage(Component.text("Some changes require a server restart"));
} else if (res.equals(ReloadResults.STORAGE_CONNECTION_FAILED.name())) {
sender.sendMessage(Component.text("Storage connection failed, please check console for details.", NamedTextColor.RED));
} else if (res.equals(ReloadResults.DISCORD_CONNECTION_FAILED.name())) {
sender.sendMessage(Component.text("Discord connection failed, please check console for details.", NamedTextColor.RED));
} else if (res.equals(ReloadResults.DISCORD_CONNECTION_RELOAD_REQUIRED.name())) {
String command = "discordsrv reload " + DiscordSRVApi.ReloadFlag.DISCORD_CONNECTION.name().toLowerCase(Locale.ROOT) + " -confirm";
Component child;
if (sender instanceof IPlayer) {
child = Component.text("[Click to reload Discord connection]", NamedTextColor.DARK_RED)
.clickEvent(ClickEvent.runCommand("/" + command))
.hoverEvent(HoverEvent.showText(Component.text("/" + command)));
} else {
child = Component.text("Run ", NamedTextColor.DARK_RED)
.append(Component.text(command, NamedTextColor.GRAY))
.append(Component.text(" to reload the Discord connection"));
}
sender.sendMessage(
Component.text()
.append(Component.text("Some changes require a Discord connection reload. ", NamedTextColor.GRAY))
.append(child)
);
}
});
}
}
private Set<DiscordSRV.ReloadFlag> getFlagsFromArguments(ICommandSender sender, GameCommandArguments arguments, AtomicBoolean dangerousFlags) {

View File

@ -3,6 +3,7 @@ package com.discordsrv.common.command.game.commands.subcommand.reload;
import com.discordsrv.api.DiscordSRVApi;
public enum ReloadResults implements DiscordSRVApi.ReloadResult {
FAILED,
SUCCESS,
SECURITY_FAILED,
STORAGE_CONNECTION_FAILED,