online suggestions via suggester
This commit is contained in:
1 parent
5f9df1239a
commit
bc99b081ca
2 files changed
+72
-34
No files matched your search
@@ -215,7 +215,7 @@ public class CarpetScriptHost extends ScriptHost
|
|||||||
Value spec = typeData.getValue();
|
Value spec = typeData.getValue();
|
||||||
if (!(spec instanceof MapValue)) throw new InternalExpressionException("Spec for '"+argument+"' should be a map");
|
if (!(spec instanceof MapValue)) throw new InternalExpressionException("Spec for '"+argument+"' should be a map");
|
||||||
Map<String, Value> specData = ((MapValue) spec).getMap().entrySet().stream().collect(Collectors.toMap(e -> e.getKey().getString(), Map.Entry::getValue));
|
Map<String, Value> specData = ((MapValue) spec).getMap().entrySet().stream().collect(Collectors.toMap(e -> e.getKey().getString(), Map.Entry::getValue));
|
||||||
appArgTypes.put(argument, CommandArgument.buildFromConfig(argument, specData));
|
appArgTypes.put(argument, CommandArgument.buildFromConfig(argument, specData, this));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
appConfig = config;
|
appConfig = config;
|
||||||
|
|||||||
@@ -2,11 +2,13 @@ package carpet.script.command;
|
|||||||
|
|
||||||
import carpet.fakes.BlockStateArgumentInterface;
|
import carpet.fakes.BlockStateArgumentInterface;
|
||||||
import carpet.script.CarpetScriptHost;
|
import carpet.script.CarpetScriptHost;
|
||||||
|
import carpet.script.argument.FunctionArgument;
|
||||||
import carpet.script.exception.InternalExpressionException;
|
import carpet.script.exception.InternalExpressionException;
|
||||||
import carpet.script.value.BlockValue;
|
import carpet.script.value.BlockValue;
|
||||||
import carpet.script.value.EntityValue;
|
import carpet.script.value.EntityValue;
|
||||||
import carpet.script.value.FormattedTextValue;
|
import carpet.script.value.FormattedTextValue;
|
||||||
import carpet.script.value.ListValue;
|
import carpet.script.value.ListValue;
|
||||||
|
import carpet.script.value.MapValue;
|
||||||
import carpet.script.value.NBTSerializableValue;
|
import carpet.script.value.NBTSerializableValue;
|
||||||
import carpet.script.value.NumericValue;
|
import carpet.script.value.NumericValue;
|
||||||
import carpet.script.value.StringValue;
|
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.arguments.StringArgumentType;
|
||||||
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
|
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
|
||||||
import com.mojang.brigadier.context.CommandContext;
|
import com.mojang.brigadier.context.CommandContext;
|
||||||
|
import com.mojang.brigadier.context.ParsedCommandNode;
|
||||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||||
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
|
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
|
||||||
import com.mojang.brigadier.suggestion.SuggestionProvider;
|
import com.mojang.brigadier.suggestion.SuggestionProvider;
|
||||||
import com.mojang.brigadier.suggestion.Suggestions;
|
import com.mojang.brigadier.suggestion.Suggestions;
|
||||||
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
|
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.advancement.Advancement;
|
||||||
import net.minecraft.command.CommandSource;
|
import net.minecraft.command.CommandSource;
|
||||||
import net.minecraft.command.argument.AngleArgumentType;
|
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.math.Vec2f;
|
||||||
import net.minecraft.util.registry.Registry;
|
import net.minecraft.util.registry.Registry;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -259,13 +266,15 @@ public abstract class CommandArgument
|
|||||||
{
|
{
|
||||||
CommandArgument arg = getTypeForArgument(param, host);
|
CommandArgument arg = getTypeForArgument(param, host);
|
||||||
if (arg.suggestionProvider != null) return argument(param, arg.getArgumentType()).suggests(arg.suggestionProvider);
|
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 String suffix;
|
||||||
protected Collection<String> examples;
|
protected Collection<String> examples;
|
||||||
protected boolean needsMatching = false;
|
protected boolean needsMatching = false;
|
||||||
protected SuggestionProvider<ServerCommandSource> suggestionProvider;
|
protected SuggestionProvider<ServerCommandSource> suggestionProvider;
|
||||||
|
protected FunctionArgument<Value> customSuggester;
|
||||||
|
|
||||||
|
|
||||||
protected CommandArgument(
|
protected CommandArgument(
|
||||||
String suffix,
|
String suffix,
|
||||||
@@ -292,7 +301,7 @@ public abstract class CommandArgument
|
|||||||
return suffix;
|
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"))
|
if (!config.containsKey("type"))
|
||||||
throw new InternalExpressionException("Custom types should at least specify the type");
|
throw new InternalExpressionException("Custom types should at least specify the type");
|
||||||
@@ -300,15 +309,20 @@ public abstract class CommandArgument
|
|||||||
if (!builtIns.containsKey(baseType))
|
if (!builtIns.containsKey(baseType))
|
||||||
throw new InternalExpressionException("Unknown base type: "+baseType);
|
throw new InternalExpressionException("Unknown base type: "+baseType);
|
||||||
CommandArgument variant = builtIns.get(baseType).builder().get();
|
CommandArgument variant = builtIns.get(baseType).builder().get();
|
||||||
variant.configure(config);
|
variant.configure(config, host);
|
||||||
variant.suffix = suffix;
|
variant.suffix = suffix;
|
||||||
return variant;
|
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("suggest"))
|
||||||
{
|
{
|
||||||
|
if (config.containsKey("suggester")) throw new InternalExpressionException("Attempted to provide 'suggest' list while 'suggester' is present");
|
||||||
Value suggestionValue = config.get("suggest");
|
Value suggestionValue = config.get("suggest");
|
||||||
if (!(suggestionValue instanceof ListValue)) throw new InternalExpressionException("Argument suggestions needs to be a list");
|
if (!(suggestionValue instanceof ListValue)) throw new InternalExpressionException("Argument suggestions needs to be a list");
|
||||||
examples = ((ListValue) suggestionValue).getItems().stream()
|
examples = ((ListValue) suggestionValue).getItems().stream()
|
||||||
@@ -316,34 +330,55 @@ public abstract class CommandArgument
|
|||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
if (!examples.isEmpty()) needsMatching = true;
|
if (!examples.isEmpty()) needsMatching = true;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
public CompletableFuture<Suggestions> suggest(
|
public CompletableFuture<Suggestions> suggest(
|
||||||
CommandContext<ServerCommandSource> context,
|
CommandContext<ServerCommandSource> context,
|
||||||
SuggestionsBuilder suggestionsBuilder
|
SuggestionsBuilder suggestionsBuilder,
|
||||||
)
|
CarpetScriptHost host
|
||||||
|
) throws CommandSyntaxException
|
||||||
{
|
{
|
||||||
String prefix = suggestionsBuilder.getRemaining().toLowerCase(Locale.ROOT);
|
String prefix = suggestionsBuilder.getRemaining().toLowerCase(Locale.ROOT);
|
||||||
suggestFor(prefix).forEach(suggestionsBuilder::suggest);
|
suggestFor(context, prefix, host).forEach(suggestionsBuilder::suggest);
|
||||||
return suggestionsBuilder.buildFuture();
|
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("");
|
//return Lists.newArrayList("");
|
||||||
// better than nothing I guess
|
// better than nothing I guess
|
||||||
// nothing is such a bad default.
|
// nothing is such a bad default.
|
||||||
if (needsMatching) return examples;
|
|
||||||
return Collections.singletonList("... "+getTypeSuffix());
|
return Collections.singletonList("... "+getTypeSuffix());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean optionMatchesPrefix(String prefix, String option)
|
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)
|
for(int i = 0; !option.startsWith(prefix, i); ++i)
|
||||||
{
|
{
|
||||||
i = option.indexOf('_', i);
|
i = option.indexOf('_', i);
|
||||||
@@ -382,9 +417,9 @@ public abstract class CommandArgument
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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();
|
caseSensitive = config.getOrDefault("case_sensitive", Value.FALSE).getBoolean();
|
||||||
if (config.containsKey("options"))
|
if (config.containsKey("options"))
|
||||||
{
|
{
|
||||||
@@ -397,7 +432,10 @@ public abstract class CommandArgument
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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
|
@Override
|
||||||
protected Supplier<CommandArgument> builder() { return WordArgument::new; }
|
protected Supplier<CommandArgument> builder() { return WordArgument::new; }
|
||||||
@@ -446,9 +484,9 @@ public abstract class CommandArgument
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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();
|
mustBeLoaded = config.getOrDefault("loaded", Value.FALSE).getBoolean();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -481,9 +519,9 @@ public abstract class CommandArgument
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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();
|
blockCentered = config.getOrDefault("block_centered", Value.TRUE).getBoolean();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -529,9 +567,9 @@ public abstract class CommandArgument
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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();
|
onlyFans = config.getOrDefault("players", Value.FALSE).getBoolean();
|
||||||
single = config.getOrDefault("single", Value.FALSE).getBoolean();
|
single = config.getOrDefault("single", Value.FALSE).getBoolean();
|
||||||
}
|
}
|
||||||
@@ -570,9 +608,9 @@ public abstract class CommandArgument
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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();
|
single = config.getOrDefault("single", Value.FALSE).getBoolean();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -611,9 +649,9 @@ public abstract class CommandArgument
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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();
|
single = config.getOrDefault("single", Value.FALSE).getBoolean();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -648,9 +686,9 @@ public abstract class CommandArgument
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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();
|
mapRequired = !config.getOrDefault("allow_element", Value.FALSE).getBoolean();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -694,9 +732,9 @@ public abstract class CommandArgument
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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"))
|
if (config.containsKey("options"))
|
||||||
{
|
{
|
||||||
Value optionsValue = config.get("options");
|
Value optionsValue = config.get("options");
|
||||||
@@ -736,9 +774,9 @@ public abstract class CommandArgument
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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"))
|
if (config.containsKey("min"))
|
||||||
{
|
{
|
||||||
min = NumericValue.asNumber(config.get("min"), "min").getDouble();
|
min = NumericValue.asNumber(config.get("min"), "min").getDouble();
|
||||||
@@ -787,9 +825,9 @@ public abstract class CommandArgument
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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"))
|
if (config.containsKey("min"))
|
||||||
{
|
{
|
||||||
min = NumericValue.asNumber(config.get("min"), "min").getLong();
|
min = NumericValue.asNumber(config.get("min"), "min").getLong();
|
||||||
|
|||||||
Reference in new issue
Block a user