From 6b54a6384d0d4c62e16191e612bcad8ab6445861 Mon Sep 17 00:00:00 2001 From: hondacrx Date: Thu, 25 Aug 2022 12:04:58 -0400 Subject: [PATCH] Core/Commands: More work on commands. --- Source/Game/Chat/CommandArgs.cs | 553 ++++++++++-------- Source/Game/Chat/CommandAttribute.cs | 3 + Source/Game/Chat/CommandManager.cs | 34 +- Source/Game/Chat/CommandTags.cs | 194 ++++++ Source/Game/Chat/Commands/AccountCommands.cs | 19 +- .../Game/Chat/Commands/BNetAccountCommands.cs | 2 +- Source/Game/Chat/Commands/CastCommands.cs | 12 +- .../Game/Chat/Commands/CharacterCommands.cs | 10 +- Source/Game/Chat/Commands/LearnCommands.cs | 2 +- Source/Game/Chat/Commands/ListCommands.cs | 2 +- Source/Game/Chat/Commands/MessageCommands.cs | 41 +- Source/Game/Chat/Commands/MiscCommands.cs | 35 +- Source/Game/Chat/Commands/NPCCommands.cs | 14 +- Source/Game/Chat/Commands/TeleCommands.cs | 8 +- Source/Game/Chat/Hyperlink.cs | 11 +- 15 files changed, 623 insertions(+), 317 deletions(-) create mode 100644 Source/Game/Chat/CommandTags.cs diff --git a/Source/Game/Chat/CommandArgs.cs b/Source/Game/Chat/CommandArgs.cs index c84455acc..7ea2ea5f3 100644 --- a/Source/Game/Chat/CommandArgs.cs +++ b/Source/Game/Chat/CommandArgs.cs @@ -15,25 +15,42 @@ * along with this program. If not, see . */ -using Framework.Constants; -using Framework.IO; -using Game.Entities; -using Game.Spells; using System; using System.Collections.Generic; +using System.Reflection; namespace Game.Chat { class CommandArgs { - public static bool Parse(out dynamic[] parsedArgs, CommandHandler handler, Type[] parameterTypes, StringArguments args) + static Dictionary> Parsers = new() { - parsedArgs = new dynamic[parameterTypes.Length]; + { typeof(sbyte), args => args.NextSByte() }, + { typeof(short), args => args.NextInt16() }, + { typeof(int), args => args.NextInt32() }, + { typeof(long), args => args.NextInt64() }, + { typeof(byte), args => args.NextByte() }, + { typeof(ushort), args => args.NextUInt16() }, + { typeof(uint), args => args.NextUInt32() }, + { typeof(ulong), args => args.NextUInt64() }, + { typeof(float), args => args.NextSingle() }, + { typeof(string), args => args.NextString() }, + { typeof(bool), args => args.NextBoolean() }, + { typeof(PlayerIdentifier), args => PlayerIdentifier.ParseFromString(args) }, + { typeof(AccountIdentifier), args => AccountIdentifier.ParseFromString(args) }, + { typeof(Tail), args => Tail.ParseFromString(args) }, + }; + + public static bool Parse(out dynamic[] parsedArgs, CommandHandler handler, ParameterInfo[] parameterInfos, string tailCmd) + { + parsedArgs = new dynamic[parameterInfos.Length]; parsedArgs[0] = handler; - for (var i = 1; i < parameterTypes.Length; i++) + CommandArguments args = new CommandArguments(tailCmd); + + for (var i = 1; i < parameterInfos.Length; i++) { - if (!ParseArgument(out dynamic value, parameterTypes[i], args)) + if (!ParseArgument(out dynamic value, parameterInfos[i], args)) return false; parsedArgs[i] = value; @@ -42,271 +59,339 @@ namespace Game.Chat return true; } - static bool ParseArgument(out dynamic value, Type type, StringArguments args, bool IsOptional = false) + static bool ParseArgument(out dynamic value, ParameterInfo parameterInfo, CommandArguments args) { - value = default; + var parameterType = parameterInfo.ParameterType; - 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 - if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)) - return ParseArgument(out value, Nullable.GetUnderlyingType(type), args, true); - - if (args.IsAtEnd()) - return IsOptional; - - if (Hyperlink.TryParse(out value, type, args)) + if (Hyperlink.TryParse(out value, parameterType, args)) return true; - if (type.IsEnum) - type = type.GetEnumUnderlyingType(); + bool isOptional = false; - switch (Type.GetTypeCode(type)) + var optionalArgAttribute = parameterInfo.GetCustomAttribute(true); + if (optionalArgAttribute != null) + isOptional = true; + + if (parameterType.IsGenericType && parameterType.GetGenericTypeDefinition() == typeof(Nullable<>)) { - case TypeCode.SByte: - value = args.NextSByte(); - break; - case TypeCode.Int16: - value = args.NextInt16(); - break; - case TypeCode.Int32: - value = args.NextInt32(); - break; - case TypeCode.Int64: - value = args.NextInt64(); - break; - case TypeCode.Byte: - value = args.NextByte(); - break; - case TypeCode.UInt16: - value = args.NextUInt16(); - break; - case TypeCode.UInt32: - value = args.NextUInt32(); - break; - case TypeCode.UInt64: - value = args.NextUInt64(); - break; - case TypeCode.Single: - value = args.NextSingle(); - break; - case TypeCode.String: - value = args.NextString(); - break; - case TypeCode.Boolean: - value = args.NextBoolean(); - break; - case TypeCode.Char: - value = args.NextChar(); - break; - case TypeCode.Object: - switch (type.Name) - { - case nameof(PlayerIdentifier): - value = PlayerIdentifier.ParseFromString(args.NextString()); - break; - case nameof(AccountIdentifier): - value = AccountIdentifier.ParseFromString(args.NextString()); - break; - default: - return false; - } - break; - default: - return false; + parameterType = Nullable.GetUnderlyingType(parameterType); + isOptional = true; } + if (parameterType.IsEnum) + parameterType = parameterType.GetEnumUnderlyingType(); + + var pos = args.GetCurrentPosition(); + + var result = Parsers[parameterType](args); + if (result != ParseResult.Ok) + { + if (!isOptional) + return false; + else + args.SetCurrentPosition(pos); + } + + value = result.GetValue(); return true; } } - class PlayerIdentifier + public enum ParseResult { - string _name; - ObjectGuid _guid; - Player _player; + Ok, + Error, + EndOfString + } - public PlayerIdentifier(string name, ObjectGuid guid) + public struct ParseStringResult + { + ParseResult result; + dynamic value; + + public ParseStringResult(ParseResult _result, dynamic _value = default) { - _name = name; - _guid = guid; + result = _result; + value = _value; } - public PlayerIdentifier(Player player) + public dynamic GetValue() { return value; } + + public static implicit operator ParseResult(ParseStringResult stringResult) { - _name = player.GetName(); - _guid = player.GetGUID(); - _player = player; + return stringResult.result; } - public string GetName() { return _name; } - public ObjectGuid GetGUID() { return _guid; } - public bool IsConnected() { return _player != null; } - public Player GetConnectedPlayer() { return _player; } - - public static PlayerIdentifier FromTarget(CommandHandler handler) + public static implicit operator string(ParseStringResult stringResult) { - Player player = handler.GetPlayer(); - if (player != null) - { - Player target = player.GetSelectedPlayer(); - if (target != null) - return new PlayerIdentifier(target); - } - - return null; - } - - public static PlayerIdentifier FromSelf(CommandHandler handler) - { - Player player = handler.GetPlayer(); - if (player != null) - return new PlayerIdentifier(player); - - return null; - } - - public static PlayerIdentifier FromTargetOrSelf(CommandHandler handler) - { - PlayerIdentifier fromTarget = FromTarget(handler); - if (fromTarget != null) - return fromTarget; - else - return FromSelf(handler); - } - - public static PlayerIdentifier ParseFromString(string arg) - { - ulong guid = 0; - string name; - if (!Hyperlink.TryParse(out name, arg) || !ulong.TryParse(arg, out guid)) - name = arg; - - if (!name.IsEmpty()) - { - ObjectManager.NormalizePlayerName(ref name); - var player = Global.ObjAccessor.FindPlayerByName(name); - if (player != null) - return new PlayerIdentifier(player); - else - { - var objectGuid = Global.CharacterCacheStorage.GetCharacterGuidByName(name); - if (objectGuid.IsEmpty()) - return new PlayerIdentifier(name, objectGuid); - } - } - else if (guid != 0) - { - var player = Global.ObjAccessor.FindPlayerByLowGUID(guid); - if (player != null) - return new PlayerIdentifier(player); - } - - return null; + return stringResult.value; } } - class AccountIdentifier + public sealed class CommandArguments { - uint _id; - string _name; - WorldSession _session; + static ParseStringResult ErrorResult = new(ParseResult.Error); + static ParseStringResult EndOfStringResult = new(ParseResult.EndOfString); - public AccountIdentifier(WorldSession session) + public CommandArguments(string args) { - _id = session.GetAccountId(); - _name = session.GetAccountName(); - _session = session; + if (!args.IsEmpty()) + activestring = args.TrimStart(' '); + activeposition = -1; } - public uint GetID() { return _id; } - public string GetName() { return _name; } - public bool IsConnected() { return _session != null; } - public WorldSession GetConnectedSession() { return _session; } - - public static AccountIdentifier ParseFromString(string arg) + public CommandArguments(CommandArguments args) { - // try parsing as account name - var session = Global.WorldMgr.FindSession(Global.AccountMgr.GetId(arg)); - if (session != null) // account with name exists, we are done - return new AccountIdentifier(session); - - // try parsing as account id - if (uint.TryParse(arg, out uint id)) - return null; - - session = Global.WorldMgr.FindSession(id); - if (session != null) - return new AccountIdentifier(session); - - return null; + activestring = args.activestring; + activeposition = args.activeposition; + Current = args.Current; } - public static AccountIdentifier FromTarget(CommandHandler handler) + public bool Empty() { - Player player = handler.GetPlayer(); - if (player != null) + return activestring.IsEmpty(); + } + + public void MoveToNextChar(char c) + { + for (var i = activeposition; i < activestring.Length; ++i) + if (activestring[i] == c) + break; + } + + public ParseStringResult NextString(string delimiters = " ") + { + if (!MoveNext(delimiters)) + return new ParseStringResult(ParseResult.EndOfString, ""); + + if (System.Text.RegularExpressions.Regex.IsMatch(Current, @"^[a-zA-Z]+$")) + return new ParseStringResult(ParseResult.Ok, Current); + + return new ParseStringResult(ParseResult.Error, ""); + } + + public ParseStringResult NextBoolean(string delimiters = " ") + { + if (!MoveNext(delimiters)) + return EndOfStringResult; + + bool value; + if (bool.TryParse(Current, out value)) + return new ParseStringResult(ParseResult.Ok, value); + + if ((Current == "1") || Current.Equals("y", StringComparison.OrdinalIgnoreCase) || Current.Equals("on", StringComparison.OrdinalIgnoreCase) || Current.Equals("yes", StringComparison.OrdinalIgnoreCase) || Current.Equals("true", StringComparison.OrdinalIgnoreCase)) + return new ParseStringResult(ParseResult.Ok, true); + if ((Current == "0") || Current.Equals("n", StringComparison.OrdinalIgnoreCase) || Current.Equals("off", StringComparison.OrdinalIgnoreCase) || Current.Equals("no", StringComparison.OrdinalIgnoreCase) || Current.Equals("false", StringComparison.OrdinalIgnoreCase)) + return new ParseStringResult(ParseResult.Ok, false); + + return ErrorResult; + } + + public ParseStringResult NextChar(string delimiters = " ") + { + if (!MoveNext(delimiters)) + return EndOfStringResult; + + if (char.TryParse(Current, out char value)) + return new ParseStringResult(ParseResult.Ok, value); + + return ErrorResult; + } + + public ParseStringResult NextByte(string delimiters = " ") + { + if (!MoveNext(delimiters)) + return EndOfStringResult; + + if (byte.TryParse(Current, out byte value)) + return new ParseStringResult(ParseResult.Ok, value); + + return ErrorResult; + } + + public ParseStringResult NextSByte(string delimiters = " ") + { + if (!MoveNext(delimiters)) + return EndOfStringResult; + + if (sbyte.TryParse(Current, out sbyte value)) + return new ParseStringResult(ParseResult.Ok, value); + + return ErrorResult; + } + + public ParseStringResult NextUInt16(string delimiters = " ") + { + if (!MoveNext(delimiters)) + return EndOfStringResult; + + if (ushort.TryParse(Current, out ushort value)) + return new ParseStringResult(ParseResult.Ok, value); + + return ErrorResult; + } + + public ParseStringResult NextInt16(string delimiters = " ") + { + if (!MoveNext(delimiters)) + return EndOfStringResult; + + if (short.TryParse(Current, out short value)) + return new ParseStringResult(ParseResult.Ok, value); + + return ErrorResult; + } + + public ParseStringResult NextUInt32(string delimiters = " ") + { + if (!MoveNext(delimiters)) + return EndOfStringResult; + + if (uint.TryParse(Current, out uint value)) + return new ParseStringResult(ParseResult.Ok, value); + + return ErrorResult; + } + + public ParseStringResult NextInt32(string delimiters = " ") + { + if (!MoveNext(delimiters)) + return EndOfStringResult; + + if (int.TryParse(Current, out int value)) + return new ParseStringResult(ParseResult.Ok, value); + + return ErrorResult; + } + + public ParseStringResult NextUInt64(string delimiters = " ") + { + if (!MoveNext(delimiters)) + return EndOfStringResult; + + if (ulong.TryParse(Current, out ulong value)) + return new ParseStringResult(ParseResult.Ok, value); + + return ErrorResult; + } + + public ParseStringResult NextInt64(string delimiters = " ") + { + if (!MoveNext(delimiters)) + return EndOfStringResult; + + if (long.TryParse(Current, out long value)) + return new ParseStringResult(ParseResult.Ok, value); + + return ErrorResult; + } + + public ParseStringResult NextSingle(string delimiters = " ") + { + if (!MoveNext(delimiters)) + return EndOfStringResult; + + if (float.TryParse(Current, out float value)) + return new ParseStringResult(ParseResult.Ok, value); + + return ErrorResult; + } + + public ParseStringResult NextDouble(string delimiters = " ") + { + if (!MoveNext(delimiters)) + return EndOfStringResult; + + if (double.TryParse(Current, out double value)) + return new ParseStringResult(ParseResult.Ok, value); + + return ErrorResult; + } + + public ParseStringResult NextDecimal(string delimiters = " ") + { + if (!MoveNext(delimiters)) + return EndOfStringResult; + + if (decimal.TryParse(Current, out decimal value)) + return new ParseStringResult(ParseResult.Ok, value); + + return ErrorResult; + } + + public void AlignToNextChar() + { + while (activeposition < activestring.Length && activestring[activeposition] != ' ') + activeposition++; + } + + public char this[int index] + { + get { return activestring[index]; } + } + + public string GetString() + { + return activestring; + } + + public void Reset() + { + activeposition = -1; + Current = null; + } + + public bool IsAtEnd() + { + return activestring.IsEmpty() || activeposition == activestring.Length; + } + + public int GetCurrentPosition() + { + return activeposition; + } + + public void SetCurrentPosition(int currentPosition) + { + activeposition = currentPosition; + } + + bool MoveNext(string delimiters) + { + //the stringtotokenize was never set: + if (activestring == null) + return false; + + //all tokens have already been extracted: + if (activeposition == activestring.Length) + return false; + + //bypass delimiters: + activeposition++; + while (activeposition < activestring.Length && delimiters.IndexOf(activestring[activeposition]) > -1) { - Player target = player.GetSelectedPlayer(); - if (target != null) - { - WorldSession session = target.GetSession(); - if (session != null) - return new AccountIdentifier(session); - } + activeposition++; } - return null; - } - } + //only delimiters were left, so return null: + if (activeposition == activestring.Length) + return false; - struct OptionalArg - { - private bool _hasValue; - public T Value; + //get starting position of string to return: + int startingposition = activeposition; - public OptionalArg(T value) - { - Value = value; - _hasValue = true; + //read until next delimiter: + do + { + activeposition++; + } while (activeposition < activestring.Length && delimiters.IndexOf(activestring[activeposition]) == -1); + + Current = activestring.Substring(startingposition, activeposition - startingposition); + return 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 optional) - { - return optional.Value; - } - - public static implicit operator OptionalArg(T value) - { - return new OptionalArg(value); - } - - public Type GetValueType() - { - return typeof(T); - } + private string activestring; + private int activeposition; + private string Current; } } diff --git a/Source/Game/Chat/CommandAttribute.cs b/Source/Game/Chat/CommandAttribute.cs index ee5fcc306..d0f278c61 100644 --- a/Source/Game/Chat/CommandAttribute.cs +++ b/Source/Game/Chat/CommandAttribute.cs @@ -76,4 +76,7 @@ namespace Game.Chat public CommandNonGroupAttribute(string command, CypherStrings help, RBACPermissions rbac, bool allowConsole = false) : base(command, help, rbac, allowConsole) { } public CommandNonGroupAttribute(string command, RBACPermissions rbac, bool allowConsole = false) : base(command, rbac, allowConsole) { } } + + [AttributeUsage(AttributeTargets.Parameter)] + public class OptionalArgAttribute : Attribute { } } diff --git a/Source/Game/Chat/CommandManager.cs b/Source/Game/Chat/CommandManager.cs index 0be09c559..b76eda723 100644 --- a/Source/Game/Chat/CommandManager.cs +++ b/Source/Game/Chat/CommandManager.cs @@ -114,14 +114,17 @@ namespace Game.Chat foreach (var method in type.GetMethods(BindingFlags.Static | BindingFlags.NonPublic)) { - CommandAttribute commandAttribute = method.GetCustomAttribute(false); - if (commandAttribute == null) + var commandAttributes = method.GetCustomAttributes(false).ToArray(); + if (commandAttributes.Length == 0) continue; - if (commandAttribute.GetType() == typeof(CommandNonGroupAttribute)) - continue; + foreach (var commandAttribute in commandAttributes) + { + if (commandAttribute.GetType() == typeof(CommandNonGroupAttribute)) + continue; - command.AddSubCommand(new ChatCommandNode(commandAttribute, method)); + command.AddSubCommand(new ChatCommandNode(commandAttribute, method)); + } } } @@ -161,7 +164,7 @@ namespace Game.Chat public SortedDictionary _subCommands = new(); MethodInfo _methodInfo; - Type[] parameterTypes; + ParameterInfo[] parameters; public ChatCommandNode(CommandAttribute attribute) { @@ -173,7 +176,7 @@ namespace Game.Chat public ChatCommandNode(CommandAttribute attribute, MethodInfo methodInfo) : this(attribute) { _methodInfo = methodInfo; - parameterTypes = (from parameter in methodInfo.GetParameters() select parameter.ParameterType).ToArray(); + parameters = methodInfo.GetParameters(); } public static bool TryExecuteCommand(CommandHandler handler, string cmdStr) @@ -221,7 +224,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))) + if (cmd.IsInvokerVisible(handler) && cmd.Invoke(handler, oldTail)) { /* invocation succeeded, log this */ if (!handler.IsConsole()) LogCommandUsage(handler.GetSession(), (uint)cmd._permission.RequiredPermission, cmdStr); @@ -283,7 +286,12 @@ namespace Game.Chat { handler.SendSysMessage(CypherStrings.AvailableCmds); foreach (var (name, command) in map) + { + if (!command.IsVisible(handler)) + continue; + handler.SendSysMessage(command.HasVisibleSubCommands(handler) ? CypherStrings.SubcmdsListEntryEllipsis : CypherStrings.SubcmdsListEntry, name); + } } else handler.SendSysMessage(CypherStrings.CmdInvalid, cmdStr); @@ -390,7 +398,7 @@ namespace Game.Chat _helpText = command._helpText; _helpString = command._helpString; _methodInfo = command._methodInfo; - parameterTypes = command.parameterTypes; + parameters = command.parameters; } else { @@ -399,13 +407,13 @@ namespace Game.Chat } } - public bool Invoke(CommandHandler handler, StringArguments args) + public bool Invoke(CommandHandler handler, string args) { - if (parameterTypes.Contains(typeof(StringArguments)))//Old system, can remove once all commands are changed. - return (bool)_methodInfo.Invoke(null, new object[] { handler, args }); + if (parameters.Any(p => p.ParameterType == typeof(StringArguments)))//Old system, can remove once all commands are changed. + return (bool)_methodInfo.Invoke(null, new object[] { handler, new StringArguments(args) }); else { - if (CommandArgs.Parse(out dynamic[] parseArgs, handler, parameterTypes, args)) + if (CommandArgs.Parse(out dynamic[] parseArgs, handler, parameters, args)) return (bool)_methodInfo.Invoke(null, parseArgs); return false; diff --git a/Source/Game/Chat/CommandTags.cs b/Source/Game/Chat/CommandTags.cs new file mode 100644 index 000000000..51278ca9d --- /dev/null +++ b/Source/Game/Chat/CommandTags.cs @@ -0,0 +1,194 @@ +/* + * Copyright (C) 2012-2020 CypherCore + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +using Game.Entities; +using System; + +namespace Game.Chat +{ + class PlayerIdentifier + { + string _name; + ObjectGuid _guid; + Player _player; + + public PlayerIdentifier(string name, ObjectGuid guid) + { + _name = name; + _guid = guid; + } + + public PlayerIdentifier(Player player) + { + _name = player.GetName(); + _guid = player.GetGUID(); + _player = player; + } + + public string GetName() { return _name; } + public ObjectGuid GetGUID() { return _guid; } + public bool IsConnected() { return _player != null; } + public Player GetConnectedPlayer() { return _player; } + + public static PlayerIdentifier FromTarget(CommandHandler handler) + { + Player player = handler.GetPlayer(); + if (player != null) + { + Player target = player.GetSelectedPlayer(); + if (target != null) + return new PlayerIdentifier(target); + } + + return null; + } + + public static PlayerIdentifier FromSelf(CommandHandler handler) + { + Player player = handler.GetPlayer(); + if (player != null) + return new PlayerIdentifier(player); + + return null; + } + + public static PlayerIdentifier FromTargetOrSelf(CommandHandler handler) + { + PlayerIdentifier fromTarget = FromTarget(handler); + if (fromTarget != null) + return fromTarget; + else + return FromSelf(handler); + } + + public static ParseStringResult ParseFromString(CommandArguments args) + { + var result = args.NextString(); + if (result != ParseResult.Ok) + return new ParseStringResult(ParseResult.Error); + + string arg = result.GetValue(); + + ulong guid = 0; + string name; + if (!Hyperlink.TryParse(out name, arg) || !ulong.TryParse(arg, out guid)) + name = arg; + + if (!name.IsEmpty()) + { + ObjectManager.NormalizePlayerName(ref name); + var player = Global.ObjAccessor.FindPlayerByName(name); + if (player != null) + return new ParseStringResult(ParseResult.Ok, new PlayerIdentifier(player)); + else + { + var objectGuid = Global.CharacterCacheStorage.GetCharacterGuidByName(name); + if (objectGuid.IsEmpty()) + return new ParseStringResult(ParseResult.Ok, new PlayerIdentifier(name, objectGuid)); + } + } + else if (guid != 0) + { + var player = Global.ObjAccessor.FindPlayerByLowGUID(guid); + if (player != null) + return new ParseStringResult(ParseResult.Ok, new PlayerIdentifier(player)); + } + + return new ParseStringResult(ParseResult.Error); + } + } + + class AccountIdentifier + { + uint _id; + string _name; + WorldSession _session; + + public AccountIdentifier(WorldSession session) + { + _id = session.GetAccountId(); + _name = session.GetAccountName(); + _session = session; + } + + public uint GetID() { return _id; } + public string GetName() { return _name; } + public bool IsConnected() { return _session != null; } + public WorldSession GetConnectedSession() { return _session; } + + public static ParseStringResult ParseFromString(CommandArguments args) + { + var result = args.NextString(); + if (result != ParseResult.Ok) + return new ParseStringResult(ParseResult.Error); + + // try parsing as account name + var session = Global.WorldMgr.FindSession(Global.AccountMgr.GetId(result.GetValue())); + if (session != null) // account with name exists, we are done + return new ParseStringResult(ParseResult.Ok, new AccountIdentifier(session)); + + // try parsing as account id + if (!uint.TryParse(result.GetValue(), out uint id)) + return new ParseStringResult(ParseResult.Error); + + session = Global.WorldMgr.FindSession(id); + if (session != null) + return new ParseStringResult(ParseResult.Ok, new AccountIdentifier(session)); + + return new ParseStringResult(ParseResult.Error); + } + + public static AccountIdentifier FromTarget(CommandHandler handler) + { + Player player = handler.GetPlayer(); + if (player != null) + { + Player target = player.GetSelectedPlayer(); + if (target != null) + { + WorldSession session = target.GetSession(); + if (session != null) + return new AccountIdentifier(session); + } + } + + return null; + } + } + + struct Tail + { + string str; + + public Tail(CommandArguments args) + { + str = args.NextString("").GetValue(); + } + + public bool IsEmpty() { return str.IsEmpty(); } + + public static implicit operator string(Tail tail) + { + return tail.str; + } + + public static ParseStringResult ParseFromString(CommandArguments args) + { + return new ParseStringResult(ParseResult.Ok, new Tail(args)); + } + } +} diff --git a/Source/Game/Chat/Commands/AccountCommands.cs b/Source/Game/Chat/Commands/AccountCommands.cs index e6917335a..f20d8b9d4 100644 --- a/Source/Game/Chat/Commands/AccountCommands.cs +++ b/Source/Game/Chat/Commands/AccountCommands.cs @@ -87,7 +87,7 @@ namespace Game.Chat } [Command("create", CypherStrings.CommandAccCreateHelp, RBACPermissions.CommandAccountCreate, true)] - static bool HandleAccountCreateCommand(CommandHandler handler, string accountName, string password, OptionalArg 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.ValueOr("")); + AccountOpResult result = Global.AccountMgr.CreateAccount(accountName, password, email); switch (result) { case AccountOpResult.Ok: @@ -221,7 +221,7 @@ namespace Game.Chat } [Command("password", CypherStrings.CommandAccPasswordHelp, RBACPermissions.CommandAccountPassword)] - static bool HandleAccountPasswordCommand(CommandHandler handler, string oldPassword, string newPassword, string confirmPassword, string confirmEmail) + static bool HandleAccountPasswordCommand(CommandHandler handler, string oldPassword, string newPassword, string confirmPassword, [OptionalArg] string confirmEmail) { // First, we check config. What security type (sec type) is it ? Depending on it, the command branches out uint pwConfig = WorldConfig.GetUIntValue(WorldCfg.AccPasschangesec); // 0 - PW_NONE, 1 - PW_EMAIL, 2 - PW_RBAC @@ -441,7 +441,7 @@ namespace Game.Chat class AccountSetCommands { [Command("addon", CypherStrings.CommandAccSetAddonHelp, RBACPermissions.CommandAccountSetAddon, true)] - static bool HandleAccountSetAddonCommand(CommandHandler handler, string accountName, byte expansion) + static bool HandleAccountSetAddonCommand(CommandHandler handler, [OptionalArg] string accountName, byte expansion) { uint accountId; if (!accountName.IsEmpty()) @@ -486,12 +486,6 @@ namespace Game.Chat return true; } - [Command("gmlevel", CypherStrings.CommandAccSetSeclevelHelp, RBACPermissions.CommandAccountSetSecLevel, true)] - static bool HandleAccountSetGmLevelCommand(CommandHandler handler, string accountName, byte securityLevel, int realmId = -1) - { - return HandleAccountSetSecLevelCommand(handler, accountName, securityLevel, realmId); - } - [Command("password", CypherStrings.CommandAccSetPasswordHelp, RBACPermissions.CommandAccountSetPassword, true)] static bool HandleAccountSetPasswordCommand(CommandHandler handler, string accountName, string password, string confirmPassword) { @@ -534,7 +528,8 @@ namespace Game.Chat } [Command("seclevel", CypherStrings.CommandAccSetSeclevelHelp, RBACPermissions.CommandAccountSetSecLevel, true)] - static bool HandleAccountSetSecLevelCommand(CommandHandler handler, string accountName, byte securityLevel, int? realmId) + [Command("gmlevel", CypherStrings.CommandAccSetSeclevelHelp, RBACPermissions.CommandAccountSetSecLevel, true)] + static bool HandleAccountSetSecLevelCommand(CommandHandler handler, [OptionalArg] string accountName, byte securityLevel, int? realmId) { uint accountId; if (!accountName.IsEmpty()) @@ -698,7 +693,5 @@ namespace Game.Chat } } } - - } } diff --git a/Source/Game/Chat/Commands/BNetAccountCommands.cs b/Source/Game/Chat/Commands/BNetAccountCommands.cs index a02d9e077..67a25b246 100644 --- a/Source/Game/Chat/Commands/BNetAccountCommands.cs +++ b/Source/Game/Chat/Commands/BNetAccountCommands.cs @@ -156,7 +156,7 @@ namespace Game.Chat.Commands handler.SendSysMessage("----------------------------------------------------"); do { - handler.SendSysMessage("| {10:0} | {1} | {2} |", accountList.Read(0), accountList.Read(1), formatDisplayName(accountList.Read(1))); + handler.SendSysMessage("| {0,10} | {1,16} | {2,16} |", accountList.Read(0), accountList.Read(1), formatDisplayName(accountList.Read(1))); } while (accountList.NextRow()); handler.SendSysMessage("----------------------------------------------------"); } diff --git a/Source/Game/Chat/Commands/CastCommands.cs b/Source/Game/Chat/Commands/CastCommands.cs index 77faa4457..867da7207 100644 --- a/Source/Game/Chat/Commands/CastCommands.cs +++ b/Source/Game/Chat/Commands/CastCommands.cs @@ -27,7 +27,7 @@ namespace Game.Chat class CastCommands { [Command("", RBACPermissions.CommandCast)] - static bool HandleCastCommand(CommandHandler handler, uint spellId, string triggeredStr) + static bool HandleCastCommand(CommandHandler handler, uint spellId, [OptionalArg] string triggeredStr) { Unit target = handler.GetSelectedUnit(); if (!target) @@ -48,7 +48,7 @@ namespace Game.Chat } [Command("back", RBACPermissions.CommandCastBack)] - static bool HandleCastBackCommand(CommandHandler handler, uint spellId, string triggeredStr) + static bool HandleCastBackCommand(CommandHandler handler, uint spellId, [OptionalArg] string triggeredStr) { Creature caster = handler.GetSelectedCreature(); if (!caster) @@ -70,7 +70,7 @@ namespace Game.Chat } [Command("dist", RBACPermissions.CommandCastDist)] - static bool HandleCastDistCommand(CommandHandler handler, uint spellId, float dist, string triggeredStr) + static bool HandleCastDistCommand(CommandHandler handler, uint spellId, float dist, [OptionalArg] string triggeredStr) { if (CheckSpellExistsAndIsValid(handler, spellId)) return false; @@ -88,7 +88,7 @@ namespace Game.Chat } [Command("self", RBACPermissions.CommandCastSelf)] - static bool HandleCastSelfCommand(CommandHandler handler, uint spellId, string triggeredStr) + static bool HandleCastSelfCommand(CommandHandler handler, uint spellId, [OptionalArg] string triggeredStr) { Unit target = handler.GetSelectedUnit(); if (!target) @@ -110,7 +110,7 @@ namespace Game.Chat } [Command("target", RBACPermissions.CommandCastTarget)] - static bool HandleCastTargetCommad(CommandHandler handler, uint spellId, string triggeredStr) + static bool HandleCastTargetCommad(CommandHandler handler, uint spellId, [OptionalArg] string triggeredStr) { Creature caster = handler.GetSelectedCreature(); if (!caster) @@ -138,7 +138,7 @@ namespace Game.Chat } [Command("dest", RBACPermissions.CommandCastDest)] - static bool HandleCastDestCommand(CommandHandler handler, uint spellId, float x, float y, float z, string triggeredStr) + static bool HandleCastDestCommand(CommandHandler handler, uint spellId, float x, float y, float z, [OptionalArg] string triggeredStr) { Unit caster = handler.GetSelectedUnit(); if (!caster) diff --git a/Source/Game/Chat/Commands/CharacterCommands.cs b/Source/Game/Chat/Commands/CharacterCommands.cs index 1f2c357c9..9040e93d3 100644 --- a/Source/Game/Chat/Commands/CharacterCommands.cs +++ b/Source/Game/Chat/Commands/CharacterCommands.cs @@ -77,7 +77,7 @@ namespace Game.Chat //rename characters [Command("rename", RBACPermissions.CommandCharacterRename, true)] - static bool HandleCharacterRenameCommand(CommandHandler handler, PlayerIdentifier player, string newName) + static bool HandleCharacterRenameCommand(CommandHandler handler, PlayerIdentifier player, [OptionalArg] string newName) { if (player == null && !newName.IsEmpty()) return false; @@ -469,7 +469,7 @@ namespace Game.Chat } [Command("list", RBACPermissions.CommandCharacterDeletedList, true)] - static bool HandleCharacterDeletedListCommand(CommandHandler handler, string needle) + static bool HandleCharacterDeletedListCommand(CommandHandler handler, [OptionalArg] string needle) { List foundList = new(); if (!GetDeletedCharacterInfoList(foundList, needle)) @@ -488,7 +488,7 @@ namespace Game.Chat } [Command("restore", RBACPermissions.CommandCharacterDeletedRestore, true)] - static bool HandleCharacterDeletedRestoreCommand(CommandHandler handler, string needle, string newCharName, AccountIdentifier newAccount) + static bool HandleCharacterDeletedRestoreCommand(CommandHandler handler, string needle, [OptionalArg] string newCharName, AccountIdentifier newAccount) { List foundList = new(); if (!GetDeletedCharacterInfoList(foundList, needle)) @@ -725,7 +725,7 @@ namespace Game.Chat class PdumpCommand { [Command("copy", RBACPermissions.CommandPdumpCopy, true)] - static bool HandlePDumpCopyCommand(CommandHandler handler, string playerName, string accountName, string characterName, ulong? characterGUID) + static bool HandlePDumpCopyCommand(CommandHandler handler, PlayerIdentifier player, AccountIdentifier account, [OptionalArg] string characterName, ulong? characterGUID) { /* std::string name; @@ -771,7 +771,7 @@ namespace Game.Chat } [Command("load", RBACPermissions.CommandPdumpLoad, true)] - static bool HandlePDumpLoadCommand(CommandHandler handler, string fileName, string accountName, string characterName, ulong? characterGuid) + static bool HandlePDumpLoadCommand(CommandHandler handler, string fileName, AccountIdentifier account, [OptionalArg] string characterName, ulong? characterGuid) { /* if (!AccountMgr.normalizeString(accountName)) diff --git a/Source/Game/Chat/Commands/LearnCommands.cs b/Source/Game/Chat/Commands/LearnCommands.cs index a0b3729a0..c486f641c 100644 --- a/Source/Game/Chat/Commands/LearnCommands.cs +++ b/Source/Game/Chat/Commands/LearnCommands.cs @@ -149,7 +149,7 @@ namespace Game.Chat.Commands } [Command("recipes", CypherStrings.CommandLearnAllRecipesHelp, RBACPermissions.CommandLearnAllRecipes)] - static bool HandleLearnAllRecipesCommand(CommandHandler handler, string namePart) + static bool HandleLearnAllRecipesCommand(CommandHandler handler, Tail namePart) { // Learns all recipes of specified profession and sets skill to max // Example: .learn all_recipes enchanting diff --git a/Source/Game/Chat/Commands/ListCommands.cs b/Source/Game/Chat/Commands/ListCommands.cs index 1aa935baa..8678f7ea9 100644 --- a/Source/Game/Chat/Commands/ListCommands.cs +++ b/Source/Game/Chat/Commands/ListCommands.cs @@ -578,7 +578,7 @@ namespace Game.Chat.Commands } [Command("name", RBACPermissions.CommandListAuras)] - static bool HandleListAurasByNameCommand(CommandHandler handler, string namePart) + static bool HandleListAurasByNameCommand(CommandHandler handler, Tail namePart) { return ListAurasCommand(handler, null, namePart); } diff --git a/Source/Game/Chat/Commands/MessageCommands.cs b/Source/Game/Chat/Commands/MessageCommands.cs index 32f70848b..d92d28869 100644 --- a/Source/Game/Chat/Commands/MessageCommands.cs +++ b/Source/Game/Chat/Commands/MessageCommands.cs @@ -28,7 +28,7 @@ namespace Game.Chat class MessageCommands { [CommandNonGroup("nameannounce", RBACPermissions.CommandNameannounce, true)] - static bool HandleNameAnnounceCommand(CommandHandler handler, string message) + static bool HandleNameAnnounceCommand(CommandHandler handler, Tail message) { if (message.IsEmpty()) return false; @@ -43,7 +43,7 @@ namespace Game.Chat } [CommandNonGroup("gmnameannounce", RBACPermissions.CommandGmnameannounce, true)] - static bool HandleGMNameAnnounceCommand(CommandHandler handler, string message) + static bool HandleGMNameAnnounceCommand(CommandHandler handler, Tail message) { if (message.IsEmpty()) return false; @@ -58,7 +58,7 @@ namespace Game.Chat } [CommandNonGroup("announce", RBACPermissions.CommandAnnounce, true)] - static bool HandleAnnounceCommand(CommandHandler handler, string message) + static bool HandleAnnounceCommand(CommandHandler handler, Tail message) { if (message.IsEmpty()) return false; @@ -68,7 +68,7 @@ namespace Game.Chat } [CommandNonGroup("gmannounce", RBACPermissions.CommandGmannounce, true)] - static bool HandleGMAnnounceCommand(CommandHandler handler, string message) + static bool HandleGMAnnounceCommand(CommandHandler handler, Tail message) { if (message.IsEmpty()) return false; @@ -78,7 +78,7 @@ namespace Game.Chat } [CommandNonGroup("notify", RBACPermissions.CommandNotify, true)] - static bool HandleNotifyCommand(CommandHandler handler, string message) + static bool HandleNotifyCommand(CommandHandler handler, Tail message) { if (message.IsEmpty()) return false; @@ -92,7 +92,7 @@ namespace Game.Chat } [CommandNonGroup("gmnotify", RBACPermissions.CommandGmnotify, true)] - static bool HandleGMNotifyCommand(CommandHandler handler, string message) + static bool HandleGMNotifyCommand(CommandHandler handler, Tail message) { if (message.IsEmpty()) return false; @@ -106,7 +106,7 @@ namespace Game.Chat } [CommandNonGroup("whispers", RBACPermissions.CommandWhispers)] - static bool HandleWhispersCommand(CommandHandler handler, bool? operationArg) + static bool HandleWhispersCommand(CommandHandler handler, bool? operationArg, [OptionalArg] string playerNameArg) { if (!operationArg.HasValue) { @@ -118,6 +118,7 @@ namespace Game.Chat { handler.GetSession().GetPlayer().SetAcceptWhispers(true); handler.SendSysMessage(CypherStrings.CommandWhisperon); + return true; } else { @@ -125,9 +126,33 @@ namespace Game.Chat handler.GetSession().GetPlayer().ClearWhisperWhiteList(); handler.GetSession().GetPlayer().SetAcceptWhispers(false); handler.SendSysMessage(CypherStrings.CommandWhisperoff); + return true; } - return true; + //todo fix me + /*if (operationArg->holds_alternative < EXACT_SEQUENCE("remove") > ()) + { + if (!playerNameArg) + return false; + + if (normalizePlayerName(*playerNameArg)) + { + if (Player * player = ObjectAccessor::FindPlayerByName(*playerNameArg)) + { + handler->GetSession()->GetPlayer()->RemoveFromWhisperWhiteList(player->GetGUID()); + handler->PSendSysMessage(LANG_COMMAND_WHISPEROFFPLAYER, playerNameArg->c_str()); + return true; + } + else + { + handler->PSendSysMessage(LANG_PLAYER_NOT_FOUND, playerNameArg->c_str()); + handler->SetSentErrorMessage(true); + return false; + } + } + } + handler.SendSysMessage(CypherStrings.UseBol); + return false;*/ } } diff --git a/Source/Game/Chat/Commands/MiscCommands.cs b/Source/Game/Chat/Commands/MiscCommands.cs index 0e3b0ba14..056a1ebc6 100644 --- a/Source/Game/Chat/Commands/MiscCommands.cs +++ b/Source/Game/Chat/Commands/MiscCommands.cs @@ -733,10 +733,10 @@ namespace Game.Chat } [CommandNonGroup("help", RBACPermissions.CommandHelp, true)] - static bool HandleHelpCommand(CommandHandler handler, OptionalArg cmd) + static bool HandleHelpCommand(CommandHandler handler, Tail cmd) { - ChatCommandNode.SendCommandHelpFor(handler, cmd.ValueOr("")); - if (!cmd.HasValue) + ChatCommandNode.SendCommandHelpFor(handler, cmd); + if (cmd.IsEmpty()) ChatCommandNode.SendCommandHelpFor(handler, "help"); return true; @@ -835,7 +835,7 @@ namespace Game.Chat } [CommandNonGroup("linkgrave", RBACPermissions.CommandLinkgrave)] - static bool HandleLinkGraveCommand(CommandHandler handler, uint graveyardId, string teamArg) + static bool HandleLinkGraveCommand(CommandHandler handler, uint graveyardId, [OptionalArg] string teamArg) { Team team; if (teamArg.IsEmpty()) @@ -1005,10 +1005,11 @@ namespace Game.Chat // mute player for the specified duration [CommandNonGroup("mute", RBACPermissions.CommandMute, true)] - static bool HandleMuteCommand(CommandHandler handler, PlayerIdentifier player, uint muteTime, string muteReason) + static bool HandleMuteCommand(CommandHandler handler, PlayerIdentifier player, uint muteTime, Tail muteReason) { + string muteReasonStr = muteReason; if (muteReason.IsEmpty()) - muteReason = handler.GetCypherString(CypherStrings.NoReason); + muteReasonStr = handler.GetCypherString(CypherStrings.NoReason); if (player == null) player = PlayerIdentifier.FromTarget(handler); @@ -1053,7 +1054,7 @@ namespace Game.Chat stmt.AddValue(0, -(muteTime * Time.Minute)); } - stmt.AddValue(1, muteReason); + stmt.AddValue(1, muteReasonStr); stmt.AddValue(2, muteBy); stmt.AddValue(3, accountId); DB.Login.Execute(stmt); @@ -1062,21 +1063,21 @@ namespace Game.Chat stmt.AddValue(0, accountId); stmt.AddValue(1, muteTime); stmt.AddValue(2, muteBy); - stmt.AddValue(3, muteReason); + stmt.AddValue(3, muteReasonStr); DB.Login.Execute(stmt); string nameLink = handler.PlayerLink(player.GetName()); if (WorldConfig.GetBoolValue(WorldCfg.ShowMuteInWorld)) - Global.WorldMgr.SendWorldText(CypherStrings.CommandMutemessageWorld, muteBy, nameLink, muteTime, muteReason); + Global.WorldMgr.SendWorldText(CypherStrings.CommandMutemessageWorld, muteBy, nameLink, muteTime, muteReasonStr); if (target) { - target.SendSysMessage(CypherStrings.YourChatDisabled, muteTime, muteBy, muteReason); - handler.SendSysMessage(CypherStrings.YouDisableChat, nameLink, muteTime, muteReason); + target.SendSysMessage(CypherStrings.YourChatDisabled, muteTime, muteBy, muteReasonStr); + handler.SendSysMessage(CypherStrings.YouDisableChat, nameLink, muteTime, muteReasonStr); } else { - handler.SendSysMessage(CypherStrings.CommandDisableChatDelayed, nameLink, muteTime, muteReason); + handler.SendSysMessage(CypherStrings.CommandDisableChatDelayed, nameLink, muteTime, muteReasonStr); } return true; @@ -1119,7 +1120,7 @@ namespace Game.Chat } [CommandNonGroup("neargrave", RBACPermissions.CommandNeargrave)] - static bool HandleNearGraveCommand(CommandHandler handler, string teamArg) + static bool HandleNearGraveCommand(CommandHandler handler, [OptionalArg] string teamArg) { Team team; if (teamArg.IsEmpty()) @@ -1890,7 +1891,7 @@ namespace Game.Chat } [CommandNonGroup("unfreeze", RBACPermissions.CommandUnfreeze)] - static bool HandleUnFreezeCommand(CommandHandler handler, string targetNameArg) + static bool HandleUnFreezeCommand(CommandHandler handler, [OptionalArg] string targetNameArg) { string name = ""; Player player; @@ -2267,7 +2268,7 @@ namespace Game.Chat } [Command("set", RBACPermissions.CommandAdditemset)] - static bool HandleAddItemSetCommand(CommandHandler handler, uint itemSetId, string bonuses, string context) + static bool HandleAddItemSetCommand(CommandHandler handler, uint itemSetId, [OptionalArg] string bonuses, byte? context) { // prevent generation all items with itemset field value '0' if (itemSetId == 0) @@ -2290,8 +2291,8 @@ namespace Game.Chat } ItemContext itemContext = ItemContext.None; - if (!context.IsEmpty()) - itemContext = context.ToEnum(); + if (context.HasValue) + itemContext = (ItemContext)context; Player player = handler.GetSession().GetPlayer(); Player playerTarget = handler.GetSelectedPlayer(); diff --git a/Source/Game/Chat/Commands/NPCCommands.cs b/Source/Game/Chat/Commands/NPCCommands.cs index 507369293..5c6281d6c 100644 --- a/Source/Game/Chat/Commands/NPCCommands.cs +++ b/Source/Game/Chat/Commands/NPCCommands.cs @@ -283,7 +283,7 @@ namespace Game.Chat } [Command("say", RBACPermissions.CommandNpcSay)] - static bool HandleNpcSayCommand(CommandHandler handler, string text) + static bool HandleNpcSayCommand(CommandHandler handler, Tail text) { if (text.IsEmpty()) return false; @@ -298,7 +298,7 @@ namespace Game.Chat creature.Say(text, Language.Universal); // make some emotes - switch (text.LastOrDefault()) + switch (((string)text).LastOrDefault()) { case '?': creature.HandleEmoteCommand(Emote.OneshotQuestion); @@ -480,7 +480,7 @@ namespace Game.Chat } [Command("textemote", RBACPermissions.CommandNpcTextemote)] - static bool HandleNpcTextEmoteCommand(CommandHandler handler, string text) + static bool HandleNpcTextEmoteCommand(CommandHandler handler, Tail text) { Creature creature = handler.GetSelectedCreature(); if (!creature) @@ -495,7 +495,7 @@ namespace Game.Chat } [Command("whisper", RBACPermissions.CommandNpcWhisper)] - static bool HandleNpcWhisperCommand(CommandHandler handler, string recv, string text) + static bool HandleNpcWhisperCommand(CommandHandler handler, string recv, Tail text) { if (text.IsEmpty()) { @@ -520,7 +520,7 @@ namespace Game.Chat } [Command("yell", RBACPermissions.CommandNpcYell)] - static bool HandleNpcYellCommand(CommandHandler handler, string text) + static bool HandleNpcYellCommand(CommandHandler handler, Tail text) { if (text.IsEmpty()) return false; @@ -625,7 +625,7 @@ namespace Game.Chat } [Command("item", RBACPermissions.CommandNpcAddItem)] - static bool HandleNpcAddVendorItemCommand(CommandHandler handler, uint itemId, uint? mc, uint? it, uint? ec, string bonusListIds) + static bool HandleNpcAddVendorItemCommand(CommandHandler handler, uint itemId, uint? mc, uint? it, uint? ec, [OptionalArg] string bonusListIds) { if (itemId == 0) { @@ -740,7 +740,7 @@ namespace Game.Chat } [Command("temp", RBACPermissions.CommandNpcAddTemp)] - static bool HandleNpcAddTempSpawnCommand(CommandHandler handler, string lootStr, uint id) + static bool HandleNpcAddTempSpawnCommand(CommandHandler handler, [OptionalArg] string lootStr, uint id) { bool loot = false; if (!lootStr.IsEmpty()) diff --git a/Source/Game/Chat/Commands/TeleCommands.cs b/Source/Game/Chat/Commands/TeleCommands.cs index e8a0faea8..1b894e060 100644 --- a/Source/Game/Chat/Commands/TeleCommands.cs +++ b/Source/Game/Chat/Commands/TeleCommands.cs @@ -333,14 +333,16 @@ namespace Game.Chat } [Command("name", RBACPermissions.CommandTeleName, true)] - static bool HandleTeleNameNpcNameCommand(CommandHandler handler, PlayerIdentifier player, string name) + static bool HandleTeleNameNpcNameCommand(CommandHandler handler, PlayerIdentifier player, Tail name) { + string normalizedName = name; + if (player == null) return false; - DB.World.EscapeString(ref name); + DB.World.EscapeString(ref normalizedName); - SQLResult result = DB.World.Query($"SELECT c.position_x, c.position_y, c.position_z, c.orientation, c.map, ct.name FROM creature c INNER JOIN creature_template ct ON c.id = ct.entry WHERE ct.name LIKE '{name}'"); + SQLResult result = DB.World.Query($"SELECT c.position_x, c.position_y, c.position_z, c.orientation, c.map, ct.name FROM creature c INNER JOIN creature_template ct ON c.id = ct.entry WHERE ct.name LIKE '{normalizedName}'"); if (result.IsEmpty()) { handler.SendSysMessage(CypherStrings.CommandGocreatnotfound); diff --git a/Source/Game/Chat/Hyperlink.cs b/Source/Game/Chat/Hyperlink.cs index a1e904b10..075e48aa7 100644 --- a/Source/Game/Chat/Hyperlink.cs +++ b/Source/Game/Chat/Hyperlink.cs @@ -15,12 +15,7 @@ * along with this program. If not, see . */ -using Framework.Constants; -using Framework.IO; -using Game.DataStorage; -using Game.Spells; using System; -using System.Collections.Generic; namespace Game.Chat { @@ -39,7 +34,7 @@ namespace Game.Chat return true; } - public static bool TryParse(out dynamic value, Type type, StringArguments args) + public static bool TryParse(out dynamic value, Type type, CommandArguments args) { value = default; @@ -77,10 +72,10 @@ namespace Game.Chat switch (type.Name) { case nameof(PlayerIdentifier): - value = PlayerIdentifier.ParseFromString(args.NextString()); + value = PlayerIdentifier.ParseFromString(args); break; case nameof(AccountIdentifier): - value = AccountIdentifier.ParseFromString(args.NextString()); + value = AccountIdentifier.ParseFromString(args); break; default: return false;