Core/Commands: Change way we handle optional args. Fixes #43

This commit is contained in:
hondacrx
2022-08-20 18:43:31 -04:00
parent 135760cbed
commit 56d9dc6190
4 changed files with 75 additions and 19 deletions
+64 -13
View File
@@ -26,30 +26,35 @@ namespace Game.Chat
{
class CommandArgs
{
public static object[] Parse(CommandHandler handler, Type[] parameterTypes, StringArguments args)
public static bool Parse(out dynamic[] parsedArgs, CommandHandler handler, Type[] parameterTypes, StringArguments args)
{
List<object> arguments = new();
arguments.Add(handler);
for (var i = 1; i < parameterTypes.Length; i++)
arguments.Add(default);
parsedArgs = new dynamic[parameterTypes.Length];
parsedArgs[0] = handler;
for (var i = 1; i < parameterTypes.Length; i++)
{
if (!ParseArgument(out dynamic value, parameterTypes[i], args))
break;
return false;
arguments[i] = value;
parsedArgs[i] = value;
}
return arguments.ToArray();
return true;
}
static bool ParseArgument(out dynamic value, Type type, StringArguments args)
static bool ParseArgument(out dynamic value, Type type, StringArguments args, bool IsOptional = false)
{
value = default;
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(OptionalArg<>))
return ParseArgument(out value, type.GetGenericArguments()[0], args, true);
//todo remove me when all commands to changed to OptionalArg<T>
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
return ParseArgument(out value, Nullable.GetUnderlyingType(type), args, true);
if (args.IsAtEnd())
return false;
return IsOptional;
if (Hyperlink.TryParse(out value, type, args))
return true;
@@ -57,9 +62,6 @@ namespace Game.Chat
if (type.IsEnum)
type = type.GetEnumUnderlyingType();
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
type = Nullable.GetUnderlyingType(type);
switch (Type.GetTypeCode(type))
{
case TypeCode.SByte:
@@ -258,4 +260,53 @@ namespace Game.Chat
return null;
}
}
struct OptionalArg<T>
{
private bool _hasValue;
public T Value;
public OptionalArg(T value)
{
Value = value;
_hasValue = true;
}
public bool HasValue
{
get { return _hasValue; }
}
public void Set(T value)
{
Value = value;
_hasValue = true;
}
public void Clear()
{
_hasValue = false;
Value = default;
}
public T ValueOr(T otherValue)
{
return HasValue ? Value : otherValue;
}
public static explicit operator T(OptionalArg<T> optional)
{
return optional.Value;
}
public static implicit operator OptionalArg<T>(T value)
{
return new OptionalArg<T>(value);
}
public Type GetValueType()
{
return typeof(T);
}
}
}
+6 -1
View File
@@ -220,6 +220,7 @@ namespace Game.Chat
if (cmd != null)
{ /* if we matched a command at some point, invoke it */
handler._sentErrorMessage = false;
if (cmd.IsInvokerVisible(handler) && cmd.Invoke(handler, new StringArguments(oldTail)))
{ /* invocation succeeded, log this */
if (!handler.IsConsole())
@@ -403,8 +404,12 @@ namespace Game.Chat
if (parameterTypes.Contains(typeof(StringArguments)))//Old system, can remove once all commands are changed.
return (bool)_methodInfo.Invoke(null, new object[] { handler, args });
else
return (bool)_methodInfo.Invoke(null, CommandArgs.Parse(handler, parameterTypes, args));
{
if (CommandArgs.Parse(out dynamic[] parseArgs, handler, parameterTypes, args))
return (bool)_methodInfo.Invoke(null, parseArgs);
return false;
}
}
}
+2 -2
View File
@@ -87,7 +87,7 @@ namespace Game.Chat
}
[Command("create", CypherStrings.CommandAccCreateHelp, RBACPermissions.CommandAccountCreate, true)]
static bool HandleAccountCreateCommand(CommandHandler handler, string accountName, string password, string email)
static bool HandleAccountCreateCommand(CommandHandler handler, string accountName, string password, OptionalArg<string> email)
{
if (accountName.Contains("@"))
{
@@ -95,7 +95,7 @@ namespace Game.Chat
return false;
}
AccountOpResult result = Global.AccountMgr.CreateAccount(accountName, password, email);
AccountOpResult result = Global.AccountMgr.CreateAccount(accountName, password, email.ValueOr(""));
switch (result)
{
case AccountOpResult.Ok:
+3 -3
View File
@@ -733,10 +733,10 @@ namespace Game.Chat
}
[CommandNonGroup("help", RBACPermissions.CommandHelp, true)]
static bool HandleHelpCommand(CommandHandler handler, string cmd)
static bool HandleHelpCommand(CommandHandler handler, OptionalArg<string> cmd)
{
ChatCommandNode.SendCommandHelpFor(handler, cmd);
if (cmd.IsEmpty())
ChatCommandNode.SendCommandHelpFor(handler, cmd.ValueOr(""));
if (!cmd.HasValue)
ChatCommandNode.SendCommandHelpFor(handler, "help");
return true;