0.3
This commit is contained in:
parent
f8e79ea869
commit
4f8429e0b1
8 changed files with 298 additions and 151 deletions
|
|
@ -2,10 +2,11 @@ plugins {
|
|||
id("java")
|
||||
id("java-library")
|
||||
id("maven-publish")
|
||||
kotlin("jvm") version "1.7.0"
|
||||
}
|
||||
|
||||
group = "ru.d3st0ny"
|
||||
version = "0.1"
|
||||
version = "0.3"
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
|
|
@ -17,17 +18,16 @@ dependencies {
|
|||
api("com.mojang:brigadier:1.0.18") {
|
||||
exclude("com.google.guava", "guava")
|
||||
}
|
||||
compileOnly("io.papermc.paper:paper-api:1.19-R0.1-SNAPSHOT")
|
||||
compileOnly("io.papermc.paper:paper-api:1.19.2-R0.1-SNAPSHOT")
|
||||
compileOnly("io.papermc.paper:paper-mojangapi:1.19.2-R0.1-SNAPSHOT")
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
create<MavenPublication>("maven"){
|
||||
artifactId = project.name.toLowerCase()
|
||||
groupId = "${project.group}"
|
||||
version = "${project.version}"
|
||||
from(components["java"])
|
||||
}
|
||||
publications.create<MavenPublication>("maven") {
|
||||
artifactId = project.name.toLowerCase()
|
||||
groupId = "${project.group}"
|
||||
version = "${project.version}"
|
||||
from(components["java"])
|
||||
}
|
||||
repositories {
|
||||
maven {
|
||||
|
|
|
|||
139
src/main/java/ru/d3st0ny/adajency/AbstractAdajency.java
Normal file
139
src/main/java/ru/d3st0ny/adajency/AbstractAdajency.java
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
package ru.d3st0ny.adajency;
|
||||
|
||||
import com.mojang.brigadier.suggestion.SuggestionProvider;
|
||||
import com.mojang.brigadier.tree.ArgumentCommandNode;
|
||||
import com.mojang.brigadier.tree.CommandNode;
|
||||
import com.mojang.brigadier.tree.LiteralCommandNode;
|
||||
import com.mojang.brigadier.tree.RootCommandNode;
|
||||
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.PluginCommand;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
abstract class AbstractAdajency implements Adajency {
|
||||
|
||||
// ArgumentCommandNode#customSuggestions field
|
||||
protected static final Field CUSTOM_SUGGESTIONS_FIELD;
|
||||
|
||||
// CommandNode#command
|
||||
protected static final Field COMMAND_EXECUTE_FUNCTION_FIELD;
|
||||
|
||||
// CommandNode#children, CommandNode#literals, CommandNode#arguments fields
|
||||
protected static final Field CHILDREN_FIELD;
|
||||
protected static final Field LITERALS_FIELD;
|
||||
protected static final Field ARGUMENTS_FIELD;
|
||||
|
||||
// An array of the CommandNode fields above: [#children, #literals, #arguments]
|
||||
protected static final Field[] CHILDREN_FIELDS;
|
||||
|
||||
// Dummy instance of Command used to ensure the executable bit gets set on
|
||||
// mock commands when they're encoded into data sent to the client
|
||||
protected static final com.mojang.brigadier.Command<?> DUMMY_COMMAND;
|
||||
protected static final SuggestionProvider<?> DUMMY_SUGGESTION_PROVIDER;
|
||||
|
||||
static {
|
||||
try {
|
||||
CUSTOM_SUGGESTIONS_FIELD = ArgumentCommandNode.class.getDeclaredField("customSuggestions");
|
||||
CUSTOM_SUGGESTIONS_FIELD.setAccessible(true);
|
||||
|
||||
COMMAND_EXECUTE_FUNCTION_FIELD = CommandNode.class.getDeclaredField("command");
|
||||
COMMAND_EXECUTE_FUNCTION_FIELD.setAccessible(true);
|
||||
|
||||
CHILDREN_FIELD = CommandNode.class.getDeclaredField("children");
|
||||
LITERALS_FIELD = CommandNode.class.getDeclaredField("literals");
|
||||
ARGUMENTS_FIELD = CommandNode.class.getDeclaredField("arguments");
|
||||
CHILDREN_FIELDS = new Field[]{CHILDREN_FIELD, LITERALS_FIELD, ARGUMENTS_FIELD};
|
||||
for (Field field : CHILDREN_FIELDS) {
|
||||
field.setAccessible(true);
|
||||
}
|
||||
|
||||
// should never be called
|
||||
// if ReflectionCommodore: bukkit handling should override
|
||||
// if PaperCommodore: this is only sent to the client, not used for actual command handling
|
||||
DUMMY_COMMAND = (ctx) -> { throw new UnsupportedOperationException(); };
|
||||
// should never be called - only used in clientbound root node, and the server impl will pass anything through
|
||||
// SuggestionProviders#safelySwap (swap it for the ASK_SERVER provider) before sending
|
||||
DUMMY_SUGGESTION_PROVIDER = (context, builder) -> { throw new UnsupportedOperationException(); };
|
||||
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new ExceptionInInitializerError(e);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
protected static void removeChild(RootCommandNode root, String name) {
|
||||
try {
|
||||
for (Field field : CHILDREN_FIELDS) {
|
||||
Map<String, ?> children = (Map<String, ?>) field.get(root);
|
||||
children.remove(name);
|
||||
}
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected static void setRequiredHackyFieldsRecursively(CommandNode<?> node, SuggestionProvider<?> suggestionProvider) {
|
||||
// set command execution function so the server sets the executable flag on the command
|
||||
try {
|
||||
COMMAND_EXECUTE_FUNCTION_FIELD.set(node, DUMMY_COMMAND);
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (suggestionProvider != null && node instanceof ArgumentCommandNode<?, ?> argumentNode) {
|
||||
// set the custom suggestion provider field so tab completions work
|
||||
try {
|
||||
CUSTOM_SUGGESTIONS_FIELD.set(argumentNode, suggestionProvider);
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
for (CommandNode<?> child : node.getChildren()) {
|
||||
setRequiredHackyFieldsRecursively(child, suggestionProvider);
|
||||
}
|
||||
}
|
||||
|
||||
protected static <S> LiteralCommandNode<S> renameLiteralNode(LiteralCommandNode<S> node, String newLiteral) {
|
||||
LiteralCommandNode<S> clone = new LiteralCommandNode<>(newLiteral, node.getCommand(), node.getRequirement(), node.getRedirect(), node.getRedirectModifier(), node.isFork());
|
||||
for (CommandNode<S> child : node.getChildren()) {
|
||||
clone.addChild(child);
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the aliases known for the given command.
|
||||
*
|
||||
* <p>This will include the main label, as well as defined aliases, and
|
||||
* aliases including the fallback prefix added by Bukkit.</p>
|
||||
*
|
||||
* @param command the command
|
||||
* @return the aliases
|
||||
*/
|
||||
protected static Collection<String> getAliases(Command command) {
|
||||
Objects.requireNonNull(command, "command");
|
||||
|
||||
Stream<String> aliasesStream = Stream.concat(
|
||||
Stream.of(command.getLabel()),
|
||||
command.getAliases().stream()
|
||||
);
|
||||
|
||||
if (command instanceof PluginCommand) {
|
||||
String fallbackPrefix = ((PluginCommand) command).getPlugin().getName().toLowerCase().trim();
|
||||
aliasesStream = aliasesStream.flatMap(alias -> Stream.of(
|
||||
alias,
|
||||
fallbackPrefix + ":" + alias
|
||||
));
|
||||
}
|
||||
|
||||
return aliasesStream.distinct().collect(Collectors.toList());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -66,7 +66,11 @@ public interface Adajency {
|
|||
* @param command the command to read aliases from
|
||||
* @param node the argument data
|
||||
*/
|
||||
void register(Command command, LiteralCommandNode<?> node);
|
||||
default void register(Command command, LiteralCommandNode<?> node) {
|
||||
Objects.requireNonNull(command, "command");
|
||||
Objects.requireNonNull(node, "node");
|
||||
register(command, node, command::testPermissionSilent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the provided argument data to the dispatcher, against all
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package ru.d3st0ny.adajency;
|
|||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Factory for obtaining instances of {@link Adajency}.
|
||||
|
|
@ -12,20 +13,39 @@ public final class AdajencyProvider {
|
|||
throw new AssertionError();
|
||||
}
|
||||
|
||||
private static final Throwable SETUP_EXCEPTION = checkSupported();
|
||||
private static final Function<Plugin, Adajency> PROVIDER = checkSupported();
|
||||
|
||||
private static Throwable checkSupported() {
|
||||
private static Function<Plugin, Adajency> checkSupported() {
|
||||
try {
|
||||
Class.forName("com.mojang.brigadier.CommandDispatcher");
|
||||
AdajencyImpl.ensureSetup();
|
||||
MinecraftArgumentType.ensureSetup();
|
||||
return null;
|
||||
} catch (Throwable e) {
|
||||
if (System.getProperty("adajency.debug") != null) {
|
||||
System.err.println("Exception while initialising adajency:");
|
||||
e.printStackTrace(System.err);
|
||||
}
|
||||
return e;
|
||||
printDebugInfo(e);
|
||||
return null;
|
||||
}
|
||||
|
||||
// try the paper impl
|
||||
try {
|
||||
PaperAdajency.ensureSetup();
|
||||
return PaperAdajency::new;
|
||||
} catch (Throwable e) {
|
||||
printDebugInfo(e);
|
||||
}
|
||||
|
||||
// try reflection impl
|
||||
try {
|
||||
ReflectionAdajency.ensureSetup();
|
||||
return ReflectionAdajency::new;
|
||||
} catch (Throwable e) {
|
||||
printDebugInfo(e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void printDebugInfo(Throwable e) {
|
||||
if (System.getProperty("adajency.debug") != null) {
|
||||
System.err.println("Exception while initialising adajency:");
|
||||
e.printStackTrace(System.err);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -35,7 +55,7 @@ public final class AdajencyProvider {
|
|||
* @return true if adajency is supported.
|
||||
*/
|
||||
public static boolean isSupported() {
|
||||
return SETUP_EXCEPTION == null;
|
||||
return PROVIDER != null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -48,9 +68,12 @@ public final class AdajencyProvider {
|
|||
*/
|
||||
public static Adajency getAdajency(Plugin plugin) throws BrigadierUnsupportedException {
|
||||
Objects.requireNonNull(plugin, "plugin");
|
||||
if (SETUP_EXCEPTION != null) {
|
||||
throw new BrigadierUnsupportedException("Brigadier is not supported by the server.", SETUP_EXCEPTION);
|
||||
if (PROVIDER == null) {
|
||||
throw new BrigadierUnsupportedException(
|
||||
"Brigadier is not supported by the server. " +
|
||||
"Set -Dadajency.debug=true for debug info."
|
||||
);
|
||||
}
|
||||
return new AdajencyImpl(plugin);
|
||||
return PROVIDER.apply(plugin);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ package ru.d3st0ny.adajency;
|
|||
*/
|
||||
public final class BrigadierUnsupportedException extends UnsupportedOperationException {
|
||||
|
||||
public BrigadierUnsupportedException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
BrigadierUnsupportedException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
96
src/main/java/ru/d3st0ny/adajency/PaperAdajency.java
Normal file
96
src/main/java/ru/d3st0ny/adajency/PaperAdajency.java
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
package ru.d3st0ny.adajency;
|
||||
|
||||
import com.destroystokyo.paper.event.brigadier.AsyncPlayerSendCommandsEvent;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.tree.CommandNode;
|
||||
import com.mojang.brigadier.tree.LiteralCommandNode;
|
||||
import com.mojang.brigadier.tree.RootCommandNode;
|
||||
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
final class PaperAdajency extends AbstractAdajency implements Adajency, Listener {
|
||||
|
||||
static {
|
||||
try {
|
||||
Class.forName("com.destroystokyo.paper.event.brigadier.AsyncPlayerSendCommandsEvent");
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new UnsupportedOperationException("Not running on modern Paper!", e);
|
||||
}
|
||||
}
|
||||
|
||||
private final List<AdajencyCommand> commands = new ArrayList<>();
|
||||
|
||||
PaperAdajency(Plugin plugin) {
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(LiteralCommandNode<?> node) {
|
||||
Objects.requireNonNull(node, "node");
|
||||
this.commands.add(new AdajencyCommand(node, null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(Command command, LiteralCommandNode<?> node, Predicate<? super Player> permissionTest) {
|
||||
Objects.requireNonNull(command, "command");
|
||||
Objects.requireNonNull(node, "node");
|
||||
Objects.requireNonNull(permissionTest, "permissionTest");
|
||||
|
||||
try {
|
||||
setRequiredHackyFieldsRecursively(node, DUMMY_SUGGESTION_PROVIDER);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
Collection<String> aliases = getAliases(command);
|
||||
if (!aliases.contains(node.getLiteral())) {
|
||||
node = renameLiteralNode(node, command.getName());
|
||||
}
|
||||
|
||||
for (String alias : aliases) {
|
||||
if (node.getLiteral().equals(alias)) {
|
||||
this.commands.add(new AdajencyCommand(node, permissionTest));
|
||||
} else {
|
||||
LiteralCommandNode<Object> redirectNode = LiteralArgumentBuilder.literal(alias)
|
||||
.redirect((LiteralCommandNode<Object>) node)
|
||||
.build();
|
||||
this.commands.add(new AdajencyCommand(redirectNode, permissionTest));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
@SuppressWarnings("deprecation") // draft API, ok...
|
||||
public void onPlayerSendCommandsEvent(AsyncPlayerSendCommandsEvent<?> event) {
|
||||
if (event.isAsynchronous() || !event.hasFiredAsync()) {
|
||||
for (AdajencyCommand command : this.commands) {
|
||||
command.apply(event.getPlayer(), event.getCommandNode());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private record AdajencyCommand(LiteralCommandNode<?> node, Predicate<? super Player> permissionTest) {
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public void apply(Player player, RootCommandNode<?> root) {
|
||||
if (this.permissionTest != null && !this.permissionTest.test(player)) {
|
||||
return;
|
||||
}
|
||||
removeChild(root, this.node.getName());
|
||||
root.addChild((CommandNode) this.node);
|
||||
}
|
||||
}
|
||||
|
||||
static void ensureSetup() {
|
||||
// do nothing - this is only called to trigger the static initializer
|
||||
}
|
||||
}
|
||||
|
|
@ -3,14 +3,11 @@ package ru.d3st0ny.adajency;
|
|||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.suggestion.SuggestionProvider;
|
||||
import com.mojang.brigadier.tree.ArgumentCommandNode;
|
||||
import com.mojang.brigadier.tree.CommandNode;
|
||||
import com.mojang.brigadier.tree.LiteralCommandNode;
|
||||
import com.mojang.brigadier.tree.RootCommandNode;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.PluginCommand;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
|
|
@ -26,14 +23,12 @@ import java.util.Arrays;
|
|||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
final class AdajencyImpl implements Adajency {
|
||||
final class ReflectionAdajency extends AbstractAdajency implements Adajency {
|
||||
|
||||
// obc.CraftServer#console field
|
||||
private static final Field CONSOLE_FIELD;
|
||||
|
|
@ -47,26 +42,12 @@ final class AdajencyImpl implements Adajency {
|
|||
// obc.command.BukkitCommandWrapper constructor
|
||||
private static final Constructor<?> COMMAND_WRAPPER_CONSTRUCTOR;
|
||||
|
||||
// ArgumentCommandNode#customSuggestions field
|
||||
private static final Field CUSTOM_SUGGESTIONS_FIELD;
|
||||
|
||||
// CommandNode#command
|
||||
private static final Field COMMAND_EXECUTE_FUNCTION_FIELD;
|
||||
|
||||
// CommandNode#children, CommandNode#literals, CommandNode#arguments fields
|
||||
private static final Field CHILDREN_FIELD;
|
||||
private static final Field LITERALS_FIELD;
|
||||
private static final Field ARGUMENTS_FIELD;
|
||||
|
||||
// An array of the CommandNode fields above: [#children, #literals, #arguments]
|
||||
private static final Field[] CHILDREN_FIELDS;
|
||||
|
||||
// Dummy instance of Command used to ensure the executable bit gets set on
|
||||
// mock commands when they're encoded into data sent to the client
|
||||
private static final com.mojang.brigadier.Command<?> DUMMY_COMMAND;
|
||||
|
||||
static {
|
||||
try {
|
||||
if (ReflectionUtil.minecraftVersion() >= 19) {
|
||||
throw new UnsupportedOperationException("ReflectionAdajency is not supported on MC 1.19 or above. Switch to Paper :)");
|
||||
}
|
||||
|
||||
final Class<?> minecraftServer;
|
||||
final Class<?> commandDispatcher;
|
||||
|
||||
|
|
@ -97,22 +78,6 @@ final class AdajencyImpl implements Adajency {
|
|||
Class<?> commandWrapperClass = ReflectionUtil.obcClass("command.BukkitCommandWrapper");
|
||||
COMMAND_WRAPPER_CONSTRUCTOR = commandWrapperClass.getConstructor(craftServer, Command.class);
|
||||
|
||||
CUSTOM_SUGGESTIONS_FIELD = ArgumentCommandNode.class.getDeclaredField("customSuggestions");
|
||||
CUSTOM_SUGGESTIONS_FIELD.setAccessible(true);
|
||||
|
||||
COMMAND_EXECUTE_FUNCTION_FIELD = CommandNode.class.getDeclaredField("command");
|
||||
COMMAND_EXECUTE_FUNCTION_FIELD.setAccessible(true);
|
||||
|
||||
CHILDREN_FIELD = CommandNode.class.getDeclaredField("children");
|
||||
LITERALS_FIELD = CommandNode.class.getDeclaredField("literals");
|
||||
ARGUMENTS_FIELD = CommandNode.class.getDeclaredField("arguments");
|
||||
CHILDREN_FIELDS = new Field[]{CHILDREN_FIELD, LITERALS_FIELD, ARGUMENTS_FIELD};
|
||||
for (Field field : CHILDREN_FIELDS) {
|
||||
field.setAccessible(true);
|
||||
}
|
||||
|
||||
DUMMY_COMMAND = (ctx) -> { throw new UnsupportedOperationException(); };
|
||||
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new ExceptionInInitializerError(e);
|
||||
}
|
||||
|
|
@ -121,7 +86,7 @@ final class AdajencyImpl implements Adajency {
|
|||
private final Plugin plugin;
|
||||
private final List<LiteralCommandNode<?>> registeredNodes = new ArrayList<>();
|
||||
|
||||
AdajencyImpl(Plugin plugin) {
|
||||
ReflectionAdajency(Plugin plugin) {
|
||||
this.plugin = plugin;
|
||||
this.plugin.getServer().getPluginManager().registerEvents(new ServerReloadListener(this), this.plugin);
|
||||
}
|
||||
|
|
@ -172,70 +137,19 @@ final class AdajencyImpl implements Adajency {
|
|||
if (node.getLiteral().equals(alias)) {
|
||||
register(node);
|
||||
} else {
|
||||
register(LiteralArgumentBuilder.literal(alias).redirect((LiteralCommandNode<Object>)node).build());
|
||||
register(LiteralArgumentBuilder.literal(alias).redirect((LiteralCommandNode<Object>) node).build());
|
||||
}
|
||||
}
|
||||
|
||||
this.plugin.getServer().getPluginManager().registerEvents(new CommandDataSendListener(command, permissionTest), this.plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(Command command, LiteralCommandNode<?> node) {
|
||||
Objects.requireNonNull(command, "command");
|
||||
Objects.requireNonNull(node, "node");
|
||||
|
||||
register(command, node, command::testPermissionSilent);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
private static void removeChild(RootCommandNode root, String name) {
|
||||
try {
|
||||
for (Field field : CHILDREN_FIELDS) {
|
||||
Map<String, ?> children = (Map<String, ?>) field.get(root);
|
||||
children.remove(name);
|
||||
}
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void setRequiredHackyFieldsRecursively(CommandNode<?> node, SuggestionProvider<?> suggestionProvider) {
|
||||
// set command execution function so the server sets the executable flag on the command
|
||||
try {
|
||||
COMMAND_EXECUTE_FUNCTION_FIELD.set(node, DUMMY_COMMAND);
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (node instanceof ArgumentCommandNode<?, ?> argumentNode) {
|
||||
|
||||
// set the custom suggestion provider field so tab completions work
|
||||
try {
|
||||
CUSTOM_SUGGESTIONS_FIELD.set(argumentNode, suggestionProvider);
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
for (CommandNode<?> child : node.getChildren()) {
|
||||
setRequiredHackyFieldsRecursively(child, suggestionProvider);
|
||||
}
|
||||
}
|
||||
|
||||
private static <S> LiteralCommandNode<S> renameLiteralNode(LiteralCommandNode<S> node, String newLiteral) {
|
||||
LiteralCommandNode<S> clone = new LiteralCommandNode<>(newLiteral, node.getCommand(), node.getRequirement(), node.getRedirect(), node.getRedirectModifier(), node.isFork());
|
||||
for (CommandNode<S> child : node.getChildren()) {
|
||||
clone.addChild(child);
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens for server (re)loads, and re-adds all registered nodes to the dispatcher.
|
||||
*/
|
||||
private record ServerReloadListener(AdajencyImpl adajency) implements Listener {
|
||||
private record ServerReloadListener(ReflectionAdajency adajency) implements Listener {
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
@EventHandler
|
||||
public void onLoad(ServerLoadEvent e) {
|
||||
CommandDispatcher dispatcher = this.adajency.getDispatcher();
|
||||
|
|
@ -276,36 +190,7 @@ final class AdajencyImpl implements Adajency {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the aliases known for the given command.
|
||||
*
|
||||
* <p>This will include the main label, as well as defined aliases, and
|
||||
* aliases including the fallback prefix added by Bukkit.</p>
|
||||
*
|
||||
* @param command the command
|
||||
* @return the aliases
|
||||
*/
|
||||
private static Collection<String> getAliases(Command command) {
|
||||
Objects.requireNonNull(command, "command");
|
||||
|
||||
Stream<String> aliasesStream = Stream.concat(
|
||||
Stream.of(command.getLabel()),
|
||||
command.getAliases().stream()
|
||||
);
|
||||
|
||||
if (command instanceof PluginCommand) {
|
||||
String fallbackPrefix = ((PluginCommand) command).getPlugin().getName().toLowerCase().trim();
|
||||
aliasesStream = aliasesStream.flatMap(alias -> Stream.of(
|
||||
alias,
|
||||
fallbackPrefix + ":" + alias
|
||||
));
|
||||
}
|
||||
|
||||
return aliasesStream.distinct().collect(Collectors.toList());
|
||||
}
|
||||
|
||||
static void ensureSetup() {
|
||||
// do nothing - this is only called to trigger the static initializer
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@ import java.util.regex.Matcher;
|
|||
import java.util.regex.Pattern;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
final class ReflectionUtil {
|
||||
public final class ReflectionUtil {
|
||||
private static final String SERVER_VERSION = getServerVersion();
|
||||
|
||||
private static String getServerVersion() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue