mirror of
https://github.com/DiscordSRV/Ascension.git
synced 2024-12-26 17:18:29 +01:00
Add running commands and sending command output for execute command
This commit is contained in:
parent
1207990461
commit
512741bd92
@ -19,7 +19,6 @@
|
||||
package com.discordsrv.bukkit.component;
|
||||
|
||||
import com.discordsrv.api.component.MinecraftComponent;
|
||||
import com.discordsrv.common.DiscordSRV;
|
||||
import com.discordsrv.common.component.ComponentFactory;
|
||||
import com.discordsrv.common.component.util.ComponentUtil;
|
||||
import net.kyori.adventure.platform.bukkit.BukkitComponentSerializer;
|
||||
@ -60,21 +59,14 @@ public class PaperComponentHandle<T> {
|
||||
this.handle = handle;
|
||||
}
|
||||
|
||||
public MinecraftComponent getComponent(DiscordSRV discordSRV, T target) {
|
||||
public MinecraftComponent getComponent(T target) {
|
||||
if (handle != null) {
|
||||
Object unrelocated = null;
|
||||
try {
|
||||
unrelocated = handle.invoke(target);
|
||||
} catch (Throwable ignored) {}
|
||||
if (unrelocated != null) {
|
||||
MinecraftComponent component = discordSRV.componentFactory().empty();
|
||||
MinecraftComponent.Adapter<Object> adapter = component.unrelocatedAdapter();
|
||||
if (adapter == null) {
|
||||
throw new IllegalStateException("Unrelocated adventure unavailable");
|
||||
}
|
||||
|
||||
adapter.setComponent(unrelocated);
|
||||
return component;
|
||||
return ComponentUtil.fromUnrelocated(unrelocated);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,8 +31,8 @@ import java.util.UUID;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@SuppressWarnings("deprecation") // Paper
|
||||
@Proxy(value = CommandSender.class, className = "BukkitCommandExecutorProxy")
|
||||
public abstract class BukkitCommandExecutorProxyTemplate implements CommandSender {
|
||||
@Proxy(value = CommandSender.class, className = "BukkitCommandFeedbackExecutorProxy")
|
||||
public abstract class BukkitCommandFeedbackExecutorProxyTemplate implements CommandSender {
|
||||
|
||||
@Original
|
||||
private final CommandSender commandSender;
|
||||
@ -40,7 +40,7 @@ public abstract class BukkitCommandExecutorProxyTemplate implements CommandSende
|
||||
|
||||
private Spigot spigot;
|
||||
|
||||
public BukkitCommandExecutorProxyTemplate(CommandSender commandSender, Consumer<Component> componentConsumer) {
|
||||
public BukkitCommandFeedbackExecutorProxyTemplate(CommandSender commandSender, Consumer<Component> componentConsumer) {
|
||||
this.commandSender = commandSender;
|
||||
this.componentConsumer = componentConsumer;
|
||||
try {
|
@ -0,0 +1,31 @@
|
||||
package com.discordsrv.bukkit.console.executor;
|
||||
|
||||
import com.discordsrv.api.component.MinecraftComponent;
|
||||
import com.discordsrv.common.component.util.ComponentUtil;
|
||||
import com.discordsrv.unrelocate.net.kyori.adventure.text.Component;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class PaperCommandFeedbackExecutor implements Consumer<Component> {
|
||||
|
||||
private final Consumer<MinecraftComponent> componentConsumer;
|
||||
private final CommandSender sender;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public PaperCommandFeedbackExecutor(Server server, Consumer<MinecraftComponent> componentConsumer) {
|
||||
this.componentConsumer = componentConsumer;
|
||||
this.sender = server.createCommandSender((Consumer<? super net.kyori.adventure.text.Component>) (Object) this);
|
||||
}
|
||||
|
||||
public CommandSender sender() {
|
||||
return sender;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(Component component) {
|
||||
MinecraftComponent minecraftComponent = ComponentUtil.fromUnrelocated(component);
|
||||
componentConsumer.accept(minecraftComponent);
|
||||
}
|
||||
}
|
@ -45,11 +45,8 @@ public class PaperModernAdvancementListener extends AbstractBukkitAwardListener
|
||||
);
|
||||
}
|
||||
|
||||
private final DiscordSRV discordSRV;
|
||||
|
||||
public PaperModernAdvancementListener(DiscordSRV discordSRV, IBukkitAwardForwarder forwarder) {
|
||||
super(discordSRV, forwarder);
|
||||
this.discordSRV = discordSRV;
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
@ -62,8 +59,8 @@ public class PaperModernAdvancementListener extends AbstractBukkitAwardListener
|
||||
return;
|
||||
}
|
||||
|
||||
MinecraftComponent message = MESSAGE_HANDLE.getComponent(discordSRV, event);
|
||||
MinecraftComponent displayName = DISPLAY_NAME_HANDLE.getComponent(discordSRV, advancement);
|
||||
MinecraftComponent message = MESSAGE_HANDLE.getComponent(event);
|
||||
MinecraftComponent displayName = DISPLAY_NAME_HANDLE.getComponent(advancement);
|
||||
forwarder.publishEvent(event, event.getPlayer(), displayName, message, false);
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,6 @@ package com.discordsrv.bukkit.listener.chat;
|
||||
|
||||
import com.discordsrv.api.component.MinecraftComponent;
|
||||
import com.discordsrv.bukkit.component.PaperComponentHandle;
|
||||
import com.discordsrv.common.DiscordSRV;
|
||||
import io.papermc.paper.event.player.AsyncChatEvent;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
@ -38,17 +37,15 @@ public class PaperChatListener implements Listener {
|
||||
);
|
||||
}
|
||||
|
||||
private final DiscordSRV discordSRV;
|
||||
private final IBukkitChatForwarder listener;
|
||||
|
||||
public PaperChatListener(DiscordSRV discordSRV, IBukkitChatForwarder listener) {
|
||||
this.discordSRV = discordSRV;
|
||||
public PaperChatListener(IBukkitChatForwarder listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onAsyncChat(AsyncChatEvent event) {
|
||||
MinecraftComponent component = COMPONENT_HANDLE.getComponent(discordSRV, event);
|
||||
MinecraftComponent component = COMPONENT_HANDLE.getComponent(event);
|
||||
listener.publishEvent(event, event.getPlayer(), component, event.isCancelled());
|
||||
}
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ public class BukkitGameCommandExecutionHelper implements GameCommandExecutionHel
|
||||
if (PaperCommandMap.IS_AVAILABLE) {
|
||||
// If Paper's CommandMap is available we can list out 'root' commands
|
||||
CompletableFuture<List<String>> future = new CompletableFuture<>();
|
||||
discordSRV.scheduler().runOnMainThread(() -> {
|
||||
discordSRV.scheduler().runOnMainThread(discordSRV.server().getConsoleSender(), () -> {
|
||||
try {
|
||||
for (String cmd : PaperCommandMap.getKnownCommands(discordSRV.server())) {
|
||||
if (commandName == null || cmd.startsWith(commandName)) {
|
||||
@ -63,9 +63,10 @@ public class BukkitGameCommandExecutionHelper implements GameCommandExecutionHel
|
||||
|
||||
CompletableFuture<List<String>> future = new CompletableFuture<>();
|
||||
String finalPrefix = prefix;
|
||||
discordSRV.scheduler().runOnMainThread(() -> {
|
||||
|
||||
CommandSender commandSender = discordSRV.server().getConsoleSender();
|
||||
discordSRV.scheduler().runOnMainThread(commandSender, () -> {
|
||||
try {
|
||||
CommandSender commandSender = discordSRV.server().getConsoleSender();
|
||||
List<String> completions = command.tabComplete(commandSender, commandName, parts.toArray(new String[0]));
|
||||
|
||||
List<String> suggestions = new ArrayList<>();
|
||||
|
@ -21,7 +21,9 @@ package com.discordsrv.bukkit.console.executor;
|
||||
import com.discordsrv.bukkit.BukkitDiscordSRV;
|
||||
import com.discordsrv.common.command.game.executor.CommandExecutor;
|
||||
import com.discordsrv.common.command.game.executor.CommandExecutorProvider;
|
||||
import com.discordsrv.common.component.util.ComponentUtil;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
@ -33,7 +35,9 @@ public class BukkitCommandExecutorProvider implements CommandExecutorProvider {
|
||||
static {
|
||||
boolean has = false;
|
||||
try {
|
||||
has = PaperCommandExecutor.CREATE_COMMAND_SENDER != null;
|
||||
//noinspection JavaReflectionMemberAccess
|
||||
Server.class.getDeclaredMethod("createCommandSender", Consumer.class);
|
||||
has = true;
|
||||
} catch (Throwable ignored) {}
|
||||
HAS_PAPER_FORWARDING = has;
|
||||
}
|
||||
@ -48,11 +52,15 @@ public class BukkitCommandExecutorProvider implements CommandExecutorProvider {
|
||||
public CommandExecutor getConsoleExecutor(Consumer<Component> componentConsumer) {
|
||||
if (HAS_PAPER_FORWARDING) {
|
||||
try {
|
||||
return new PaperCommandExecutor(discordSRV, componentConsumer);
|
||||
CommandSender sender = new PaperCommandFeedbackExecutor(
|
||||
discordSRV.server(),
|
||||
apiComponent -> componentConsumer.accept(ComponentUtil.fromAPI(apiComponent))
|
||||
).sender();
|
||||
return new CommandSenderExecutor(discordSRV, sender);
|
||||
} catch (Throwable ignored) {}
|
||||
}
|
||||
|
||||
CommandSender commandSender = new BukkitCommandExecutorProxy(discordSRV.server().getConsoleSender(), componentConsumer).getProxy();
|
||||
CommandSender commandSender = new BukkitCommandFeedbackExecutorProxy(discordSRV.server().getConsoleSender(), componentConsumer).getProxy();
|
||||
return new CommandSenderExecutor(discordSRV, commandSender);
|
||||
}
|
||||
}
|
||||
|
@ -1,49 +0,0 @@
|
||||
/*
|
||||
* This file is part of DiscordSRV, licensed under the GPLv3 License
|
||||
* Copyright (c) 2016-2023 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.bukkit.console.executor;
|
||||
|
||||
import com.discordsrv.bukkit.BukkitDiscordSRV;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@SuppressWarnings("JavaLangInvokeHandleSignature") // PaperAPI that is not included at compile accessed via reflection
|
||||
public class PaperCommandExecutor extends CommandSenderExecutor {
|
||||
|
||||
public static final MethodHandle CREATE_COMMAND_SENDER;
|
||||
|
||||
static {
|
||||
MethodHandles.Lookup lookup = MethodHandles.lookup();
|
||||
MethodHandle handle = null;
|
||||
try {
|
||||
MethodType methodType = MethodType.methodType(CommandSender.class, Consumer.class);
|
||||
handle = lookup.findVirtual(Server.class, "createCommandSender", methodType);
|
||||
} catch (Throwable ignored) {}
|
||||
CREATE_COMMAND_SENDER = handle;
|
||||
}
|
||||
|
||||
public PaperCommandExecutor(BukkitDiscordSRV discordSRV, Consumer<Component> componentConsumer) throws Throwable {
|
||||
super(discordSRV, (CommandSender) CREATE_COMMAND_SENDER.invoke(componentConsumer));
|
||||
}
|
||||
}
|
@ -65,7 +65,7 @@ public class BukkitDeathListener implements Listener {
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onPlayerDeath(PlayerDeathEvent event) {
|
||||
DiscordSRVPlayer player = discordSRV.playerProvider().player(event.getEntity());
|
||||
MinecraftComponent component = COMPONENT_HANDLE.getComponent(discordSRV, event);
|
||||
MinecraftComponent component = COMPONENT_HANDLE.getComponent(event);
|
||||
|
||||
boolean cancelled = false;
|
||||
if (CANCELLED_HANDLE != null) {
|
||||
|
@ -57,7 +57,7 @@ public class BukkitStatusMessageListener implements Listener {
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||
DiscordSRVPlayer player = discordSRV.playerProvider().player(event.getPlayer());
|
||||
MinecraftComponent component = JOIN_HANDLE.getComponent(discordSRV, event);
|
||||
MinecraftComponent component = JOIN_HANDLE.getComponent(event);
|
||||
boolean firstJoin = !event.getPlayer().hasPlayedBefore();
|
||||
|
||||
discordSRV.scheduler().run(() -> discordSRV.eventBus().publish(
|
||||
@ -68,7 +68,7 @@ public class BukkitStatusMessageListener implements Listener {
|
||||
@EventHandler(priority = EventPriority.HIGH)
|
||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||
DiscordSRVPlayer player = discordSRV.playerProvider().player(event.getPlayer());
|
||||
MinecraftComponent component = QUIT_HANDLE.getComponent(discordSRV, event);
|
||||
MinecraftComponent component = QUIT_HANDLE.getComponent(event);
|
||||
|
||||
discordSRV.scheduler().run(() -> discordSRV.eventBus().publish(
|
||||
new LeaveMessageReceiveEvent(event, player, component, null, false)
|
||||
|
@ -34,7 +34,7 @@ public class BukkitChatForwarder implements IBukkitChatForwarder {
|
||||
// TODO: config option
|
||||
//noinspection ConstantConditions,PointlessBooleanExpression
|
||||
if (1 == 2 && PaperComponentHandle.IS_PAPER_ADVENTURE) {
|
||||
return new PaperChatListener(discordSRV, new BukkitChatForwarder(discordSRV));
|
||||
return new PaperChatListener(new BukkitChatForwarder(discordSRV));
|
||||
}
|
||||
|
||||
return new BukkitChatListener(new BukkitChatForwarder(discordSRV));
|
||||
|
@ -33,7 +33,6 @@ public class BukkitPlayer extends BukkitCommandSender implements IPlayer {
|
||||
|
||||
private static final PaperComponentHandle<Player> DISPLAY_NAME_HANDLE = makeDisplayNameHandle();
|
||||
|
||||
@SuppressWarnings("deprecation") // Paper
|
||||
private static PaperComponentHandle<Player> makeDisplayNameHandle() {
|
||||
return new PaperComponentHandle<>(
|
||||
Player.class,
|
||||
@ -63,7 +62,7 @@ public class BukkitPlayer extends BukkitCommandSender implements IPlayer {
|
||||
|
||||
@Override
|
||||
public @NotNull Component displayName() {
|
||||
return ComponentUtil.fromAPI(DISPLAY_NAME_HANDLE.getComponent(discordSRV, player));
|
||||
return ComponentUtil.fromAPI(DISPLAY_NAME_HANDLE.getComponent(player));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -13,15 +13,13 @@ import com.discordsrv.common.config.main.DiscordCommandConfig;
|
||||
import com.discordsrv.common.config.main.generic.GameCommandFilterConfig;
|
||||
import com.discordsrv.common.logging.Logger;
|
||||
import com.discordsrv.common.logging.NamedLogger;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.interactions.InteractionHook;
|
||||
import net.dv8tion.jda.api.interactions.commands.OptionMapping;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class ExecuteCommand implements Consumer<DiscordChatInputInteractionEvent>, DiscordCommand.AutoCompleteHandler {
|
||||
@ -88,7 +86,10 @@ public class ExecuteCommand implements Consumer<DiscordChatInputInteractionEvent
|
||||
return;
|
||||
}
|
||||
|
||||
discordSRV.logger().error("> " + command);
|
||||
boolean ephemeral = config.ephemeral;
|
||||
event.asJDA().reply("Executing command `" + command + "`")
|
||||
.setEphemeral(ephemeral)
|
||||
.queue(ih -> new ExecutionContext(discordSRV, ih, config.getOutputMode(), ephemeral).run(command));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -171,4 +172,84 @@ public class ExecuteCommand implements Consumer<DiscordChatInputInteractionEvent
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static class ExecutionContext {
|
||||
|
||||
private final DiscordSRV discordSRV;
|
||||
private final InteractionHook hook;
|
||||
private final DiscordCommandConfig.OutputMode outputMode;
|
||||
private final boolean ephemeral;
|
||||
private ScheduledFuture<?> future;
|
||||
private final Queue<Component> queued = new LinkedBlockingQueue<>();
|
||||
|
||||
public ExecutionContext(
|
||||
DiscordSRV discordSRV,
|
||||
InteractionHook hook,
|
||||
DiscordCommandConfig.OutputMode outputMode,
|
||||
boolean ephemeral
|
||||
) {
|
||||
this.discordSRV = discordSRV;
|
||||
this.hook = hook;
|
||||
this.outputMode = outputMode;
|
||||
this.ephemeral = ephemeral;
|
||||
}
|
||||
|
||||
public void run(String command) {
|
||||
discordSRV.console().commandExecutorProvider()
|
||||
.getConsoleExecutor(this::consumeComponent)
|
||||
.runCommand(command);
|
||||
}
|
||||
|
||||
private void consumeComponent(Component component) {
|
||||
if (outputMode == DiscordCommandConfig.OutputMode.OFF) {
|
||||
return;
|
||||
}
|
||||
synchronized (queued) {
|
||||
queued.offer(component);
|
||||
if (future == null) {
|
||||
future = discordSRV.scheduler().runLater(this::send, 500);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void send() {
|
||||
boolean ansi = outputMode == DiscordCommandConfig.OutputMode.ANSI;
|
||||
boolean plainBlock = outputMode == DiscordCommandConfig.OutputMode.PLAIN_BLOCK;
|
||||
String prefix = ansi ? "```ansi\n" : (plainBlock ? "```\n" : "");
|
||||
String suffix = ansi ? "```" : (plainBlock ? "```" : "");
|
||||
|
||||
String delimiter = "\n";
|
||||
StringJoiner joiner = new StringJoiner(delimiter);
|
||||
|
||||
Component component;
|
||||
synchronized (queued) {
|
||||
while ((component = queued.poll()) != null) {
|
||||
String discord;
|
||||
switch (outputMode) {
|
||||
default:
|
||||
case MARKDOWN:
|
||||
discord = discordSRV.componentFactory().discordSerializer().serialize(component);
|
||||
break;
|
||||
case ANSI:
|
||||
discord = discordSRV.componentFactory().ansiSerializer().serialize(component);
|
||||
break;
|
||||
case PLAIN:
|
||||
case PLAIN_BLOCK:
|
||||
discord = discordSRV.componentFactory().plainSerializer().serialize(component);
|
||||
break;
|
||||
}
|
||||
|
||||
if (prefix.length() + suffix.length() + discord.length() + joiner.length() + delimiter.length() > Message.MAX_CONTENT_LENGTH) {
|
||||
hook.sendMessage(prefix + joiner + suffix).setEphemeral(ephemeral).queue();
|
||||
joiner = new StringJoiner(delimiter);
|
||||
}
|
||||
|
||||
joiner.add(discord);
|
||||
}
|
||||
future = null;
|
||||
}
|
||||
hook.sendMessage(prefix + joiner + suffix).setEphemeral(ephemeral).queue();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -70,14 +70,14 @@ public final class ComponentUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static Component fromUnrelocated(Object unrelocatedAdventure) {
|
||||
public static MinecraftComponent fromUnrelocated(Object unrelocatedAdventure) {
|
||||
MinecraftComponentImpl component = MinecraftComponentImpl.empty();
|
||||
MinecraftComponent.Adapter<Object> adapter = component.unrelocatedAdapter();
|
||||
if (adapter == null) {
|
||||
throw new IllegalStateException("Could not get unrelocated adventure gson serializer");
|
||||
}
|
||||
adapter.setComponent(unrelocatedAdventure);
|
||||
return fromAPI(component);
|
||||
return component;
|
||||
}
|
||||
|
||||
public static Component join(Component delimiter, Collection<? extends ComponentLike> components) {
|
||||
|
@ -7,6 +7,7 @@ import org.spongepowered.configurate.objectmapping.meta.Comment;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
@ConfigSerializable
|
||||
public class DiscordCommandConfig {
|
||||
@ -28,6 +29,28 @@ public class DiscordCommandConfig {
|
||||
|
||||
public boolean enabled = true;
|
||||
|
||||
@Comment("If the command output should only be visible to the user who ran the command")
|
||||
public boolean ephemeral = true;
|
||||
|
||||
@Comment("The mode for the command output, available options are:\n"
|
||||
+ "- markdown: Regular Discord markdown\n"
|
||||
+ "- ansi: A colored ansi code block\n"
|
||||
+ "- plain: Plain text\n"
|
||||
+ "- codeblock: Plain code block\n"
|
||||
+ "- off: No command output")
|
||||
public String outputMode = "markdown";
|
||||
|
||||
public OutputMode getOutputMode() {
|
||||
switch (outputMode.toLowerCase(Locale.ROOT)) {
|
||||
default:
|
||||
case "markdown": return OutputMode.MARKDOWN;
|
||||
case "ansi": return OutputMode.ANSI;
|
||||
case "plain": return OutputMode.PLAIN;
|
||||
case "codeblock": return OutputMode.PLAIN_BLOCK;
|
||||
case "off": return OutputMode.OFF;
|
||||
}
|
||||
}
|
||||
|
||||
@Comment("At least one condition has to match to allow execution")
|
||||
public List<GameCommandFilterConfig> filters = new ArrayList<>();
|
||||
|
||||
@ -38,4 +61,12 @@ public class DiscordCommandConfig {
|
||||
@Comment("If suggestions should be filtered based on the \"filters\" option")
|
||||
public boolean filterSuggestions = true;
|
||||
}
|
||||
|
||||
public enum OutputMode {
|
||||
MARKDOWN,
|
||||
ANSI,
|
||||
PLAIN,
|
||||
PLAIN_BLOCK,
|
||||
OFF
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
dependencies {
|
||||
compileOnlyApi(libs.slf4j.api)
|
||||
compileOnlyApi(libs.adventure.api)
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package com.discordsrv.unrelocate.net.kyori.adventure.text;
|
||||
|
||||
@SuppressWarnings("NonExtendableApiUsage")
|
||||
public interface Component extends net.kyori.adventure.text.Component {
|
||||
}
|
Loading…
Reference in New Issue
Block a user