geforkt von Mirrors/Velocity
Deprecate anonymous command registrations
Dieser Commit ist enthalten in:
Ursprung
4f227badc2
Commit
2016d1482f
@ -45,7 +45,9 @@ public interface CommandManager {
|
|||||||
* @throws IllegalArgumentException if one of the given aliases is already registered, or
|
* @throws IllegalArgumentException if one of the given aliases is already registered, or
|
||||||
* the given command does not implement a registrable {@link Command} subinterface
|
* the given command does not implement a registrable {@link Command} subinterface
|
||||||
* @see Command for a list of registrable Command subinterfaces
|
* @see Command for a list of registrable Command subinterfaces
|
||||||
|
* @deprecated use {@link #register(CommandMeta, Command)} instead with a plugin specified
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
default void register(String alias, Command command, String... otherAliases) {
|
default void register(String alias, Command command, String... otherAliases) {
|
||||||
register(metaBuilder(alias).aliases(otherAliases).build(), command);
|
register(metaBuilder(alias).aliases(otherAliases).build(), command);
|
||||||
}
|
}
|
||||||
@ -55,7 +57,9 @@ public interface CommandManager {
|
|||||||
*
|
*
|
||||||
* @param command the command to register
|
* @param command the command to register
|
||||||
* @throws IllegalArgumentException if the node alias is already registered
|
* @throws IllegalArgumentException if the node alias is already registered
|
||||||
|
* @deprecated use {@link #register(CommandMeta, Command)} instead with a plugin specified
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
void register(BrigadierCommand command);
|
void register(BrigadierCommand command);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -22,11 +22,13 @@ import com.google.common.base.Preconditions;
|
|||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
|
import com.velocitypowered.api.command.BrigadierCommand;
|
||||||
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
|
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
|
||||||
import com.velocitypowered.api.event.proxy.ProxyReloadEvent;
|
import com.velocitypowered.api.event.proxy.ProxyReloadEvent;
|
||||||
import com.velocitypowered.api.event.proxy.ProxyShutdownEvent;
|
import com.velocitypowered.api.event.proxy.ProxyShutdownEvent;
|
||||||
import com.velocitypowered.api.network.ProtocolVersion;
|
import com.velocitypowered.api.network.ProtocolVersion;
|
||||||
import com.velocitypowered.api.plugin.PluginContainer;
|
import com.velocitypowered.api.plugin.PluginContainer;
|
||||||
|
import com.velocitypowered.api.plugin.PluginDescription;
|
||||||
import com.velocitypowered.api.plugin.PluginManager;
|
import com.velocitypowered.api.plugin.PluginManager;
|
||||||
import com.velocitypowered.api.proxy.Player;
|
import com.velocitypowered.api.proxy.Player;
|
||||||
import com.velocitypowered.api.proxy.ProxyServer;
|
import com.velocitypowered.api.proxy.ProxyServer;
|
||||||
@ -52,6 +54,9 @@ import com.velocitypowered.proxy.crypto.EncryptionUtils;
|
|||||||
import com.velocitypowered.proxy.event.VelocityEventManager;
|
import com.velocitypowered.proxy.event.VelocityEventManager;
|
||||||
import com.velocitypowered.proxy.network.ConnectionManager;
|
import com.velocitypowered.proxy.network.ConnectionManager;
|
||||||
import com.velocitypowered.proxy.plugin.VelocityPluginManager;
|
import com.velocitypowered.proxy.plugin.VelocityPluginManager;
|
||||||
|
import com.velocitypowered.proxy.plugin.loader.VelocityPluginContainer;
|
||||||
|
import com.velocitypowered.proxy.plugin.loader.VelocityPluginDescription;
|
||||||
|
import com.velocitypowered.proxy.plugin.virtual.VelocityVirtualPlugin;
|
||||||
import com.velocitypowered.proxy.protocol.ProtocolUtils;
|
import com.velocitypowered.proxy.protocol.ProtocolUtils;
|
||||||
import com.velocitypowered.proxy.protocol.util.FaviconSerializer;
|
import com.velocitypowered.proxy.protocol.util.FaviconSerializer;
|
||||||
import com.velocitypowered.proxy.protocol.util.GameProfileSerializer;
|
import com.velocitypowered.proxy.protocol.util.GameProfileSerializer;
|
||||||
@ -77,6 +82,7 @@ import java.nio.file.Path;
|
|||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
@ -111,6 +117,8 @@ import org.checkerframework.checker.nullness.qual.Nullable;
|
|||||||
*/
|
*/
|
||||||
public class VelocityServer implements ProxyServer, ForwardingAudience {
|
public class VelocityServer implements ProxyServer, ForwardingAudience {
|
||||||
|
|
||||||
|
public static final String VELOCITY_URL = "https://velocitypowered.com";
|
||||||
|
|
||||||
private static final Logger logger = LogManager.getLogger(VelocityServer.class);
|
private static final Logger logger = LogManager.getLogger(VelocityServer.class);
|
||||||
public static final Gson GENERAL_GSON = new GsonBuilder()
|
public static final Gson GENERAL_GSON = new GsonBuilder()
|
||||||
.registerTypeHierarchyAdapter(Favicon.class, FaviconSerializer.INSTANCE)
|
.registerTypeHierarchyAdapter(Favicon.class, FaviconSerializer.INSTANCE)
|
||||||
@ -163,7 +171,7 @@ public class VelocityServer implements ProxyServer, ForwardingAudience {
|
|||||||
VelocityServer(final ProxyOptions options) {
|
VelocityServer(final ProxyOptions options) {
|
||||||
pluginManager = new VelocityPluginManager(this);
|
pluginManager = new VelocityPluginManager(this);
|
||||||
eventManager = new VelocityEventManager(pluginManager);
|
eventManager = new VelocityEventManager(pluginManager);
|
||||||
commandManager = new VelocityCommandManager(eventManager);
|
commandManager = new VelocityCommandManager(eventManager, pluginManager);
|
||||||
scheduler = new VelocityScheduler(pluginManager);
|
scheduler = new VelocityScheduler(pluginManager);
|
||||||
console = new VelocityConsole(this);
|
console = new VelocityConsole(this);
|
||||||
cm = new ConnectionManager(this);
|
cm = new ConnectionManager(this);
|
||||||
@ -200,6 +208,16 @@ public class VelocityServer implements ProxyServer, ForwardingAudience {
|
|||||||
return new ProxyVersion(implName, implVendor, implVersion);
|
return new ProxyVersion(implName, implVendor, implVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private VelocityPluginContainer createVirtualPlugin() {
|
||||||
|
ProxyVersion version = getVersion();
|
||||||
|
PluginDescription description = new VelocityPluginDescription(
|
||||||
|
"velocity", version.getName(), version.getVersion(), "The Velocity proxy",
|
||||||
|
VELOCITY_URL, ImmutableList.of(version.getVendor()), Collections.emptyList(), null);
|
||||||
|
VelocityPluginContainer container = new VelocityPluginContainer(description);
|
||||||
|
container.setInstance(VelocityVirtualPlugin.INSTANCE);
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public VelocityCommandManager getCommandManager() {
|
public VelocityCommandManager getCommandManager() {
|
||||||
return commandManager;
|
return commandManager;
|
||||||
@ -214,6 +232,7 @@ public class VelocityServer implements ProxyServer, ForwardingAudience {
|
|||||||
void start() {
|
void start() {
|
||||||
logger.info("Booting up {} {}...", getVersion().getName(), getVersion().getVersion());
|
logger.info("Booting up {} {}...", getVersion().getName(), getVersion().getVersion());
|
||||||
console.setupStreams();
|
console.setupStreams();
|
||||||
|
pluginManager.registerPlugin(this.createVirtualPlugin());
|
||||||
|
|
||||||
registerTranslations();
|
registerTranslations();
|
||||||
|
|
||||||
@ -222,11 +241,35 @@ public class VelocityServer implements ProxyServer, ForwardingAudience {
|
|||||||
cm.logChannelInformation();
|
cm.logChannelInformation();
|
||||||
|
|
||||||
// Initialize commands first
|
// Initialize commands first
|
||||||
commandManager.register(VelocityCommand.create(this));
|
final BrigadierCommand velocityParentCommand = VelocityCommand.create(this);
|
||||||
commandManager.register(CallbackCommand.create());
|
commandManager.register(
|
||||||
commandManager.register(ServerCommand.create(this));
|
commandManager.metaBuilder(velocityParentCommand)
|
||||||
commandManager.register("shutdown", ShutdownCommand.command(this),
|
.plugin(VelocityVirtualPlugin.INSTANCE)
|
||||||
"end", "stop");
|
.build(),
|
||||||
|
velocityParentCommand
|
||||||
|
);
|
||||||
|
final BrigadierCommand callbackCommand = CallbackCommand.create();
|
||||||
|
commandManager.register(
|
||||||
|
commandManager.metaBuilder(callbackCommand)
|
||||||
|
.plugin(VelocityVirtualPlugin.INSTANCE)
|
||||||
|
.build(),
|
||||||
|
velocityParentCommand
|
||||||
|
);
|
||||||
|
final BrigadierCommand serverCommand = ServerCommand.create(this);
|
||||||
|
commandManager.register(
|
||||||
|
commandManager.metaBuilder(serverCommand)
|
||||||
|
.plugin(VelocityVirtualPlugin.INSTANCE)
|
||||||
|
.build(),
|
||||||
|
serverCommand
|
||||||
|
);
|
||||||
|
final BrigadierCommand shutdownCommand = ShutdownCommand.command(this);
|
||||||
|
commandManager.register(
|
||||||
|
commandManager.metaBuilder(shutdownCommand)
|
||||||
|
.plugin(VelocityVirtualPlugin.INSTANCE)
|
||||||
|
.aliases("end", "stop")
|
||||||
|
.build(),
|
||||||
|
shutdownCommand
|
||||||
|
);
|
||||||
new GlistCommand(this).register();
|
new GlistCommand(this).register();
|
||||||
new SendCommand(this).register();
|
new SendCommand(this).register();
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ package com.velocitypowered.proxy.command;
|
|||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.common.util.concurrent.MoreExecutors;
|
||||||
import com.mojang.brigadier.CommandDispatcher;
|
import com.mojang.brigadier.CommandDispatcher;
|
||||||
import com.mojang.brigadier.Message;
|
import com.mojang.brigadier.Message;
|
||||||
import com.mojang.brigadier.ParseResults;
|
import com.mojang.brigadier.ParseResults;
|
||||||
@ -37,11 +38,15 @@ import com.velocitypowered.api.command.CommandSource;
|
|||||||
import com.velocitypowered.api.command.VelocityBrigadierMessage;
|
import com.velocitypowered.api.command.VelocityBrigadierMessage;
|
||||||
import com.velocitypowered.api.event.command.CommandExecuteEvent;
|
import com.velocitypowered.api.event.command.CommandExecuteEvent;
|
||||||
import com.velocitypowered.api.event.command.PostCommandInvocationEvent;
|
import com.velocitypowered.api.event.command.PostCommandInvocationEvent;
|
||||||
|
import com.velocitypowered.api.plugin.PluginManager;
|
||||||
|
import com.velocitypowered.proxy.command.brigadier.VelocityBrigadierCommandWrapper;
|
||||||
import com.velocitypowered.proxy.command.registrar.BrigadierCommandRegistrar;
|
import com.velocitypowered.proxy.command.registrar.BrigadierCommandRegistrar;
|
||||||
import com.velocitypowered.proxy.command.registrar.CommandRegistrar;
|
import com.velocitypowered.proxy.command.registrar.CommandRegistrar;
|
||||||
import com.velocitypowered.proxy.command.registrar.RawCommandRegistrar;
|
import com.velocitypowered.proxy.command.registrar.RawCommandRegistrar;
|
||||||
import com.velocitypowered.proxy.command.registrar.SimpleCommandRegistrar;
|
import com.velocitypowered.proxy.command.registrar.SimpleCommandRegistrar;
|
||||||
import com.velocitypowered.proxy.event.VelocityEventManager;
|
import com.velocitypowered.proxy.event.VelocityEventManager;
|
||||||
|
import com.velocitypowered.proxy.plugin.virtual.VelocityVirtualPlugin;
|
||||||
|
import io.netty.util.concurrent.FastThreadLocalThread;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -49,8 +54,7 @@ import java.util.Locale;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.ForkJoinPool;
|
|
||||||
import java.util.concurrent.locks.ReadWriteLock;
|
import java.util.concurrent.locks.ReadWriteLock;
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@ -73,14 +77,16 @@ public class VelocityCommandManager implements CommandManager {
|
|||||||
private final SuggestionsProvider<CommandSource> suggestionsProvider;
|
private final SuggestionsProvider<CommandSource> suggestionsProvider;
|
||||||
private final CommandGraphInjector<CommandSource> injector;
|
private final CommandGraphInjector<CommandSource> injector;
|
||||||
private final Map<String, CommandMeta> commandMetas;
|
private final Map<String, CommandMeta> commandMetas;
|
||||||
private final ExecutorService asyncExecutor;
|
private final PluginManager pluginManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a command manager.
|
* Constructs a command manager.
|
||||||
*
|
*
|
||||||
* @param eventManager the event manager
|
* @param eventManager the event manager
|
||||||
*/
|
*/
|
||||||
public VelocityCommandManager(final VelocityEventManager eventManager) {
|
public VelocityCommandManager(final VelocityEventManager eventManager,
|
||||||
|
PluginManager pluginManager) {
|
||||||
|
this.pluginManager = pluginManager;
|
||||||
this.lock = new ReentrantReadWriteLock();
|
this.lock = new ReentrantReadWriteLock();
|
||||||
this.dispatcher = new CommandDispatcher<>();
|
this.dispatcher = new CommandDispatcher<>();
|
||||||
this.eventManager = Preconditions.checkNotNull(eventManager);
|
this.eventManager = Preconditions.checkNotNull(eventManager);
|
||||||
@ -92,7 +98,6 @@ public class VelocityCommandManager implements CommandManager {
|
|||||||
this.suggestionsProvider = new SuggestionsProvider<>(this.dispatcher, this.lock.readLock());
|
this.suggestionsProvider = new SuggestionsProvider<>(this.dispatcher, this.lock.readLock());
|
||||||
this.injector = new CommandGraphInjector<>(this.dispatcher, this.lock.readLock());
|
this.injector = new CommandGraphInjector<>(this.dispatcher, this.lock.readLock());
|
||||||
this.commandMetas = new ConcurrentHashMap<>();
|
this.commandMetas = new ConcurrentHashMap<>();
|
||||||
this.asyncExecutor = ForkJoinPool.commonPool(); // TODO: remove entirely
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAnnounceProxyCommands(boolean announceProxyCommands) {
|
public void setAnnounceProxyCommands(boolean announceProxyCommands) {
|
||||||
@ -222,16 +227,13 @@ public class VelocityCommandManager implements CommandManager {
|
|||||||
return eventManager.fire(new CommandExecuteEvent(source, cmdLine));
|
return eventManager.fire(new CommandExecuteEvent(source, cmdLine));
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean executeImmediately0(final CommandSource source, final String cmdLine) {
|
private boolean executeImmediately0(final CommandSource source, final ParseResults<CommandSource> parsed) {
|
||||||
Preconditions.checkNotNull(source, "source");
|
Preconditions.checkNotNull(source, "source");
|
||||||
Preconditions.checkNotNull(cmdLine, "cmdLine");
|
|
||||||
|
|
||||||
final String normalizedInput = VelocityCommands.normalizeInput(cmdLine, true);
|
|
||||||
CommandResult result = CommandResult.EXCEPTION;
|
CommandResult result = CommandResult.EXCEPTION;
|
||||||
try {
|
try {
|
||||||
// The parse can fail if the requirement predicates throw
|
// The parse can fail if the requirement predicates throw
|
||||||
final ParseResults<CommandSource> parse = this.parse(normalizedInput, source);
|
boolean executed = dispatcher.execute(parsed) != BrigadierCommand.FORWARD;
|
||||||
boolean executed = dispatcher.execute(parse) != BrigadierCommand.FORWARD;
|
|
||||||
result = executed ? CommandResult.EXECUTED : CommandResult.FORWARDED;
|
result = executed ? CommandResult.EXECUTED : CommandResult.FORWARDED;
|
||||||
return executed;
|
return executed;
|
||||||
} catch (final CommandSyntaxException e) {
|
} catch (final CommandSyntaxException e) {
|
||||||
@ -253,9 +255,9 @@ public class VelocityCommandManager implements CommandManager {
|
|||||||
}
|
}
|
||||||
} catch (final Throwable e) {
|
} catch (final Throwable e) {
|
||||||
// Ugly, ugly swallowing of everything Throwable, because plugins are naughty.
|
// Ugly, ugly swallowing of everything Throwable, because plugins are naughty.
|
||||||
throw new RuntimeException("Unable to invoke command " + cmdLine + " for " + source, e);
|
throw new RuntimeException("Unable to invoke command " + parsed.getReader().getString() + "for " + source, e);
|
||||||
} finally {
|
} finally {
|
||||||
eventManager.fireAndForget(new PostCommandInvocationEvent(source, cmdLine, result));
|
eventManager.fireAndForget(new PostCommandInvocationEvent(source, parsed.getReader().getString(), result));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,13 +266,17 @@ public class VelocityCommandManager implements CommandManager {
|
|||||||
Preconditions.checkNotNull(source, "source");
|
Preconditions.checkNotNull(source, "source");
|
||||||
Preconditions.checkNotNull(cmdLine, "cmdLine");
|
Preconditions.checkNotNull(cmdLine, "cmdLine");
|
||||||
|
|
||||||
return callCommandEvent(source, cmdLine).thenApplyAsync(event -> {
|
return callCommandEvent(source, cmdLine).thenComposeAsync(event -> {
|
||||||
CommandExecuteEvent.CommandResult commandResult = event.getResult();
|
CommandExecuteEvent.CommandResult commandResult = event.getResult();
|
||||||
if (commandResult.isForwardToServer() || !commandResult.isAllowed()) {
|
if (commandResult.isForwardToServer() || !commandResult.isAllowed()) {
|
||||||
return false;
|
return CompletableFuture.completedFuture(false);
|
||||||
}
|
}
|
||||||
return executeImmediately0(source, commandResult.getCommand().orElse(event.getCommand()));
|
final ParseResults<CommandSource> parsed = this.parse(
|
||||||
}, asyncExecutor);
|
commandResult.getCommand().orElse(cmdLine), source);
|
||||||
|
return CompletableFuture.supplyAsync(
|
||||||
|
() -> executeImmediately0(source, parsed), this.getAsyncExecutor(parsed)
|
||||||
|
);
|
||||||
|
}, figureAsyncExecutorForParsing());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -279,7 +285,13 @@ public class VelocityCommandManager implements CommandManager {
|
|||||||
Preconditions.checkNotNull(source, "source");
|
Preconditions.checkNotNull(source, "source");
|
||||||
Preconditions.checkNotNull(cmdLine, "cmdLine");
|
Preconditions.checkNotNull(cmdLine, "cmdLine");
|
||||||
|
|
||||||
return CompletableFuture.supplyAsync(() -> executeImmediately0(source, cmdLine), asyncExecutor);
|
return CompletableFuture.supplyAsync(
|
||||||
|
() -> this.parse(cmdLine, source), figureAsyncExecutorForParsing()
|
||||||
|
).thenCompose(
|
||||||
|
parsed -> CompletableFuture.supplyAsync(
|
||||||
|
() -> executeImmediately0(source, parsed), this.getAsyncExecutor(parsed)
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -327,9 +339,10 @@ public class VelocityCommandManager implements CommandManager {
|
|||||||
* @return the parse results
|
* @return the parse results
|
||||||
*/
|
*/
|
||||||
private ParseResults<CommandSource> parse(final String input, final CommandSource source) {
|
private ParseResults<CommandSource> parse(final String input, final CommandSource source) {
|
||||||
|
final String normalizedInput = VelocityCommands.normalizeInput(input, true);
|
||||||
lock.readLock().lock();
|
lock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
return dispatcher.parse(input, source);
|
return dispatcher.parse(normalizedInput, source);
|
||||||
} finally {
|
} finally {
|
||||||
lock.readLock().unlock();
|
lock.readLock().unlock();
|
||||||
}
|
}
|
||||||
@ -373,4 +386,25 @@ public class VelocityCommandManager implements CommandManager {
|
|||||||
public CommandGraphInjector<CommandSource> getInjector() {
|
public CommandGraphInjector<CommandSource> getInjector() {
|
||||||
return injector;
|
return injector;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Executor getAsyncExecutor(ParseResults<CommandSource> parse) {
|
||||||
|
Object registrant;
|
||||||
|
if (parse.getContext().getCommand() instanceof VelocityBrigadierCommandWrapper vbcw) {
|
||||||
|
registrant = vbcw.registrant() == null ? VelocityVirtualPlugin.INSTANCE : vbcw.registrant();
|
||||||
|
} else {
|
||||||
|
registrant = VelocityVirtualPlugin.INSTANCE;
|
||||||
|
}
|
||||||
|
return pluginManager.ensurePluginContainer(registrant).getExecutorService();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Executor figureAsyncExecutorForParsing() {
|
||||||
|
final Thread thread = Thread.currentThread();
|
||||||
|
if (thread instanceof FastThreadLocalThread) {
|
||||||
|
// we *never* want to block the Netty event loop, so use the async executor
|
||||||
|
return pluginManager.ensurePluginContainer(VelocityVirtualPlugin.INSTANCE).getExecutorService();
|
||||||
|
} else {
|
||||||
|
// it's some other thread that isn't a Netty event loop thread. direct execution it is!
|
||||||
|
return MoreExecutors.directExecutor();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -24,6 +24,7 @@ import com.mojang.brigadier.context.CommandContext;
|
|||||||
import com.mojang.brigadier.context.CommandContextBuilder;
|
import com.mojang.brigadier.context.CommandContextBuilder;
|
||||||
import com.mojang.brigadier.context.ParsedArgument;
|
import com.mojang.brigadier.context.ParsedArgument;
|
||||||
import com.mojang.brigadier.context.ParsedCommandNode;
|
import com.mojang.brigadier.context.ParsedCommandNode;
|
||||||
|
import com.mojang.brigadier.tree.ArgumentCommandNode;
|
||||||
import com.mojang.brigadier.tree.CommandNode;
|
import com.mojang.brigadier.tree.CommandNode;
|
||||||
import com.mojang.brigadier.tree.LiteralCommandNode;
|
import com.mojang.brigadier.tree.LiteralCommandNode;
|
||||||
import com.mojang.brigadier.tree.RootCommandNode;
|
import com.mojang.brigadier.tree.RootCommandNode;
|
||||||
@ -32,6 +33,7 @@ import com.velocitypowered.api.command.CommandManager;
|
|||||||
import com.velocitypowered.api.command.CommandSource;
|
import com.velocitypowered.api.command.CommandSource;
|
||||||
import com.velocitypowered.api.command.InvocableCommand;
|
import com.velocitypowered.api.command.InvocableCommand;
|
||||||
import com.velocitypowered.proxy.command.brigadier.VelocityArgumentCommandNode;
|
import com.velocitypowered.proxy.command.brigadier.VelocityArgumentCommandNode;
|
||||||
|
import com.velocitypowered.proxy.command.brigadier.VelocityBrigadierCommandWrapper;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -44,6 +46,59 @@ import org.checkerframework.checker.nullness.qual.Nullable;
|
|||||||
*/
|
*/
|
||||||
public final class VelocityCommands {
|
public final class VelocityCommands {
|
||||||
|
|
||||||
|
// Wrapping
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Walks the command node tree and wraps all {@link Command} instances in a {@link VelocityBrigadierCommandWrapper},
|
||||||
|
* to indicate the plugin that registered the command. This also has the side effect of cloning
|
||||||
|
* the command node tree.
|
||||||
|
*
|
||||||
|
* @param delegate the command node to wrap
|
||||||
|
* @param registrant the plugin that registered the command
|
||||||
|
* @return the wrapped command node
|
||||||
|
*/
|
||||||
|
public static CommandNode<CommandSource> wrap(final CommandNode<CommandSource> delegate,
|
||||||
|
final @Nullable Object registrant) {
|
||||||
|
Preconditions.checkNotNull(delegate, "delegate");
|
||||||
|
if (registrant == null) {
|
||||||
|
// the registrant is null if the `plugin` was absent when we try to register the command
|
||||||
|
return delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
com.mojang.brigadier.Command<CommandSource> maybeCommand = delegate.getCommand();
|
||||||
|
if (maybeCommand != null && !(maybeCommand instanceof VelocityBrigadierCommandWrapper)) {
|
||||||
|
maybeCommand = VelocityBrigadierCommandWrapper.wrap(delegate.getCommand(), registrant);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (delegate instanceof LiteralCommandNode<CommandSource> lcn) {
|
||||||
|
var literalBuilder = shallowCopyAsBuilder(lcn, delegate.getName(), true);
|
||||||
|
literalBuilder.executes(maybeCommand);
|
||||||
|
// we also need to wrap any children
|
||||||
|
for (final CommandNode<CommandSource> child : delegate.getChildren()) {
|
||||||
|
literalBuilder.then(wrap(child, registrant));
|
||||||
|
}
|
||||||
|
if (delegate.getRedirect() != null) {
|
||||||
|
literalBuilder.redirect(wrap(delegate.getRedirect(), registrant));
|
||||||
|
}
|
||||||
|
return literalBuilder.build();
|
||||||
|
} else if (delegate instanceof VelocityArgumentCommandNode<CommandSource, ?> vacn) {
|
||||||
|
return vacn.withCommand(maybeCommand)
|
||||||
|
.withRedirect(delegate.getRedirect() != null ? wrap(delegate.getRedirect(), registrant) : null);
|
||||||
|
} else if (delegate instanceof ArgumentCommandNode) {
|
||||||
|
var argBuilder = delegate.createBuilder().executes(maybeCommand);
|
||||||
|
// we also need to wrap any children
|
||||||
|
for (final CommandNode<CommandSource> child : delegate.getChildren()) {
|
||||||
|
argBuilder.then(wrap(child, registrant));
|
||||||
|
}
|
||||||
|
if (delegate.getRedirect() != null) {
|
||||||
|
argBuilder.redirect(wrap(delegate.getRedirect(), registrant));
|
||||||
|
}
|
||||||
|
return argBuilder.build();
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("Unsupported node type: " + delegate.getClass());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Normalization
|
// Normalization
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -135,6 +190,33 @@ public final class VelocityCommands {
|
|||||||
*/
|
*/
|
||||||
public static LiteralCommandNode<CommandSource> shallowCopy(
|
public static LiteralCommandNode<CommandSource> shallowCopy(
|
||||||
final LiteralCommandNode<CommandSource> original, final String newName) {
|
final LiteralCommandNode<CommandSource> original, final String newName) {
|
||||||
|
return shallowCopy(original, newName, original.getCommand());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a copy of the given literal with the specified name.
|
||||||
|
*
|
||||||
|
* @param original the literal node to copy
|
||||||
|
* @param newName the name of the returned literal node
|
||||||
|
* @param newCommand the new command to set on the copied node
|
||||||
|
* @return a copy of the literal with the given name
|
||||||
|
*/
|
||||||
|
private static LiteralCommandNode<CommandSource> shallowCopy(
|
||||||
|
final LiteralCommandNode<CommandSource> original, final String newName,
|
||||||
|
final com.mojang.brigadier.Command<CommandSource> newCommand) {
|
||||||
|
return shallowCopyAsBuilder(original, newName, false).executes(newCommand).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a copy of the given literal with the specified name.
|
||||||
|
*
|
||||||
|
* @param original the literal node to copy
|
||||||
|
* @param newName the name of the returned literal node
|
||||||
|
* @return a copy of the literal with the given name
|
||||||
|
*/
|
||||||
|
private static LiteralArgumentBuilder<CommandSource> shallowCopyAsBuilder(
|
||||||
|
final LiteralCommandNode<CommandSource> original, final String newName,
|
||||||
|
final boolean skipChildren) {
|
||||||
// Brigadier resolves the redirect of a node if further input can be parsed.
|
// Brigadier resolves the redirect of a node if further input can be parsed.
|
||||||
// Let <bar> be a literal node having a redirect to a <foo> literal. Then,
|
// Let <bar> be a literal node having a redirect to a <foo> literal. Then,
|
||||||
// the context returned by CommandDispatcher#parseNodes when given the input
|
// the context returned by CommandDispatcher#parseNodes when given the input
|
||||||
@ -150,10 +232,12 @@ public final class VelocityCommands {
|
|||||||
.requiresWithContext(original.getContextRequirement())
|
.requiresWithContext(original.getContextRequirement())
|
||||||
.forward(original.getRedirect(), original.getRedirectModifier(), original.isFork())
|
.forward(original.getRedirect(), original.getRedirectModifier(), original.isFork())
|
||||||
.executes(original.getCommand());
|
.executes(original.getCommand());
|
||||||
for (final CommandNode<CommandSource> child : original.getChildren()) {
|
if (!skipChildren) {
|
||||||
builder.then(child);
|
for (final CommandNode<CommandSource> child : original.getChildren()) {
|
||||||
|
builder.then(child);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return builder.build();
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Arguments node
|
// Arguments node
|
||||||
|
@ -93,6 +93,16 @@ public class VelocityArgumentCommandNode<S, T> extends ArgumentCommandNode<S, St
|
|||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public VelocityArgumentCommandNode<S, T> withCommand(Command<S> command) {
|
||||||
|
return new VelocityArgumentCommandNode<>(getName(), type, command, getRequirement(),
|
||||||
|
getContextRequirement(), getRedirect(), getRedirectModifier(), isFork(), getCustomSuggestions());
|
||||||
|
}
|
||||||
|
|
||||||
|
public VelocityArgumentCommandNode<S, T> withRedirect(CommandNode<S> target) {
|
||||||
|
return new VelocityArgumentCommandNode<>(getName(), type, getCommand(), getRequirement(),
|
||||||
|
getContextRequirement(), target, getRedirectModifier(), isFork(), getCustomSuggestions());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isValidInput(final String input) {
|
public boolean isValidInput(final String input) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 Velocity 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.velocitypowered.proxy.command.brigadier;
|
||||||
|
|
||||||
|
import com.mojang.brigadier.Command;
|
||||||
|
import com.mojang.brigadier.context.CommandContext;
|
||||||
|
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||||
|
import com.velocitypowered.api.command.CommandSource;
|
||||||
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wraps a Brigadier command to allow us to track the registrant.
|
||||||
|
*/
|
||||||
|
public class VelocityBrigadierCommandWrapper implements Command<CommandSource> {
|
||||||
|
|
||||||
|
private final Command<CommandSource> delegate;
|
||||||
|
private final Object registrant;
|
||||||
|
|
||||||
|
private VelocityBrigadierCommandWrapper(Command<CommandSource> delegate, Object registrant) {
|
||||||
|
this.delegate = delegate;
|
||||||
|
this.registrant = registrant;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transforms the given command into a {@code VelocityBrigadierCommandWrapper} if the registrant
|
||||||
|
* is not null and if the command is not already wrapped.
|
||||||
|
*
|
||||||
|
* @param delegate the command to wrap
|
||||||
|
* @param registrant the registrant of the command
|
||||||
|
* @return the wrapped command, if necessary
|
||||||
|
*/
|
||||||
|
public static Command<CommandSource> wrap(Command<CommandSource> delegate, @Nullable Object registrant) {
|
||||||
|
if (registrant == null) {
|
||||||
|
// nothing to wrap
|
||||||
|
return delegate;
|
||||||
|
}
|
||||||
|
if (delegate instanceof VelocityBrigadierCommandWrapper) {
|
||||||
|
// already wrapped
|
||||||
|
return delegate;
|
||||||
|
}
|
||||||
|
return new VelocityBrigadierCommandWrapper(delegate, registrant);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int run(CommandContext<CommandSource> context) throws CommandSyntaxException {
|
||||||
|
return delegate.run(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object registrant() {
|
||||||
|
return registrant;
|
||||||
|
}
|
||||||
|
}
|
@ -31,6 +31,7 @@ import com.velocitypowered.api.permission.Tristate;
|
|||||||
import com.velocitypowered.api.proxy.Player;
|
import com.velocitypowered.api.proxy.Player;
|
||||||
import com.velocitypowered.api.proxy.ProxyServer;
|
import com.velocitypowered.api.proxy.ProxyServer;
|
||||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||||
|
import com.velocitypowered.proxy.plugin.virtual.VelocityVirtualPlugin;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
@ -80,7 +81,13 @@ public class GlistCommand {
|
|||||||
.executes(this::serverCount)
|
.executes(this::serverCount)
|
||||||
.build();
|
.build();
|
||||||
rootNode.then(serverNode);
|
rootNode.then(serverNode);
|
||||||
server.getCommandManager().register(new BrigadierCommand(rootNode));
|
final BrigadierCommand command = new BrigadierCommand(rootNode);
|
||||||
|
server.getCommandManager().register(
|
||||||
|
server.getCommandManager().metaBuilder(command)
|
||||||
|
.plugin(VelocityVirtualPlugin.INSTANCE)
|
||||||
|
.build(),
|
||||||
|
command
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int totalCount(final CommandContext<CommandSource> context) {
|
private int totalCount(final CommandContext<CommandSource> context) {
|
||||||
|
@ -30,6 +30,7 @@ import com.velocitypowered.api.proxy.Player;
|
|||||||
import com.velocitypowered.api.proxy.ProxyServer;
|
import com.velocitypowered.api.proxy.ProxyServer;
|
||||||
import com.velocitypowered.api.proxy.ServerConnection;
|
import com.velocitypowered.api.proxy.ServerConnection;
|
||||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||||
|
import com.velocitypowered.proxy.plugin.virtual.VelocityVirtualPlugin;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
@ -96,7 +97,13 @@ public class SendCommand {
|
|||||||
.build();
|
.build();
|
||||||
playerNode.then(serverNode);
|
playerNode.then(serverNode);
|
||||||
rootNode.then(playerNode.build());
|
rootNode.then(playerNode.build());
|
||||||
server.getCommandManager().register(new BrigadierCommand(rootNode.build()));
|
final BrigadierCommand command = new BrigadierCommand(rootNode);
|
||||||
|
server.getCommandManager().register(
|
||||||
|
server.getCommandManager().metaBuilder(command)
|
||||||
|
.plugin(VelocityVirtualPlugin.INSTANCE)
|
||||||
|
.build(),
|
||||||
|
command
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int usage(final CommandContext<CommandSource> context) {
|
private int usage(final CommandContext<CommandSource> context) {
|
||||||
|
@ -40,17 +40,19 @@ public final class BrigadierCommandRegistrar extends AbstractCommandRegistrar<Br
|
|||||||
// Register it (if valid), since it's probably what the user expects.
|
// Register it (if valid), since it's probably what the user expects.
|
||||||
// If invalid, the metadata contains the same alias, but in lowercase.
|
// If invalid, the metadata contains the same alias, but in lowercase.
|
||||||
final LiteralCommandNode<CommandSource> literal = command.getNode();
|
final LiteralCommandNode<CommandSource> literal = command.getNode();
|
||||||
|
final LiteralCommandNode<CommandSource> wrapped =
|
||||||
|
(LiteralCommandNode<CommandSource>) VelocityCommands.wrap(literal, meta.getPlugin());
|
||||||
final String primaryAlias = literal.getName();
|
final String primaryAlias = literal.getName();
|
||||||
if (VelocityCommands.isValidAlias(primaryAlias)) {
|
if (VelocityCommands.isValidAlias(primaryAlias)) {
|
||||||
// Register directly without copying
|
// Register directly without copying
|
||||||
this.register(literal);
|
this.register(wrapped);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (final String alias : meta.getAliases()) {
|
for (final String alias : meta.getAliases()) {
|
||||||
if (primaryAlias.equals(alias)) {
|
if (primaryAlias.equals(alias)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
this.register(literal, alias);
|
this.register(wrapped, alias);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Brigadier commands don't support hinting, ignore
|
// Brigadier commands don't support hinting, ignore
|
||||||
|
@ -32,6 +32,7 @@ import com.velocitypowered.api.command.InvocableCommand;
|
|||||||
import com.velocitypowered.proxy.command.VelocityCommandMeta;
|
import com.velocitypowered.proxy.command.VelocityCommandMeta;
|
||||||
import com.velocitypowered.proxy.command.VelocityCommands;
|
import com.velocitypowered.proxy.command.VelocityCommands;
|
||||||
import com.velocitypowered.proxy.command.brigadier.VelocityArgumentBuilder;
|
import com.velocitypowered.proxy.command.brigadier.VelocityArgumentBuilder;
|
||||||
|
import com.velocitypowered.proxy.command.brigadier.VelocityBrigadierCommandWrapper;
|
||||||
import com.velocitypowered.proxy.command.invocation.CommandInvocationFactory;
|
import com.velocitypowered.proxy.command.invocation.CommandInvocationFactory;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.concurrent.locks.Lock;
|
import java.util.concurrent.locks.Lock;
|
||||||
@ -76,11 +77,11 @@ abstract class InvocableCommandRegistrar<T extends InvocableCommand<I>,
|
|||||||
final I invocation = invocationFactory.create(context);
|
final I invocation = invocationFactory.create(context);
|
||||||
return command.hasPermission(invocation);
|
return command.hasPermission(invocation);
|
||||||
};
|
};
|
||||||
final Command<CommandSource> callback = context -> {
|
final Command<CommandSource> callback = VelocityBrigadierCommandWrapper.wrap(context -> {
|
||||||
final I invocation = invocationFactory.create(context);
|
final I invocation = invocationFactory.create(context);
|
||||||
command.execute(invocation);
|
command.execute(invocation);
|
||||||
return 1; // handled
|
return 1; // handled
|
||||||
};
|
}, meta.getPlugin());
|
||||||
|
|
||||||
final LiteralCommandNode<CommandSource> literal = LiteralArgumentBuilder
|
final LiteralCommandNode<CommandSource> literal = LiteralArgumentBuilder
|
||||||
.<CommandSource>literal(alias)
|
.<CommandSource>literal(alias)
|
||||||
|
@ -68,7 +68,12 @@ public class VelocityPluginManager implements PluginManager {
|
|||||||
this.server = checkNotNull(server, "server");
|
this.server = checkNotNull(server, "server");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerPlugin(PluginContainer plugin) {
|
/**
|
||||||
|
* Registers a plugin with the plugin manager.
|
||||||
|
*
|
||||||
|
* @param plugin the plugin to register
|
||||||
|
*/
|
||||||
|
public void registerPlugin(PluginContainer plugin) {
|
||||||
pluginsById.put(plugin.getDescription().getId(), plugin);
|
pluginsById.put(plugin.getDescription().getId(), plugin);
|
||||||
Optional<?> instance = plugin.getInstance();
|
Optional<?> instance = plugin.getInstance();
|
||||||
instance.ifPresent(o -> pluginInstances.put(o, plugin));
|
instance.ifPresent(o -> pluginInstances.put(o, plugin));
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 Velocity 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.velocitypowered.proxy.plugin.virtual;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A singleton plugin object that represents the Velocity proxy itself.
|
||||||
|
*/
|
||||||
|
public class VelocityVirtualPlugin {
|
||||||
|
@SuppressWarnings("InstantiationOfUtilityClass")
|
||||||
|
public static final VelocityVirtualPlugin INSTANCE = new VelocityVirtualPlugin();
|
||||||
|
|
||||||
|
private VelocityVirtualPlugin() {
|
||||||
|
}
|
||||||
|
}
|
@ -230,7 +230,7 @@ public class BrigadierCommandTests extends CommandTestSuite {
|
|||||||
final Exception wrapper = assertThrows(CompletionException.class, () ->
|
final Exception wrapper = assertThrows(CompletionException.class, () ->
|
||||||
manager.executeAsync(source, "hello").join());
|
manager.executeAsync(source, "hello").join());
|
||||||
|
|
||||||
assertSame(expected, wrapper.getCause().getCause());
|
assertSame(expected, wrapper.getCause());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Suggestions
|
// Suggestions
|
||||||
|
@ -29,6 +29,7 @@ import com.velocitypowered.api.permission.Tristate;
|
|||||||
import com.velocitypowered.api.proxy.Player;
|
import com.velocitypowered.api.proxy.Player;
|
||||||
import com.velocitypowered.proxy.event.MockEventManager;
|
import com.velocitypowered.proxy.event.MockEventManager;
|
||||||
import com.velocitypowered.proxy.event.VelocityEventManager;
|
import com.velocitypowered.proxy.event.VelocityEventManager;
|
||||||
|
import com.velocitypowered.proxy.testutil.FakePluginManager;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
@ -48,7 +49,7 @@ abstract class CommandTestSuite {
|
|||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void setUp() {
|
void setUp() {
|
||||||
this.manager = new VelocityCommandManager(eventManager);
|
this.manager = new VelocityCommandManager(eventManager, new FakePluginManager());
|
||||||
}
|
}
|
||||||
|
|
||||||
final void assertHandled(final String input) {
|
final void assertHandled(final String input) {
|
||||||
|
@ -22,6 +22,7 @@ import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
|||||||
import com.velocitypowered.api.plugin.PluginContainer;
|
import com.velocitypowered.api.plugin.PluginContainer;
|
||||||
import com.velocitypowered.api.plugin.PluginDescription;
|
import com.velocitypowered.api.plugin.PluginDescription;
|
||||||
import com.velocitypowered.api.plugin.PluginManager;
|
import com.velocitypowered.api.plugin.PluginManager;
|
||||||
|
import com.velocitypowered.proxy.plugin.virtual.VelocityVirtualPlugin;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
@ -39,6 +40,8 @@ public class FakePluginManager implements PluginManager {
|
|||||||
|
|
||||||
private final PluginContainer containerA = new FakePluginContainer("a", PLUGIN_A);
|
private final PluginContainer containerA = new FakePluginContainer("a", PLUGIN_A);
|
||||||
private final PluginContainer containerB = new FakePluginContainer("b", PLUGIN_B);
|
private final PluginContainer containerB = new FakePluginContainer("b", PLUGIN_B);
|
||||||
|
private final PluginContainer containerVelocity = new FakePluginContainer("velocity",
|
||||||
|
VelocityVirtualPlugin.INSTANCE);
|
||||||
|
|
||||||
private ExecutorService service = Executors.newCachedThreadPool(
|
private ExecutorService service = Executors.newCachedThreadPool(
|
||||||
new ThreadFactoryBuilder().setNameFormat("Test Async Thread").setDaemon(true).build()
|
new ThreadFactoryBuilder().setNameFormat("Test Async Thread").setDaemon(true).build()
|
||||||
@ -50,6 +53,8 @@ public class FakePluginManager implements PluginManager {
|
|||||||
return Optional.of(containerA);
|
return Optional.of(containerA);
|
||||||
} else if (instance == PLUGIN_B) {
|
} else if (instance == PLUGIN_B) {
|
||||||
return Optional.of(containerB);
|
return Optional.of(containerB);
|
||||||
|
} else if (instance == VelocityVirtualPlugin.INSTANCE) {
|
||||||
|
return Optional.of(containerVelocity);
|
||||||
} else {
|
} else {
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
@ -62,6 +67,8 @@ public class FakePluginManager implements PluginManager {
|
|||||||
return Optional.of(containerA);
|
return Optional.of(containerA);
|
||||||
case "b":
|
case "b":
|
||||||
return Optional.of(containerB);
|
return Optional.of(containerB);
|
||||||
|
case "velocity":
|
||||||
|
return Optional.of(containerVelocity);
|
||||||
default:
|
default:
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
@ -69,7 +76,7 @@ public class FakePluginManager implements PluginManager {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NonNull Collection<PluginContainer> getPlugins() {
|
public @NonNull Collection<PluginContainer> getPlugins() {
|
||||||
return ImmutableList.of(containerA, containerB);
|
return ImmutableList.of(containerVelocity, containerA, containerB);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren