brigadier: Allow specifying a custom brigadier suggestions provider
This commit is contained in:
parent
0af44e2406
commit
98aea50d3c
3 changed files with 315 additions and 44 deletions
|
|
@ -0,0 +1,125 @@
|
||||||
|
//
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Copyright (c) 2020 Alexander Söderberg & Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
package cloud.commandframework.brigadier;
|
||||||
|
|
||||||
|
import cloud.commandframework.arguments.parser.ArgumentParser;
|
||||||
|
import com.mojang.brigadier.arguments.ArgumentType;
|
||||||
|
import com.mojang.brigadier.suggestion.SuggestionProvider;
|
||||||
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import static java.util.Objects.requireNonNull;
|
||||||
|
|
||||||
|
final class BrigadierMapping<C, K extends ArgumentParser<C, ?>, S> {
|
||||||
|
private final boolean cloudSuggestions;
|
||||||
|
private final BrigadierMappingBuilder.@Nullable SuggestionProviderSupplier<K, S> suggestionsOverride;
|
||||||
|
private final @Nullable Function<K, ? extends ArgumentType<?>> mapper;
|
||||||
|
|
||||||
|
BrigadierMapping(
|
||||||
|
final boolean cloudSuggestions,
|
||||||
|
final BrigadierMappingBuilder.@Nullable SuggestionProviderSupplier<K, S> suggestionsOverride,
|
||||||
|
final @Nullable Function<K, ? extends ArgumentType<?>> mapper
|
||||||
|
) {
|
||||||
|
this.cloudSuggestions = cloudSuggestions;
|
||||||
|
this.suggestionsOverride = suggestionsOverride;
|
||||||
|
this.mapper = mapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
public @Nullable Function<K, ? extends ArgumentType<?>> getMapper() {
|
||||||
|
return this.mapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NonNull BrigadierMapping<C, K, S> withNativeSuggestions(final boolean nativeSuggestions) {
|
||||||
|
if (nativeSuggestions && this.cloudSuggestions) {
|
||||||
|
return new BrigadierMapping<>(false, this.suggestionsOverride, this.mapper);
|
||||||
|
} else if (!nativeSuggestions && !this.cloudSuggestions) {
|
||||||
|
return new BrigadierMapping<>(true, this.suggestionsOverride, this.mapper);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public @Nullable SuggestionProvider<S> makeSuggestionProvider(final K commandArgument) {
|
||||||
|
if (this.cloudSuggestions) {
|
||||||
|
return CloudBrigadierManager.delegateSuggestions();
|
||||||
|
}
|
||||||
|
return this.suggestionsOverride == null
|
||||||
|
? null
|
||||||
|
: (SuggestionProvider<S>) this.suggestionsOverride.provide(commandArgument, CloudBrigadierManager.delegateSuggestions());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static final class BuilderImpl<C, K extends ArgumentParser<C, ?>, S> implements BrigadierMappingBuilder<K, S> {
|
||||||
|
private Function<K, ? extends ArgumentType<?>> mapper;
|
||||||
|
private boolean cloudSuggestions = false;
|
||||||
|
private SuggestionProviderSupplier<K, S> suggestionsOverride;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BrigadierMappingBuilder<K, S> toConstant(final ArgumentType<?> constant) {
|
||||||
|
return this.to(parser -> constant);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BrigadierMappingBuilder<K, S> to(final Function<K, ? extends ArgumentType<?>> mapper) {
|
||||||
|
this.mapper = mapper;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BrigadierMappingBuilder<K, S> nativeSuggestions() {
|
||||||
|
this.cloudSuggestions = false;
|
||||||
|
this.suggestionsOverride = null;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BrigadierMappingBuilder<K, S> cloudSuggestions() {
|
||||||
|
this.cloudSuggestions = true;
|
||||||
|
this.suggestionsOverride = null;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BrigadierMappingBuilder<K, S> suggestedByConstant(final SuggestionProvider<S> provider) {
|
||||||
|
BrigadierMappingBuilder.super.suggestedByConstant(provider);
|
||||||
|
this.cloudSuggestions = false;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BrigadierMappingBuilder<K, S> suggestedBy(final SuggestionProviderSupplier<K, S> provider) {
|
||||||
|
this.suggestionsOverride = requireNonNull(provider, "provider");
|
||||||
|
this.cloudSuggestions = false;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BrigadierMapping<C, K, S> build() {
|
||||||
|
return new BrigadierMapping<>(this.cloudSuggestions, this.suggestionsOverride, this.mapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,113 @@
|
||||||
|
//
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Copyright (c) 2020 Alexander Söderberg & Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
package cloud.commandframework.brigadier;
|
||||||
|
|
||||||
|
import cloud.commandframework.arguments.parser.ArgumentParser;
|
||||||
|
import com.mojang.brigadier.arguments.ArgumentType;
|
||||||
|
import com.mojang.brigadier.suggestion.SuggestionProvider;
|
||||||
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import static java.util.Objects.requireNonNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A builder for a mapping between a Cloud parser and a Brigadier {@link com.mojang.brigadier.arguments.ArgumentType}
|
||||||
|
*
|
||||||
|
* @param <K> the Cloud argument parser type
|
||||||
|
* @param <S> the brigadier-native sender type
|
||||||
|
*/
|
||||||
|
public interface BrigadierMappingBuilder<K extends ArgumentParser<?, ?>, S> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map the argument type parser to a constant Brigadier argument type instance.
|
||||||
|
*
|
||||||
|
* @param constant the argument type
|
||||||
|
* @return this builder
|
||||||
|
*/
|
||||||
|
BrigadierMappingBuilder<K, S> toConstant(ArgumentType<?> constant);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map the cloud argument parser to a variable Brigadier {@link ArgumentType}.
|
||||||
|
*
|
||||||
|
* @param mapper the mapper
|
||||||
|
* @return this builder
|
||||||
|
*/
|
||||||
|
BrigadierMappingBuilder<K, S> to(Function<K, ? extends ArgumentType<?>> mapper);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use the default brigadier suggestions for this argument type.
|
||||||
|
*
|
||||||
|
* <p>This is the default option if a mapped type is specified.</p>
|
||||||
|
*
|
||||||
|
* @return this builder
|
||||||
|
*/
|
||||||
|
BrigadierMappingBuilder<K, S> nativeSuggestions();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use the suggestions from Cloud's parser for this argument type.
|
||||||
|
*
|
||||||
|
* <p>This is not the default suggestions configuration.</p>
|
||||||
|
*
|
||||||
|
* <p>Any previously set suggestion provider suppliers will not be used.</p>
|
||||||
|
*
|
||||||
|
* @return this builder
|
||||||
|
*/
|
||||||
|
BrigadierMappingBuilder<K, S> cloudSuggestions();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use a custom Brigadier suggestion provider for this parser.
|
||||||
|
*
|
||||||
|
* @param provider the suggestions provider
|
||||||
|
* @return this builder
|
||||||
|
*/
|
||||||
|
default BrigadierMappingBuilder<K, S> suggestedByConstant(final SuggestionProvider<S> provider) {
|
||||||
|
requireNonNull(provider, "provider");
|
||||||
|
return this.suggestedBy((argument, useCloud) -> provider);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use a custom Brigadier suggestion provider for this parser.
|
||||||
|
*
|
||||||
|
* @param provider the suggestions provider
|
||||||
|
* @return this builder
|
||||||
|
*/
|
||||||
|
BrigadierMappingBuilder<K, S> suggestedBy(SuggestionProviderSupplier<K, S> provider);
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
interface SuggestionProviderSupplier<K extends ArgumentParser<?, ?>, S> {
|
||||||
|
/**
|
||||||
|
* Create a new suggestion provider based on the provided argument.
|
||||||
|
*
|
||||||
|
* @param argument Argument to create a specialized provider for
|
||||||
|
* @param useCloud A provider that can be returned to ask the server to use cloud suggestions
|
||||||
|
* @return A new provider, or {@code null} to use the default value for the mapped argument type
|
||||||
|
*/
|
||||||
|
@Nullable SuggestionProvider<? super S> provide(@NonNull K argument, SuggestionProvider<S> useCloud);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -70,6 +70,7 @@ import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.function.BiPredicate;
|
import java.util.function.BiPredicate;
|
||||||
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
@ -88,13 +89,25 @@ import java.util.stream.Stream;
|
||||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||||
public final class CloudBrigadierManager<C, S> {
|
public final class CloudBrigadierManager<C, S> {
|
||||||
|
|
||||||
private final Map<Class<?>, Pair<Function<? extends ArgumentParser<C, ?>, ? extends ArgumentType<?>>, Boolean>> mappers;
|
private static final SuggestionProvider<?> DELEGATE_TO_CLOUD = (c, b) -> b.buildFuture();
|
||||||
|
|
||||||
|
private final Map<Class<?>, BrigadierMapping<C, ?, S>> mappers;
|
||||||
private final Map<@NonNull Class<?>, @NonNull Supplier<@Nullable ArgumentType<?>>> defaultArgumentTypeSuppliers;
|
private final Map<@NonNull Class<?>, @NonNull Supplier<@Nullable ArgumentType<?>>> defaultArgumentTypeSuppliers;
|
||||||
private final Supplier<CommandContext<C>> dummyContextProvider;
|
private final Supplier<CommandContext<C>> dummyContextProvider;
|
||||||
private final CommandManager<C> commandManager;
|
private final CommandManager<C> commandManager;
|
||||||
private Function<S, C> brigadierCommandSenderMapper;
|
private Function<S, C> brigadierCommandSenderMapper;
|
||||||
private Function<C, S> backwardsBrigadierCommandSenderMapper;
|
private Function<C, S> backwardsBrigadierCommandSenderMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A sentinel value for declaring that suggestions should be delegated to cloud.
|
||||||
|
*
|
||||||
|
* @param <T> the sender type
|
||||||
|
* @return a singleton sentinel suggestion provider
|
||||||
|
*/
|
||||||
|
static <T> SuggestionProvider<T> delegateSuggestions() {
|
||||||
|
return (SuggestionProvider<T>) DELEGATE_TO_CLOUD;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new cloud brigadier manager
|
* Create a new cloud brigadier manager
|
||||||
*
|
*
|
||||||
|
|
@ -123,7 +136,7 @@ public final class CloudBrigadierManager<C, S> {
|
||||||
private void registerInternalMappings() {
|
private void registerInternalMappings() {
|
||||||
/* Map byte, short and int to IntegerArgumentType */
|
/* Map byte, short and int to IntegerArgumentType */
|
||||||
this.registerMapping(new TypeToken<ByteArgument.ByteParser<C>>() {
|
this.registerMapping(new TypeToken<ByteArgument.ByteParser<C>>() {
|
||||||
}, true, argument -> {
|
}, builder -> builder.to(argument -> {
|
||||||
final boolean hasMin = argument.getMin() != Byte.MIN_VALUE;
|
final boolean hasMin = argument.getMin() != Byte.MIN_VALUE;
|
||||||
final boolean hasMax = argument.getMax() != Byte.MAX_VALUE;
|
final boolean hasMax = argument.getMax() != Byte.MAX_VALUE;
|
||||||
if (hasMin) {
|
if (hasMin) {
|
||||||
|
|
@ -133,9 +146,9 @@ public final class CloudBrigadierManager<C, S> {
|
||||||
} else {
|
} else {
|
||||||
return IntegerArgumentType.integer();
|
return IntegerArgumentType.integer();
|
||||||
}
|
}
|
||||||
});
|
}));
|
||||||
this.registerMapping(new TypeToken<ShortArgument.ShortParser<C>>() {
|
this.registerMapping(new TypeToken<ShortArgument.ShortParser<C>>() {
|
||||||
}, true, argument -> {
|
}, builder -> builder.to(argument -> {
|
||||||
final boolean hasMin = argument.getMin() != Short.MIN_VALUE;
|
final boolean hasMin = argument.getMin() != Short.MIN_VALUE;
|
||||||
final boolean hasMax = argument.getMax() != Short.MAX_VALUE;
|
final boolean hasMax = argument.getMax() != Short.MAX_VALUE;
|
||||||
if (hasMin) {
|
if (hasMin) {
|
||||||
|
|
@ -145,9 +158,9 @@ public final class CloudBrigadierManager<C, S> {
|
||||||
} else {
|
} else {
|
||||||
return IntegerArgumentType.integer();
|
return IntegerArgumentType.integer();
|
||||||
}
|
}
|
||||||
});
|
}));
|
||||||
this.registerMapping(new TypeToken<IntegerArgument.IntegerParser<C>>() {
|
this.registerMapping(new TypeToken<IntegerArgument.IntegerParser<C>>() {
|
||||||
}, true, argument -> {
|
}, builder -> builder.to(argument -> {
|
||||||
final boolean hasMin = argument.getMin() != Integer.MIN_VALUE;
|
final boolean hasMin = argument.getMin() != Integer.MIN_VALUE;
|
||||||
final boolean hasMax = argument.getMax() != Integer.MAX_VALUE;
|
final boolean hasMax = argument.getMax() != Integer.MAX_VALUE;
|
||||||
if (hasMin) {
|
if (hasMin) {
|
||||||
|
|
@ -157,10 +170,10 @@ public final class CloudBrigadierManager<C, S> {
|
||||||
} else {
|
} else {
|
||||||
return IntegerArgumentType.integer();
|
return IntegerArgumentType.integer();
|
||||||
}
|
}
|
||||||
});
|
}));
|
||||||
/* Map float to FloatArgumentType */
|
/* Map float to FloatArgumentType */
|
||||||
this.registerMapping(new TypeToken<FloatArgument.FloatParser<C>>() {
|
this.registerMapping(new TypeToken<FloatArgument.FloatParser<C>>() {
|
||||||
}, true, argument -> {
|
}, builder -> builder.to(argument -> {
|
||||||
final boolean hasMin = argument.getMin() != Float.NEGATIVE_INFINITY;
|
final boolean hasMin = argument.getMin() != Float.NEGATIVE_INFINITY;
|
||||||
final boolean hasMax = argument.getMax() != Float.POSITIVE_INFINITY;
|
final boolean hasMax = argument.getMax() != Float.POSITIVE_INFINITY;
|
||||||
if (hasMin) {
|
if (hasMin) {
|
||||||
|
|
@ -170,10 +183,10 @@ public final class CloudBrigadierManager<C, S> {
|
||||||
} else {
|
} else {
|
||||||
return FloatArgumentType.floatArg();
|
return FloatArgumentType.floatArg();
|
||||||
}
|
}
|
||||||
});
|
}));
|
||||||
/* Map double to DoubleArgumentType */
|
/* Map double to DoubleArgumentType */
|
||||||
this.registerMapping(new TypeToken<DoubleArgument.DoubleParser<C>>() {
|
this.registerMapping(new TypeToken<DoubleArgument.DoubleParser<C>>() {
|
||||||
}, true, argument -> {
|
}, builder -> builder.to(argument -> {
|
||||||
final boolean hasMin = argument.getMin() != Double.NEGATIVE_INFINITY;
|
final boolean hasMin = argument.getMin() != Double.NEGATIVE_INFINITY;
|
||||||
final boolean hasMax = argument.getMax() != Double.POSITIVE_INFINITY;
|
final boolean hasMax = argument.getMax() != Double.POSITIVE_INFINITY;
|
||||||
if (hasMin) {
|
if (hasMin) {
|
||||||
|
|
@ -183,13 +196,13 @@ public final class CloudBrigadierManager<C, S> {
|
||||||
} else {
|
} else {
|
||||||
return DoubleArgumentType.doubleArg();
|
return DoubleArgumentType.doubleArg();
|
||||||
}
|
}
|
||||||
});
|
}));
|
||||||
/* Map boolean to BoolArgumentType */
|
/* Map boolean to BoolArgumentType */
|
||||||
this.registerMapping(new TypeToken<BooleanArgument.BooleanParser<C>>() {
|
this.registerMapping(new TypeToken<BooleanArgument.BooleanParser<C>>() {
|
||||||
}, true, argument -> BoolArgumentType.bool());
|
}, builder -> builder.toConstant(BoolArgumentType.bool()));
|
||||||
/* Map String properly to StringArgumentType */
|
/* Map String properly to StringArgumentType */
|
||||||
this.registerMapping(new TypeToken<StringArgument.StringParser<C>>() {
|
this.registerMapping(new TypeToken<StringArgument.StringParser<C>>() {
|
||||||
}, false, argument -> {
|
}, builder -> builder.cloudSuggestions().to(argument -> {
|
||||||
switch (argument.getStringMode()) {
|
switch (argument.getStringMode()) {
|
||||||
case QUOTED:
|
case QUOTED:
|
||||||
return StringArgumentType.string();
|
return StringArgumentType.string();
|
||||||
|
|
@ -198,21 +211,16 @@ public final class CloudBrigadierManager<C, S> {
|
||||||
default:
|
default:
|
||||||
return StringArgumentType.word();
|
return StringArgumentType.word();
|
||||||
}
|
}
|
||||||
});
|
}));
|
||||||
/* Map flags to a greedy string */
|
/* Map flags to a greedy string */
|
||||||
this.registerMapping(new TypeToken<FlagArgument.FlagArgumentParser<C>>() {
|
this.registerMapping(new TypeToken<FlagArgument.FlagArgumentParser<C>>() {
|
||||||
}, false, argument -> StringArgumentType.greedyString());
|
}, builder -> builder.cloudSuggestions().toConstant(StringArgumentType.greedyString()));
|
||||||
/* Map String[] to a greedy string */
|
/* Map String[] to a greedy string */
|
||||||
this.registerMapping(new TypeToken<StringArrayArgument.StringArrayParser<C>>() {
|
this.registerMapping(new TypeToken<StringArrayArgument.StringArrayParser<C>>() {
|
||||||
}, false, argument -> StringArgumentType.greedyString());
|
}, builder -> builder.cloudSuggestions().toConstant(StringArgumentType.greedyString()));
|
||||||
/* Map wrapped parsers to their native types */
|
/* Map wrapped parsers to their native types */
|
||||||
this.registerWrapperMapping();
|
this.registerMapping(new TypeToken<WrappedBrigadierParser<C, ?>>() {
|
||||||
}
|
}, builder -> builder.to(WrappedBrigadierParser::getNativeArgument));
|
||||||
|
|
||||||
private <O> void registerWrapperMapping() {
|
|
||||||
/* a small hack to make type inference work properly... O doesn't behave as a wildcard */
|
|
||||||
this.registerMapping(new TypeToken<WrappedBrigadierParser<C, O>>() {
|
|
||||||
}, true, WrappedBrigadierParser::getNativeArgument);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -301,7 +309,7 @@ public final class CloudBrigadierManager<C, S> {
|
||||||
final @NonNull TypeToken<K> argumentType,
|
final @NonNull TypeToken<K> argumentType,
|
||||||
final boolean nativeSuggestions
|
final boolean nativeSuggestions
|
||||||
) throws IllegalArgumentException {
|
) throws IllegalArgumentException {
|
||||||
final Pair<Function<? extends ArgumentParser<C, ?>, ? extends ArgumentType<?>>, Boolean> pair = this.mappers.get(
|
final BrigadierMapping<C, ?, S> pair = this.mappers.get(
|
||||||
GenericTypeReflector.erase(argumentType.getType())
|
GenericTypeReflector.erase(argumentType.getType())
|
||||||
);
|
);
|
||||||
if (pair == null) {
|
if (pair == null) {
|
||||||
|
|
@ -313,27 +321,51 @@ public final class CloudBrigadierManager<C, S> {
|
||||||
}
|
}
|
||||||
this.mappers.put(
|
this.mappers.put(
|
||||||
GenericTypeReflector.erase(argumentType.getType()),
|
GenericTypeReflector.erase(argumentType.getType()),
|
||||||
Pair.of(pair.getFirst(), nativeSuggestions)
|
pair.withNativeSuggestions(nativeSuggestions)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a cloud-Brigadier mapping
|
* Register a cloud-Brigadier mapping
|
||||||
*
|
*
|
||||||
* @param argumentType cloud argument type
|
* @param argumentType cloud argument parser type
|
||||||
* @param nativeSuggestions Whether or not Brigadier suggestions should be used
|
* @param nativeSuggestions Whether or not Brigadier suggestions should be used
|
||||||
* @param mapper mapper function
|
* @param mapper mapper function
|
||||||
* @param <T> cloud argument value type
|
* @param <T> cloud argument value type
|
||||||
* @param <K> cloud argument type
|
* @param <K> cloud argument type
|
||||||
* @param <O> Brigadier argument type value
|
* @param <O> Brigadier argument type value
|
||||||
|
* @deprecated for removal since 1.4.0, use {@link #registerMapping(TypeToken, Consumer)} instead.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public <T, K extends ArgumentParser<C, T>, O> void registerMapping(
|
public <T, K extends ArgumentParser<C, T>, O> void registerMapping(
|
||||||
final @NonNull TypeToken<K> argumentType,
|
final @NonNull TypeToken<K> argumentType,
|
||||||
final boolean nativeSuggestions,
|
final boolean nativeSuggestions,
|
||||||
final @NonNull Function<@NonNull ? extends K,
|
final @NonNull Function<@NonNull ? extends K,
|
||||||
@NonNull ? extends ArgumentType<O>> mapper
|
@NonNull ? extends ArgumentType<O>> mapper
|
||||||
) {
|
) {
|
||||||
this.mappers.put(GenericTypeReflector.erase(argumentType.getType()), Pair.of(mapper, nativeSuggestions));
|
this.registerMapping(argumentType, builder -> {
|
||||||
|
builder.to((Function<K, ? extends ArgumentType<?>>) mapper);
|
||||||
|
if (!nativeSuggestions) {
|
||||||
|
builder.cloudSuggestions();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a cloud-Brigadier mapping.
|
||||||
|
*
|
||||||
|
* @param parserType The cloud argument parser type
|
||||||
|
* @param configurer a callback that will configure the mapping attributes
|
||||||
|
* @param <K> cloud argument parser type
|
||||||
|
* @since 1.4.0
|
||||||
|
*/
|
||||||
|
public <K extends ArgumentParser<C, ?>> void registerMapping(final @NonNull TypeToken<K> parserType,
|
||||||
|
final Consumer<BrigadierMappingBuilder<K, S>> configurer) {
|
||||||
|
final BrigadierMapping.BuilderImpl<C, K, S> builder = new BrigadierMapping.BuilderImpl<>();
|
||||||
|
configurer.accept(builder);
|
||||||
|
this.mappers.put(GenericTypeReflector.erase(parserType.getType()), builder.build());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -350,23 +382,24 @@ public final class CloudBrigadierManager<C, S> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("all")
|
@SuppressWarnings("all")
|
||||||
private <T, K extends ArgumentParser<?, ?>> @Nullable Pair<@NonNull ArgumentType<?>, @NonNull Boolean> getArgument(
|
private <T, K extends ArgumentParser<C, ?>> @Nullable Pair<@NonNull ArgumentType<?>, @Nullable SuggestionProvider<S>> getArgument(
|
||||||
final @NonNull TypeToken<?> valueType,
|
final @NonNull TypeToken<?> valueType,
|
||||||
final @NonNull TypeToken<T> argumentType,
|
final @NonNull TypeToken<T> argumentType,
|
||||||
final @NonNull K argument
|
final @NonNull K argument
|
||||||
) {
|
) {
|
||||||
final ArgumentParser<C, ?> commandArgument = (ArgumentParser<C, ?>) argument;
|
final ArgumentParser<C, ?> commandArgument = (ArgumentParser<C, ?>) argument;
|
||||||
final Pair pair = this.mappers.get(GenericTypeReflector.erase(argumentType.getType()));
|
final BrigadierMapping<C, K, S> mapping = (BrigadierMapping<C, K, S>) this.mappers
|
||||||
if (pair == null || pair.getFirst() == null) {
|
.get(GenericTypeReflector.erase(argumentType.getType()));
|
||||||
|
if (mapping == null || mapping.getMapper() == null) {
|
||||||
return this.createDefaultMapper(valueType);
|
return this.createDefaultMapper(valueType);
|
||||||
}
|
}
|
||||||
return Pair.of(
|
return Pair.of(
|
||||||
(ArgumentType<?>) ((Function) pair.getFirst()).apply(commandArgument),
|
(ArgumentType<?>) ((Function) mapping.getMapper()).apply(commandArgument),
|
||||||
(boolean) pair.getSecond()
|
mapping.makeSuggestionProvider(argument)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T, K extends ArgumentParser<C, T>> @NonNull Pair<@NonNull ArgumentType<?>, @NonNull Boolean> createDefaultMapper(
|
private @NonNull Pair<@NonNull ArgumentType<?>, @Nullable SuggestionProvider<S>> createDefaultMapper(
|
||||||
final @NonNull TypeToken<?> clazz
|
final @NonNull TypeToken<?> clazz
|
||||||
) {
|
) {
|
||||||
final Supplier<ArgumentType<?>> argumentTypeSupplier = this.defaultArgumentTypeSuppliers
|
final Supplier<ArgumentType<?>> argumentTypeSupplier = this.defaultArgumentTypeSuppliers
|
||||||
|
|
@ -378,9 +411,9 @@ public final class CloudBrigadierManager<C, S> {
|
||||||
defaultType = null;
|
defaultType = null;
|
||||||
}
|
}
|
||||||
if (defaultType != null) {
|
if (defaultType != null) {
|
||||||
return Pair.of(argumentTypeSupplier.get(), true);
|
return Pair.of(argumentTypeSupplier.get(), null);
|
||||||
}
|
}
|
||||||
return Pair.of(StringArgumentType.string(), false);
|
return Pair.of(StringArgumentType.string(), delegateSuggestions());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -486,12 +519,13 @@ public final class CloudBrigadierManager<C, S> {
|
||||||
|
|
||||||
for (int i = parsers.length - 1; i >= 0; i--) {
|
for (int i = parsers.length - 1; i >= 0; i--) {
|
||||||
@SuppressWarnings("unchecked") final ArgumentParser<C, ?> parser = (ArgumentParser<C, ?>) parsers[i];
|
@SuppressWarnings("unchecked") final ArgumentParser<C, ?> parser = (ArgumentParser<C, ?>) parsers[i];
|
||||||
final Pair<ArgumentType<?>, Boolean> pair = this.getArgument(
|
final Pair<ArgumentType<?>, SuggestionProvider<S>> pair = this.getArgument(
|
||||||
TypeToken.get((Class<?>) types[i]),
|
TypeToken.get((Class<?>) types[i]),
|
||||||
TypeToken.get(parser.getClass()),
|
TypeToken.get(parser.getClass()),
|
||||||
parser
|
parser
|
||||||
);
|
);
|
||||||
final SuggestionProvider<S> provider = pair.getSecond() ? null : suggestionProvider;
|
final SuggestionProvider<S> provider = pair.getSecond() == delegateSuggestions() ? suggestionProvider
|
||||||
|
: pair.getSecond();
|
||||||
|
|
||||||
final ArgumentBuilder<S, ?> fragmentBuilder = RequiredArgumentBuilder
|
final ArgumentBuilder<S, ?> fragmentBuilder = RequiredArgumentBuilder
|
||||||
.<S, Object>argument((String) names[i], (ArgumentType<Object>) pair.getFirst())
|
.<S, Object>argument((String) names[i], (ArgumentType<Object>) pair.getFirst())
|
||||||
|
|
@ -523,7 +557,7 @@ public final class CloudBrigadierManager<C, S> {
|
||||||
|
|
||||||
return argumentBuilders[0];
|
return argumentBuilders[0];
|
||||||
}
|
}
|
||||||
ArgumentBuilder<S, ?> argumentBuilder;
|
final ArgumentBuilder<S, ?> argumentBuilder;
|
||||||
if (root.getValue() instanceof StaticArgument) {
|
if (root.getValue() instanceof StaticArgument) {
|
||||||
argumentBuilder = LiteralArgumentBuilder.<S>literal(root.getValue().getName())
|
argumentBuilder = LiteralArgumentBuilder.<S>literal(root.getValue().getName())
|
||||||
.requires(sender -> permissionChecker.test(sender, (CommandPermission) root.getNodeMeta()
|
.requires(sender -> permissionChecker.test(sender, (CommandPermission) root.getNodeMeta()
|
||||||
|
|
@ -534,19 +568,18 @@ public final class CloudBrigadierManager<C, S> {
|
||||||
.executes(executor);
|
.executes(executor);
|
||||||
} else {
|
} else {
|
||||||
// Register argument
|
// Register argument
|
||||||
final Pair<ArgumentType<?>, Boolean> pair = this.getArgument(
|
final Pair<ArgumentType<?>, SuggestionProvider<S>> pair = this.getArgument(
|
||||||
root.getValue().getValueType(),
|
root.getValue().getValueType(),
|
||||||
TypeToken.get(root.getValue().getParser().getClass()),
|
TypeToken.get(root.getValue().getParser().getClass()),
|
||||||
root.getValue().getParser()
|
root.getValue().getParser()
|
||||||
);
|
);
|
||||||
final SuggestionProvider<S> provider = pair.getSecond()
|
final SuggestionProvider<S> provider = pair.getSecond() == delegateSuggestions()
|
||||||
? null
|
? (context, builder) -> this.buildSuggestions(
|
||||||
: (context, builder) -> this.buildSuggestions(
|
|
||||||
context,
|
context,
|
||||||
root.getParent(),
|
root.getParent(),
|
||||||
root.getValue(),
|
root.getValue(),
|
||||||
builder
|
builder
|
||||||
);
|
) : pair.getSecond();
|
||||||
argumentBuilder = RequiredArgumentBuilder
|
argumentBuilder = RequiredArgumentBuilder
|
||||||
.<S, Object>argument(root.getValue().getName(), (ArgumentType<Object>) pair.getFirst())
|
.<S, Object>argument(root.getValue().getName(), (ArgumentType<Object>) pair.getFirst())
|
||||||
.suggests(provider)
|
.suggests(provider)
|
||||||
|
|
@ -595,7 +628,7 @@ public final class CloudBrigadierManager<C, S> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remove namespace */
|
/* Remove namespace */
|
||||||
String leading = command.split(" ")[0];
|
final String leading = command.split(" ")[0];
|
||||||
if (leading.contains(":")) {
|
if (leading.contains(":")) {
|
||||||
command = command.substring(leading.split(":")[0].length() + 1);
|
command = command.substring(leading.split(":")[0].length() + 1);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue