custom command trees, no validation so far

This commit is contained in:
gnembon committed 2020-11-12 02:55:18 -04:00
1 parent c7a96aa219
commit 9f6771123f
5 files changed
+185 -66

No files matched your search

@@ -5,6 +5,7 @@ import carpet.script.api.Auxiliary;
import carpet.script.argument.FunctionArgument;
import carpet.script.bundled.Module;
import carpet.script.command.CommandArgument;
import carpet.script.command.CommandToken;
import carpet.script.exception.CarpetExpressionException;
import carpet.script.exception.ExpressionException;
import carpet.script.exception.InternalExpressionException;
@@ -16,14 +17,20 @@ import carpet.script.value.StringValue;
import carpet.script.value.Value;
import carpet.CarpetSettings;
import carpet.utils.Messenger;
import com.mojang.brigadier.builder.ArgumentBuilder;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.nbt.Tag;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.text.LiteralText;
import net.minecraft.util.math.BlockPos;
import org.apache.commons.lang3.tuple.Pair;
import java.math.BigInteger;
import java.util.ArrayList;
@@ -34,6 +41,7 @@ import java.util.Map;
import java.util.stream.Collectors;
import static java.lang.Math.max;
import static net.minecraft.server.command.CommandManager.literal;
public class CarpetScriptHost extends ScriptHost
{
@@ -100,6 +108,62 @@ public class CarpetScriptHost extends ScriptHost
return host;
}
private static int execute(CommandContext<ServerCommandSource> ctx, String hostName, FunctionArgument<Value> funcSpec, List<String> paramNames) throws CommandSyntaxException
{
CarpetScriptHost cHost = CarpetServer.scriptServer.modules.get(hostName).retrieveForExecution(ctx.getSource());
List<String> argNames = funcSpec.function.getArguments();
if ((argNames.size()-funcSpec.args.size()) != paramNames.size())
throw new SimpleCommandExceptionType(new LiteralText("Target function "+funcSpec.function.getPrettyString()+" as wrong number of arguments, required "+paramNames.size()+", found "+argNames.size()+" with "+funcSpec.args.size()+" provided")).create();
List<Value> args = new ArrayList<>(argNames.size());
for (String s : paramNames)
{
args.add(CommandArgument.getValue(ctx, s, cHost));
}
args.addAll(funcSpec.args);
Value response = cHost.handleCommand(ctx.getSource(), funcSpec.function, args);
// will skip prints for new
//if (!response.isNull()) Messenger.m(ctx.getSource(), "gi " + response.getString());
return (int) response.readInteger();
}
public LiteralArgumentBuilder<ServerCommandSource> addPathToCommand(
LiteralArgumentBuilder<ServerCommandSource> command,
List<CommandToken> path,
FunctionArgument<Value> functionSpec
) throws CommandSyntaxException
{
String hostName = main.getName();
List<String> commandArgs = path.stream().filter(t -> t.isArgument).map(t -> t.surface).collect(Collectors.toList());
if (commandArgs.size() != (functionSpec.function.getNumParams()-functionSpec.args.size()) )
throw CommandArgument.error("Number of parameters in function doesn't match parameters for a command");
if (path.isEmpty())
{
return command.executes((c) -> execute(c, hostName, functionSpec, Collections.emptyList()));
}
List<CommandToken> reversedPath = new ArrayList<>(path);
Collections.reverse(reversedPath);
ArgumentBuilder<ServerCommandSource, ?> argChain = reversedPath.get(0).getCommandNode(this).executes(c -> execute(c, hostName, functionSpec, commandArgs));
for (int i = 1; i < reversedPath.size(); i++)
{
argChain = reversedPath.get(i).getCommandNode(this).then(argChain);
}
return command.then(argChain);
}
public LiteralArgumentBuilder<ServerCommandSource> getNewCommandTree(
List<Pair<List<CommandToken>,FunctionArgument<Value>>> entries
) throws CommandSyntaxException
{
String hostName = main.getName();
LiteralArgumentBuilder<ServerCommandSource> command = literal(hostName).
requires((player) -> CarpetServer.scriptServer.modules.containsKey(hostName));
for (Pair<List<CommandToken>,FunctionArgument<Value>> commandData : entries)
{
command = this.addPathToCommand(command, commandData.getKey(), commandData.getValue());
}
return command;
}
@Override
protected ScriptHost duplicate()
{
@@ -162,24 +226,24 @@ public class CarpetScriptHost extends ScriptHost
return true;
}
private boolean readCommands()
public LiteralArgumentBuilder<ServerCommandSource> readCommands() throws CommandSyntaxException
{
Value commands = appConfig.get(StringValue.of("commands"));
if (commands == null) return true;
if (commands == null) return null;
if (!(commands instanceof MapValue))
throw new InternalExpressionException("'commands' element in config should be a map");
for (Map.Entry<Value, Value> commandsData : ((MapValue)commands).getMap().entrySet())
throw CommandArgument.error("'commands' element in config should be a map");
List<Pair<List<CommandToken>,FunctionArgument<Value>>> commandEntries = new ArrayList<>();
for (Map.Entry<Value, Value> commandsData : ((MapValue)commands).getMap().entrySet().stream().sorted(Map.Entry.comparingByKey()).collect(Collectors.toList()))
{
String path = commandsData.getKey().getString();
List<CommandToken> elements = CommandToken.parseSpec(commandsData.getKey().getString(), this);
FunctionArgument<Value> funSpec = FunctionArgument.fromCommandSpec(this, commandsData.getValue());
//if (fun)
//... WIP
//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));
commandEntries.add(Pair.of(elements, funSpec));
}
return true;
// validate
// ...
//
return this.getNewCommandTree(commandEntries);
}
@Override