Rewrite Bukkit entity selector arguments using WrappedBrigadierParser instead of Bukkit API

- Proper handling of spaces
- Possible to use built-in minecraft translations for brigadier exceptions
- Fixes suggestions on Paper in combination with their option to fix tag selector suggestions
- Added option to fail parse when the result collection is empty
This commit is contained in:
Jason Penilla 2022-10-26 10:45:30 -07:00 committed by Jason
parent 09a66cef95
commit 2f34437398
12 changed files with 908 additions and 290 deletions

View file

@ -39,7 +39,9 @@ import java.util.List;
import java.util.Queue;
import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier;
import org.apiguardian.api.API;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import static java.util.Objects.requireNonNull;
@ -56,6 +58,7 @@ public final class WrappedBrigadierParser<C, T> implements ArgumentParser<C, T>
private final Supplier<ArgumentType<T>> nativeType;
private final int expectedArgumentCount;
private final @Nullable ParseFunction<T> parse;
/**
* Create an argument parser based on a brigadier command.
@ -101,10 +104,28 @@ public final class WrappedBrigadierParser<C, T> implements ArgumentParser<C, T>
public WrappedBrigadierParser(
final Supplier<ArgumentType<T>> nativeType,
final int expectedArgumentCount
) {
this(nativeType, expectedArgumentCount, null);
}
/**
* Create an argument parser based on a brigadier command.
*
* @param nativeType the native command type provider, calculated lazily
* @param expectedArgumentCount the number of arguments the brigadier type is expected to consume
* @param parse special function to replace {@link ArgumentType#parse(StringReader)} (for CraftBukkit weirdness)
* @since 1.8.0
*/
@API(status = API.Status.STABLE, since = "1.8.0")
public WrappedBrigadierParser(
final Supplier<ArgumentType<T>> nativeType,
final int expectedArgumentCount,
final @Nullable ParseFunction<T> parse
) {
requireNonNull(nativeType, "brigadierType");
this.nativeType = nativeType;
this.expectedArgumentCount = expectedArgumentCount;
this.parse = parse;
}
/**
@ -135,7 +156,10 @@ public final class WrappedBrigadierParser<C, T> implements ArgumentParser<C, T>
// Then try to parse
try {
return ArgumentParseResult.success(this.nativeType.get().parse(reader));
final T result = this.parse != null
? this.parse.apply(this.nativeType.get(), reader)
: this.nativeType.get().parse(reader);
return ArgumentParseResult.success(result);
} catch (final CommandSyntaxException ex) {
return ArgumentParseResult.failure(ex);
} finally {
@ -191,4 +215,24 @@ public final class WrappedBrigadierParser<C, T> implements ArgumentParser<C, T>
public int getRequestedArgumentCount() {
return this.expectedArgumentCount;
}
/**
* Function which can call {@link ArgumentType#parse(StringReader)} or another method.
*
* @param <T> result type
* @since 1.8.0
*/
@API(status = API.Status.STABLE, since = "1.8.0")
@FunctionalInterface
public interface ParseFunction<T> {
/**
* Apply the parse function.
*
* @param type argument type
* @param reader string reader
* @return result
* @throws CommandSyntaxException on failure
*/
T apply(ArgumentType<T> type, StringReader reader) throws CommandSyntaxException;
}
}