diff --git a/common/api/src/main/java/com/dfsek/terra/api/cloud/RegistryArgument.java b/common/api/src/main/java/com/dfsek/terra/api/cloud/RegistryArgument.java new file mode 100644 index 000000000..0ade1d98d --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/cloud/RegistryArgument.java @@ -0,0 +1,117 @@ +package com.dfsek.terra.api.cloud; + +import cloud.commandframework.ArgumentDescription; +import cloud.commandframework.arguments.CommandArgument; +import cloud.commandframework.arguments.parser.ArgumentParseResult; +import cloud.commandframework.arguments.parser.ArgumentParser; +import cloud.commandframework.arguments.standard.EnumArgument; + +import cloud.commandframework.context.CommandContext; + +import cloud.commandframework.exceptions.parsing.NoInputProvidedException; + +import com.dfsek.terra.api.registry.Registry; + +import io.leangen.geantyref.TypeToken; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; +import java.util.Queue; +import java.util.function.BiFunction; + + +/** + * An argument which recieves values from a registry. + * + * @param + */ +public class RegistryArgument extends CommandArgument { + + public RegistryArgument(Registry registry, + Class registryClass, + boolean required, + @NonNull String name, + @NonNull String defaultValue, + @Nullable BiFunction, String, List> suggestionsProvider, + @NonNull ArgumentDescription defaultDescription) { + super(required, name, new RegistryParser<>(registry), defaultValue, registryClass, suggestionsProvider, defaultDescription); + } + + public static Builder newBuilder(Registry registry, Class clazz, String name) { + return new Builder<>(clazz, name, registry); + } + + public static RegistryArgument of(Registry registry, Class registryClass, String name) { + return RegistryArgument.newBuilder(registry, registryClass, name).build(); + } + + public static final class Builder extends CommandArgument.Builder { + + private final Registry registry; + + private final Class registryType; + + + private Builder(@NonNull Class valueType, @NonNull String name, Registry registry) { + super(valueType, name); + this.registry = registry; + this.registryType = valueType; + } + + @Override + public @NonNull RegistryArgument<@NonNull C, @NonNull R> build() { + return new RegistryArgument<>(registry, registryType, + this.isRequired(), + this.getName(), + this.getDefaultValue(), + this.getSuggestionsProvider(), + this.getDefaultDescription() + ); + } + } + + + public static final class RegistryParser implements ArgumentParser { + + private final Registry registry; + + public RegistryParser(Registry registry) { + this.registry = registry; + } + + + @Override + public @NonNull ArgumentParseResult parse( + final @NonNull CommandContext commandContext, + final @NonNull Queue<@NonNull String> inputQueue + ) { + final String input = inputQueue.peek(); + if(input == null) { + return ArgumentParseResult.failure(new NoInputProvidedException( + EnumArgument.EnumParser.class, + commandContext + )); + } + + if(registry.contains(input)) return ArgumentParseResult.success(registry.get(input)); + + return ArgumentParseResult.failure(new IllegalArgumentException(input)); + } + + @Override + public @NonNull List<@NonNull String> suggestions( + @NotNull CommandContext commandContext, + final @NonNull String input) { + return new ArrayList<>(registry.keys()); + } + + @Override + public boolean isContextFree() { + return true; + } + + } +}