online suggestions via suggester

This commit is contained in:
gnembon committed 2020-11-13 06:30:55 -04:00
1 parent 5f9df1239a
commit bc99b081ca
2 files changed
+72 -34

No files matched your search

@@ -2,11 +2,13 @@ package carpet.script.command;
import carpet.fakes.BlockStateArgumentInterface;
import carpet.script.CarpetScriptHost;
import carpet.script.argument.FunctionArgument;
import carpet.script.exception.InternalExpressionException;
import carpet.script.value.BlockValue;
import carpet.script.value.EntityValue;
import carpet.script.value.FormattedTextValue;
import carpet.script.value.ListValue;
import carpet.script.value.MapValue;
import carpet.script.value.NBTSerializableValue;
import carpet.script.value.NumericValue;
import carpet.script.value.StringValue;
@@ -22,11 +24,14 @@ import com.mojang.brigadier.arguments.LongArgumentType;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.context.ParsedCommandNode;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
import com.mojang.brigadier.suggestion.SuggestionProvider;
import com.mojang.brigadier.suggestion.Suggestions;
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import com.mojang.brigadier.tree.ArgumentCommandNode;
import com.mojang.brigadier.tree.CommandNode;
import net.minecraft.advancement.Advancement;
import net.minecraft.command.CommandSource;
import net.minecraft.command.argument.AngleArgumentType;
@@ -74,8 +79,10 @@ import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec2f;
import net.minecraft.util.registry.Registry;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -259,13 +266,15 @@ public abstract class CommandArgument
{
CommandArgument arg = getTypeForArgument(param, host);
if (arg.suggestionProvider != null) return argument(param, arg.getArgumentType()).suggests(arg.suggestionProvider);
return arg.needsMatching? argument(param, arg.getArgumentType()).suggests(arg::suggest) : argument(param, arg.getArgumentType());
return arg.needsMatching? argument(param, arg.getArgumentType()).suggests((c, b) -> arg.suggest(c, b, host)) : argument(param, arg.getArgumentType());
}
protected String suffix;
protected Collection<String> examples;
protected boolean needsMatching = false;
protected SuggestionProvider<ServerCommandSource> suggestionProvider;
protected FunctionArgument<Value> customSuggester;
protected CommandArgument(
String suffix,
@@ -292,7 +301,7 @@ public abstract class CommandArgument
return suffix;
}
public static CommandArgument buildFromConfig(String suffix, Map<String, Value> config)
public static CommandArgument buildFromConfig(String suffix, Map<String, Value> config, CarpetScriptHost host)
{
if (!config.containsKey("type"))
throw new InternalExpressionException("Custom types should at least specify the type");
@@ -300,15 +309,20 @@ public abstract class CommandArgument
if (!builtIns.containsKey(baseType))
throw new InternalExpressionException("Unknown base type: "+baseType);
CommandArgument variant = builtIns.get(baseType).builder().get();
variant.configure(config);
variant.configure(config, host);
variant.suffix = suffix;
return variant;
}
protected void configure(Map<String, Value> config)
protected void configure(Map<String, Value> config, CarpetScriptHost host)
{
if (config.containsKey("suggester"))
{
customSuggester = FunctionArgument.fromCommandSpec(host, config.get("suggester"));
}
if (config.containsKey("suggest"))
{
if (config.containsKey("suggester")) throw new InternalExpressionException("Attempted to provide 'suggest' list while 'suggester' is present");
Value suggestionValue = config.get("suggest");
if (!(suggestionValue instanceof ListValue)) throw new InternalExpressionException("Argument suggestions needs to be a list");
examples = ((ListValue) suggestionValue).getItems().stream()
@@ -316,34 +330,55 @@ public abstract class CommandArgument
.collect(Collectors.toSet());
if (!examples.isEmpty()) needsMatching = true;
}
};
}
public CompletableFuture<Suggestions> suggest(
CommandContext<ServerCommandSource> context,
SuggestionsBuilder suggestionsBuilder
)
SuggestionsBuilder suggestionsBuilder,
CarpetScriptHost host
) throws CommandSyntaxException
{
String prefix = suggestionsBuilder.getRemaining().toLowerCase(Locale.ROOT);
suggestFor(prefix).forEach(suggestionsBuilder::suggest);
suggestFor(context, prefix, host).forEach(suggestionsBuilder::suggest);
return suggestionsBuilder.buildFuture();
}
protected List<String> suggestFor(String prefix)
protected List<String> suggestFor(CommandContext<ServerCommandSource> context, String prefix, CarpetScriptHost host) throws CommandSyntaxException
{
return getOptions().stream().filter(s -> optionMatchesPrefix(prefix, s)).collect(Collectors.toList());
return getOptions(context, host).stream().filter(s -> optionMatchesPrefix(prefix, s)).collect(Collectors.toList());
}
protected Collection<String> getOptions()
protected Collection<String> getOptions(CommandContext<ServerCommandSource> context, CarpetScriptHost host) throws CommandSyntaxException
{
if (customSuggester != null)
{
Map<Value, Value> params = new HashMap<>();
for(ParsedCommandNode<ServerCommandSource> pnode : context.getNodes())
{
CommandNode<ServerCommandSource> node = pnode.getNode();
if (node instanceof ArgumentCommandNode)
{
params.put(StringValue.of(node.getName()), CommandArgument.getValue(context, node.getName(), host));
}
}
List<Value> args = new ArrayList<>(customSuggester.args.size()+1);
args.add(MapValue.wrap(params));
args.addAll(customSuggester.args);
Value response = host.handleCommand(context.getSource(), customSuggester.function, args);
if (!(response instanceof ListValue)) throw error("Custom suggester should return a list of options");
return ((ListValue) response).getItems().stream().map(Value::getString).collect(Collectors.toList());
}
if (needsMatching) return examples;
//return Lists.newArrayList("");
// better than nothing I guess
// nothing is such a bad default.
if (needsMatching) return examples;
return Collections.singletonList("... "+getTypeSuffix());
}
protected boolean optionMatchesPrefix(String prefix, String option)
{
//prefix = prefix.toLowerCase(Locale.ROOT);
//option = option.toLowerCase(Locale.ROOT);
for(int i = 0; !option.startsWith(prefix, i); ++i)
{
i = option.indexOf('_', i);
@@ -382,9 +417,9 @@ public abstract class CommandArgument
}
@Override
protected void configure(Map<String, Value> config)
protected void configure(Map<String, Value> config, CarpetScriptHost host)
{
super.configure(config);
super.configure(config, host);
caseSensitive = config.getOrDefault("case_sensitive", Value.FALSE).getBoolean();
if (config.containsKey("options"))
{
@@ -397,7 +432,10 @@ public abstract class CommandArgument
}
@Override
protected Collection<String> getOptions() { return validOptions.isEmpty()?super.getOptions():validOptions; }
protected Collection<String> getOptions(CommandContext<ServerCommandSource> context, CarpetScriptHost host) throws CommandSyntaxException
{
return validOptions.isEmpty()?super.getOptions(context, host):validOptions;
}
@Override
protected Supplier<CommandArgument> builder() { return WordArgument::new; }
@@ -446,9 +484,9 @@ public abstract class CommandArgument
}
@Override
protected void configure(Map<String, Value> config)
protected void configure(Map<String, Value> config, CarpetScriptHost host)
{
super.configure(config);
super.configure(config, host);
mustBeLoaded = config.getOrDefault("loaded", Value.FALSE).getBoolean();
}
@@ -481,9 +519,9 @@ public abstract class CommandArgument
}
@Override
protected void configure(Map<String, Value> config)
protected void configure(Map<String, Value> config, CarpetScriptHost host)
{
super.configure(config);
super.configure(config, host);
blockCentered = config.getOrDefault("block_centered", Value.TRUE).getBoolean();
}
@@ -529,9 +567,9 @@ public abstract class CommandArgument
}
@Override
protected void configure(Map<String, Value> config)
protected void configure(Map<String, Value> config, CarpetScriptHost host)
{
super.configure(config);
super.configure(config, host);
onlyFans = config.getOrDefault("players", Value.FALSE).getBoolean();
single = config.getOrDefault("single", Value.FALSE).getBoolean();
}
@@ -570,9 +608,9 @@ public abstract class CommandArgument
}
@Override
protected void configure(Map<String, Value> config)
protected void configure(Map<String, Value> config, CarpetScriptHost host)
{
super.configure(config);
super.configure(config, host);
single = config.getOrDefault("single", Value.FALSE).getBoolean();
}
@@ -611,9 +649,9 @@ public abstract class CommandArgument
}
@Override
protected void configure(Map<String, Value> config)
protected void configure(Map<String, Value> config, CarpetScriptHost host)
{
super.configure(config);
super.configure(config, host);
single = config.getOrDefault("single", Value.FALSE).getBoolean();
}
@@ -648,9 +686,9 @@ public abstract class CommandArgument
}
@Override
protected void configure(Map<String, Value> config)
protected void configure(Map<String, Value> config, CarpetScriptHost host)
{
super.configure(config);
super.configure(config, host);
mapRequired = !config.getOrDefault("allow_element", Value.FALSE).getBoolean();
}
@@ -694,9 +732,9 @@ public abstract class CommandArgument
}
@Override
protected void configure(Map<String, Value> config)
protected void configure(Map<String, Value> config, CarpetScriptHost host)
{
super.configure(config);
super.configure(config, host);
if (config.containsKey("options"))
{
Value optionsValue = config.get("options");
@@ -736,9 +774,9 @@ public abstract class CommandArgument
}
@Override
protected void configure(Map<String, Value> config)
protected void configure(Map<String, Value> config, CarpetScriptHost host)
{
super.configure(config);
super.configure(config, host);
if (config.containsKey("min"))
{
min = NumericValue.asNumber(config.get("min"), "min").getDouble();
@@ -787,9 +825,9 @@ public abstract class CommandArgument
}
@Override
protected void configure(Map<String, Value> config)
protected void configure(Map<String, Value> config, CarpetScriptHost host)
{
super.configure(config);
super.configure(config, host);
if (config.containsKey("min"))
{
min = NumericValue.asNumber(config.get("min"), "min").getLong();