From 0ee809194ad27488e231d2d3fdd7751f7c910e73 Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Mon, 3 Oct 2022 05:08:49 +0700 Subject: [PATCH] Add parsing support for players command arguments --- sources/Commands/Command.uc | 2 +- sources/Commands/CommandParser.uc | 46 +++++++++++++++++++++++++++---- 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/sources/Commands/Command.uc b/sources/Commands/Command.uc index ad01d0d..bfb1b94 100644 --- a/sources/Commands/Command.uc +++ b/sources/Commands/Command.uc @@ -348,7 +348,7 @@ public final function CallData ParseInputWith( } // Parse parameters themselves commandParser = CommandParser(_.memory.Allocate(class'CommandParser')); - callData = commandParser.ParseWith(parser, commandData); + callData = commandParser.ParseWith(parser, commandData, callerPlayer); callData.targetPlayers = targetPlayers; commandParser.FreeSelf(); return callData; diff --git a/sources/Commands/CommandParser.uc b/sources/Commands/CommandParser.uc index 66d5c3d..35b6cb7 100644 --- a/sources/Commands/CommandParser.uc +++ b/sources/Commands/CommandParser.uc @@ -102,6 +102,8 @@ enum ParsingTarget CPT_ExtraParameter, }; +// Parser for player parameters, setup with a caller for current parsing +var private PlayersParser currentPlayersParser; // Current `ParsingTarget`, see it's enum description for more details var private ParsingTarget currentTarget; // `true` means we are parsing parameters for a command's option and @@ -131,6 +133,10 @@ protected function Finalizer() private final function Reset() { local Command.CallData blankCallData; + + _.memory.Free(currentPlayersParser); + currentPlayersParser = none; + // We didn't create this one and are not meant to free it either commandParser = none; nextResult = blankCallData; currentTarget = CPT_NecessaryParameter; @@ -197,18 +203,20 @@ private final function PickSubCommand(Command.Data commandData) * Parses user's input given in `parser` using command's information given by * `commandData`. * - * @param parser `Parser`, initialized with user's input that will need - * to be parsed as a command's call. - * @param commandData Describes what parameters and options should be + * @param parser `Parser`, initialized with user's input that will + * need to be parsed as a command's call. + * @param commandData Describes what parameters and options should be * expected in user's input. `Text` values from `commandData` can be used * inside resulting `Command.CallData`, so deallocating them can * invalidate returned value. + * @param callerPlayer Player that called this command, if applicable. * @return Results of parsing, described by `Command.CallData`. * Returned object is guaranteed to be not `none`. */ public final function Command.CallData ParseWith( - Parser parser, - Command.Data commandData) + Parser parser, + Command.Data commandData, + optional EPlayer callerPlayer) { local HashTable commandParameters; // Temporary object to return `nextResult` while setting variable to `none` @@ -231,6 +239,9 @@ public final function Command.CallData ParseWith( } commandParser = parser; availableOptions = commandData.options; + currentPlayersParser = + PlayersParser(_.memory.Allocate(class'PlayersParser')); + currentPlayersParser.SetSelf(callerPlayer); // (subcommand) (parameters, possibly with options) and nothing else! PickSubCommand(commandData); nextResult.subCommandName = pickedSubCommand.name.Copy(); @@ -452,6 +463,9 @@ private final function bool ParseSingleValue( else if (expectedParameter.type == CPT_JSON) { return ParseJSONValue(parsedParameters, expectedParameter); } + else if (expectedParameter.type == CPT_Players) { + return ParsePlayersValue(parsedParameters, expectedParameter); + } return false; } @@ -636,6 +650,28 @@ private final function bool ParseJSONValue( return true; } +// Assumes `commandParser` and `parsedParameters` are not `none`. +// Parses a single JSON value into given `parsedParameters` +// hash table. +private final function bool ParsePlayersValue( + HashTable parsedParameters, + Command.Parameter expectedParameter) +{ + local ArrayList resultPlayerList; + local array targetPlayers; + + currentPlayersParser.ParseWith(commandParser); + if (commandParser.Ok()) { + targetPlayers = currentPlayersParser.GetPlayers(); + } + else { + return false; + } + resultPlayerList = _.collections.NewArrayList(targetPlayers); + _.memory.FreeMany(targetPlayers); + RecordParameter(parsedParameters, expectedParameter, resultPlayerList); + return true; +} // Assumes `parsedParameters` is not `none`. // Records `value` for a given `parameter` into a given `parametersArray`. // If parameter is not a list type - simply records `value` as value under