custom arg types - WIP

This commit is contained in:
gnembon committed 2020-11-03 06:30:49 -04:00
1 parent 741edf1465
commit af668bfdbc
3 files changed
+58 -19

No files matched your search

@@ -3,6 +3,7 @@ package carpet.script;
import carpet.CarpetServer; import carpet.CarpetServer;
import carpet.script.api.Auxiliary; import carpet.script.api.Auxiliary;
import carpet.script.bundled.Module; import carpet.script.bundled.Module;
import carpet.script.command.CommandArgument;
import carpet.script.exception.CarpetExpressionException; import carpet.script.exception.CarpetExpressionException;
import carpet.script.exception.ExpressionException; import carpet.script.exception.ExpressionException;
import carpet.script.exception.InternalExpressionException; import carpet.script.exception.InternalExpressionException;
@@ -26,8 +27,10 @@ import net.minecraft.util.math.BlockPos;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors;
import static java.lang.Math.max; import static java.lang.Math.max;
@@ -41,8 +44,9 @@ public class CarpetScriptHost extends ScriptHost
public boolean persistenceRequired; public boolean persistenceRequired;
public Map<Value, Value> appConfig; public Map<Value, Value> appConfig;
public Map<String, CommandArgument> appArgTypes;
private CarpetScriptHost(CarpetScriptServer server, Module code, boolean perUser, ScriptHost parent, Map<Value, Value> config) private CarpetScriptHost(CarpetScriptServer server, Module code, boolean perUser, ScriptHost parent, Map<Value, Value> config, Map<String, CommandArgument> argTypes)
{ {
super(code, perUser, parent); super(code, perUser, parent);
this.saveTimeout = 0; this.saveTimeout = 0;
@@ -58,11 +62,12 @@ public class CarpetScriptHost extends ScriptHost
persistenceRequired = ((CarpetScriptHost)parent).persistenceRequired; persistenceRequired = ((CarpetScriptHost)parent).persistenceRequired;
} }
appConfig = config; appConfig = config;
appArgTypes = argTypes;
} }
public static CarpetScriptHost create(CarpetScriptServer scriptServer, Module module, boolean perPlayer, ServerCommandSource source) public static CarpetScriptHost create(CarpetScriptServer scriptServer, Module module, boolean perPlayer, ServerCommandSource source)
{ {
CarpetScriptHost host = new CarpetScriptHost(scriptServer, module, perPlayer, null, Collections.emptyMap() ); CarpetScriptHost host = new CarpetScriptHost(scriptServer, module, perPlayer, null, Collections.emptyMap(), new HashMap<>());
// parse code and convert to expression // parse code and convert to expression
if (module != null) if (module != null)
{ {
@@ -97,7 +102,7 @@ public class CarpetScriptHost extends ScriptHost
@Override @Override
protected ScriptHost duplicate() protected ScriptHost duplicate()
{ {
return new CarpetScriptHost(scriptServer, main, false, this, appConfig); return new CarpetScriptHost(scriptServer, main, false, this, appConfig, appArgTypes);
} }
@Override @Override
@@ -132,7 +137,22 @@ public class CarpetScriptHost extends ScriptHost
Map<Value, Value> config = ((MapValue) ret).getMap(); Map<Value, Value> config = ((MapValue) ret).getMap();
setPerPlayer(config.getOrDefault(new StringValue("scope"), new StringValue("player")).getString().equalsIgnoreCase("player")); setPerPlayer(config.getOrDefault(new StringValue("scope"), new StringValue("player")).getString().equalsIgnoreCase("player"));
persistenceRequired = config.getOrDefault(new StringValue("stay_loaded"), Value.FALSE).getBoolean(); persistenceRequired = config.getOrDefault(new StringValue("stay_loaded"), Value.FALSE).getBoolean();
this.appConfig = config; // read custom arguments
Value arguments = config.get(StringValue.of("arguments"));
if (arguments != null)
{
if (!(arguments instanceof MapValue))
throw new InternalExpressionException("'arguments' element in config should be a map");
for (Map.Entry<Value, Value> typeData : ((MapValue)arguments).getMap().entrySet())
{
String argument = typeData.getKey().getString();
Value spec = typeData.getValue();
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));
appArgTypes.put(argument, CommandArgument.buildFromConfig(argument, specData));
}
}
appConfig = config;
} }
catch (NullPointerException | InvalidCallbackException ignored) catch (NullPointerException | InvalidCallbackException ignored)
{ {
@@ -315,14 +315,14 @@ public class CarpetScriptServer
List<Value> args = new ArrayList<>(argNames.size()); List<Value> args = new ArrayList<>(argNames.size());
for (String s : paramNames) for (String s : paramNames)
{ {
args.add(CommandArgument.getValue(ctx, s)); args.add(CommandArgument.getValue(ctx, s, cHost));
} }
Value response = cHost.handleCommand(ctx.getSource(), function, args); Value response = cHost.handleCommand(ctx.getSource(), function, args);
if (!response.isNull()) Messenger.m(ctx.getSource(), "gi " + response.getString()); if (!response.isNull()) Messenger.m(ctx.getSource(), "gi " + response.getString());
return (int) response.readInteger(); return (int) response.readInteger();
} }
private LiteralArgumentBuilder<ServerCommandSource> getFancyCommand(LiteralArgumentBuilder<ServerCommandSource> command, ScriptHost host, FunctionValue function ) private LiteralArgumentBuilder<ServerCommandSource> getFancyCommand(LiteralArgumentBuilder<ServerCommandSource> command, CarpetScriptHost host, FunctionValue function )
{ {
List<String> argNames = function.getArguments(); List<String> argNames = function.getArguments();
String hostName = host.getName(); String hostName = host.getName();
@@ -336,10 +336,10 @@ public class CarpetScriptServer
{ {
List<String> reversedArgs = new ArrayList<>(argNames); List<String> reversedArgs = new ArrayList<>(argNames);
Collections.reverse(reversedArgs); Collections.reverse(reversedArgs);
RequiredArgumentBuilder<ServerCommandSource, ?> argChain = CommandArgument.argumentNode(reversedArgs.get(0)).executes(c -> execute(c, hostName, function, argNames)); RequiredArgumentBuilder<ServerCommandSource, ?> argChain = CommandArgument.argumentNode(reversedArgs.get(0), host).executes(c -> execute(c, hostName, function, argNames));
for (int i = 1; i < reversedArgs.size(); i++) for (int i = 1; i < reversedArgs.size(); i++)
{ {
argChain = CommandArgument.argumentNode(reversedArgs.get(i)).then(argChain); argChain = CommandArgument.argumentNode(reversedArgs.get(i), host).then(argChain);
} }
return command.then(literal(function.getString()). return command.then(literal(function.getString()).
requires((player) -> modules.containsKey(hostName)). requires((player) -> modules.containsKey(hostName)).
@@ -1,5 +1,6 @@
package carpet.script.command; package carpet.script.command;
import carpet.script.CarpetScriptHost;
import carpet.script.exception.InternalExpressionException; import carpet.script.exception.InternalExpressionException;
import carpet.script.value.ListValue; import carpet.script.value.ListValue;
import carpet.script.value.NumericValue; import carpet.script.value.NumericValue;
@@ -42,21 +43,25 @@ public abstract class CommandArgument
public static final Map<String, CommandArgument> builtIns = baseTypes.stream().collect(Collectors.toMap(CommandArgument::getTypeSuffix, a -> a)); public static final Map<String, CommandArgument> builtIns = baseTypes.stream().collect(Collectors.toMap(CommandArgument::getTypeSuffix, a -> a));
private static CommandArgument getTypeForArgument(String argument) public static final CommandArgument DEFAULT = baseTypes.get(0);
private static CommandArgument getTypeForArgument(String argument, CarpetScriptHost host)
{ {
String[] components = argument.split("_"); String[] components = argument.split("_");
String suffix = components[components.length-1].toLowerCase(Locale.ROOT); String suffix = components[components.length-1].toLowerCase(Locale.ROOT);
return builtIns.getOrDefault(suffix, builtIns.get("string")); CommandArgument arg = host.appArgTypes.get(suffix);
if (arg != null) return arg;
return builtIns.getOrDefault(suffix, DEFAULT);
} }
public static RequiredArgumentBuilder<ServerCommandSource, ?> argumentNode(String param) public static RequiredArgumentBuilder<ServerCommandSource, ?> argumentNode(String param, CarpetScriptHost host)
{ {
CommandArgument arg = getTypeForArgument(param); CommandArgument arg = getTypeForArgument(param, host);
return arg.needsMatching? argument(param, arg.getArgumentType()).suggests(arg::suggest) : argument(param, arg.getArgumentType()); return arg.needsMatching? argument(param, arg.getArgumentType()).suggests(arg::suggest) : argument(param, arg.getArgumentType());
} }
private String suffix; private String suffix;
private final Collection<String> examples; private Collection<String> examples;
protected boolean needsMatching = false; protected boolean needsMatching = false;
protected CommandArgument( protected CommandArgument(
@@ -69,17 +74,17 @@ public abstract class CommandArgument
this.needsMatching = needsMatching; this.needsMatching = needsMatching;
} }
public static ArgumentType<?> getArgument(String param) public static ArgumentType<?> getArgument(String param, CarpetScriptHost host)
{ {
return getTypeForArgument(param).getArgumentType(); return getTypeForArgument(param, host).getArgumentType();
} }
protected abstract ArgumentType<?> getArgumentType(); protected abstract ArgumentType<?> getArgumentType();
public static Value getValue(CommandContext<ServerCommandSource> context, String param) throws CommandSyntaxException public static Value getValue(CommandContext<ServerCommandSource> context, String param, CarpetScriptHost host) throws CommandSyntaxException
{ {
return getTypeForArgument(param).getValueFromContext(context, param); return getTypeForArgument(param, host).getValueFromContext(context, param);
} }
protected abstract Value getValueFromContext(CommandContext<ServerCommandSource> context, String param) throws CommandSyntaxException; protected abstract Value getValueFromContext(CommandContext<ServerCommandSource> context, String param) throws CommandSyntaxException;
@@ -108,9 +113,20 @@ public abstract class CommandArgument
variant.configure(config); variant.configure(config);
variant.suffix = suffix; variant.suffix = suffix;
return variant; return variant;
}; }
protected abstract void configure(Map<String, Value> config); protected void configure(Map<String, Value> config)
{
if (config.containsKey("suggest"))
{
Value suggestionValue = config.get("suggest");
if (!(suggestionValue instanceof ListValue)) throw new InternalExpressionException("Argument suggestions needs to be a list");
examples = ((ListValue) suggestionValue).getItems().stream()
.map(Value::getString)
.collect(Collectors.toSet());
if (!examples.isEmpty()) needsMatching = true;
}
};
public CompletableFuture<Suggestions> suggest( public CompletableFuture<Suggestions> suggest(
CommandContext<ServerCommandSource> context, CommandContext<ServerCommandSource> context,
@@ -177,6 +193,7 @@ public abstract class CommandArgument
@Override @Override
protected void configure(Map<String, Value> config) protected void configure(Map<String, Value> config)
{ {
super.configure(config);
caseSensitive = config.getOrDefault("case_sensitive", Value.FALSE).getBoolean(); caseSensitive = config.getOrDefault("case_sensitive", Value.FALSE).getBoolean();
if (config.containsKey("options")) if (config.containsKey("options"))
{ {
@@ -222,6 +239,7 @@ public abstract class CommandArgument
@Override @Override
protected void configure(Map<String, Value> config) protected void configure(Map<String, Value> config)
{ {
super.configure(config);
mustBeLoaded = config.getOrDefault("loaded", Value.FALSE).getBoolean(); mustBeLoaded = config.getOrDefault("loaded", Value.FALSE).getBoolean();
} }
@@ -264,6 +282,7 @@ public abstract class CommandArgument
@Override @Override
protected void configure(Map<String, Value> config) protected void configure(Map<String, Value> config)
{ {
super.configure(config);
if (config.containsKey("min")) if (config.containsKey("min"))
{ {
min = NumericValue.asNumber(config.get("min"), "min").getDouble(); min = NumericValue.asNumber(config.get("min"), "min").getDouble();