diff --git a/Source/Framework/Constants/AccountConst.cs b/Source/Framework/Constants/AccountConst.cs index 1a851b8ac..b94ee0890 100644 --- a/Source/Framework/Constants/AccountConst.cs +++ b/Source/Framework/Constants/AccountConst.cs @@ -753,6 +753,7 @@ namespace Framework.Constants // 878-879 previously used, do not reuse CommandPdumpCopy = 880, CommandReloadVehicleTemplate = 881, + CommandReloadSpellScriptNames = 882, // Custom Permissions 1000+ Max } diff --git a/Source/Framework/Constants/Language.cs b/Source/Framework/Constants/Language.cs index 7060c2db9..288610168 100644 --- a/Source/Framework/Constants/Language.cs +++ b/Source/Framework/Constants/Language.cs @@ -74,10 +74,10 @@ namespace Framework.Constants Systemmessage = 3, Eventmessage = 4, NoHelpCmd = 5, - NoCmd = 6, - NoSubcmd = 7, + CmdInvalid = 6, + SubcmdAmbiguous = 7, SubcmdsList = 8, - AvailableCmd = 9, + AvailableCmds = 9, CmdSyntax = 10, AccountLevel = 11, ConnectedUsers = 12, @@ -155,9 +155,15 @@ namespace Framework.Constants GoinfoSize = 84, GoinfoAddon = 85, GoinfoModel = 86, - // Free 87 - 95 - - + UnknownError = 87, + TwoFACommandsNotSetup = 88, + TwoFAAlreadySetup = 89, + TwoFAInvalidToken = 90, + TwoFASecretSuggestion = 91, + TwoFASetupComplete = 92, + TwoFANotSetup = 93, + TwoFARemoveNeedToken = 94, + TwoFARemoveComplete = 95, GuildRenameAlreadyExists = 96, GuildRenameDone = 97, RenamePlayerAlreadyExists = 98, @@ -190,7 +196,7 @@ namespace Framework.Constants YouChangeEnergy = 122, YoursEnergyChanged = 123, - CurrentEnergy = 124, + CurrentEnergy = 124, //Log YouChangeRage = 125, YoursRageChanged = 126, YouChangeLvl = 127, @@ -259,10 +265,19 @@ namespace Framework.Constants PhaseFlagCosmetic = 183, PhaseFlagPersonal = 184, - // 185 not used + // 185 Not Used TransportPosition = 186, PartialGroupSummon = 187, - // Room For More Level 1 188-199 not used + TwoFASecretTooLong = 188, + TwoFASecretInvalid = 189, + TwoFASecretSetComplete = 190, + SubcmdsListEntry = 191, + SubcmdsListEntryEllipsis = 192, + SubcmdInvalid = 193, + CmdAmbiguous = 194, + CmdHelpGeneric = 195, + CmdNoHelpAvailable = 196, + // Room For More Level 1 197-199 Not Used // Level 2 Chat NoSelection = 200, @@ -362,14 +377,14 @@ namespace Framework.Constants CommandWhisperoff = 286, CommandCreatguidnotfound = 287, CommandNotDeadOrNoLoot = 288, - CommandNpcShowLootHeader = 289, - CommandNpcShowLootLabel = 290, - CommandNpcShowLootEntry = 291, - CommandNpcShowLootMoney = 292, - CommandNpcShowLootLabel2 = 293, - CommandNpcShowLootSublabel = 294, - CommandNpcShowLootEntry2 = 295, - // 296 free + CommandNpcShowlootHeader = 289, + CommandNpcShowlootLabel = 290, + CommandNpcShowlootEntry = 291, + CommandNpcShowlootMoney = 292, + CommandNpcShowlootLabel2 = 293, + CommandNpcShowlootSublabel = 294, + CommandNpcShowlootEntry2 = 295, + // 296 Free // End CommandWanderDistance = 297, @@ -442,7 +457,37 @@ namespace Framework.Constants CommandCheatWw = 362, CommandWhisperoffplayer = 363, CommandCheatTaxinodes = 364, - // Room For More Level 2 365-399 Not Used + CommandAchievementAddHelp = 365, + CommandAccSetAddonHelp = 366, + CommandAccSetSecRegmailHelp = 367, + CommandAccSetSecEmailHelp = 368, + CommandAccSet2faHelp = 369, + CommandAccSetSeclevelHelp = 370, + CommandAccSetPasswordHelp = 371, + CommandAcc2faSetupHelp = 372, + CommandAcc2faRemoveHelp = 373, + CommandAccAddonHelp = 374, + CommandAccCreateHelp = 375, + CommandAccDeleteHelp = 376, + CommandAccEmailHelp = 377, + CommandAccOnlinelistHelp = 378, + CommandAccLockCountryHelp = 379, + CommandAccLockIpHelp = 380, + CommandAccPasswordHelp = 381, + CommandAccountHelp = 382, + CommandLearnHelp = 383, + CommandUnlearnHelp = 384, + CommandLearnMyQuestsHelp = 385, + CommandLearnMyTrainerHelp = 386, + CommandLearnAllBlizzardHelp = 387, + CommandLearnAllDebugHelp = 388, + CommandLearnAllCraftsHelp = 389, + CommandLearnAllDefaultHelp = 390, + CommandLearnAllLanguagesHelp = 391, + CommandLearnAllRecipesHelp = 392, + CommandLearnAllTalentsHelp = 393, + CommandLearnAllPettalentHelp = 394, + // Room For More Level 2 395-399 Not Used // Level 3 Chat ScriptsReloaded = 400, @@ -504,7 +549,7 @@ namespace Framework.Constants CommandGraveyardalrlinked = 450, CommandGraveyardlinked = 451, CommandGraveyardwrongzone = 452, - // = 453, See PinfoPlayer + // = 453, See PinfoPlayer CommandGraveyarderror = 454, CommandGraveyardNoteam = 455, CommandGraveyardAny = 456, @@ -515,7 +560,7 @@ namespace Framework.Constants CommandZonenografaction = 461, CommandTpAlreadyexist = 462, CommandTpAdded = 463, - CommandTpAddedError = 464, + CommandTpAddedErr = 464, CommandTpDeleted = 465, CommandNotaxinodefound = 466, CommandTargetListauras = 467, @@ -595,7 +640,7 @@ namespace Framework.Constants MovegensIdle = 527, MovegensRandom = 528, MovegensWaypoint = 529, - // = 530, not used + // = 530, Not Used MovegensConfused = 531, MovegensChasePlayer = 532, MovegensChaseCreature = 533, @@ -615,9 +660,9 @@ namespace Framework.Constants NpcinfoTrainer = 546, NpcinfoDungeonId = 547, - // = 548, See PinfoGmActive - // = 549, See PinfoBanned - // = 550, See PinfoMuted + // = 548, See PinfoGmActive + // = 549, See PinfoBanned + // = 550, See PinfoMuted YouSetExploreAll = 551, YouSetExploreNothing = 552, @@ -678,11 +723,12 @@ namespace Framework.Constants Gmlist = 597, GmlistHeader = 598, GmlistEmpty = 599, + RemoveitemFailure = 600, // End Level 3 List, Continued At 1100 - // 601-704 - free + // 601-704 - Free WaitBeforeSpeaking = 705, NotEquippedItem = 706, @@ -694,9 +740,9 @@ namespace Framework.Constants BgQueueAnnounceSelf = 711, BgQueueAnnounceWorld = 712, YourArenaLevelReqError = 713, - // = 714, See PinfoAccAccount + // = 714, See PinfoAccAccount YourBgLevelReqError = 715, - // = 716, See PinfoAccLastlogin + // = 716, See PinfoAccLastlogin BgStartedAnnounceWorld = 717, ArenaQueueAnnounceWorldJoin = 718, ArenaQueueAnnounceWorldExit = 719, @@ -705,7 +751,7 @@ namespace Framework.Constants ArenaGroupTooLarge = 721, // "Your Group Is Too Large For This Arena. Please Regroup To Join." ArenaYourTeamOnly = 722, // "Your Group Has Members Not In Your Arena Team. Please Regroup To Join." ArenaNotEnoughPlayers = 723, // "Your Group Does Not Have Enough Players To Join This Match." - // 724-726 - free + // 724-726 - Free BgGroupOfflineMember = 727, // "Your Group Has An Offline Member. Please Remove Him Before Joining." BgGroupMixedFaction = 728, // "Your Group Has Players From The Opposing Faction. You Can'T Join The Battleground As A Group." BgGroupMixedLevels = 729, // "Your Group Has Players From Different Battleground Brakets. You Can'T Join As Group." @@ -721,24 +767,25 @@ namespace Framework.Constants DebugArenaOff = 738, DebugBgOn = 739, DebugBgOff = 740, - // DistArenaPointsStart = 741, - // DistArenaPointsOnlineStart = 742, - // DistArenaPointsOnlineEnd = 743, - // DistArenaPointsTeamStart = 744, - // DistArenaPointsTeamEnd = 745, - // DistArenaPointsEnd = 746, + DistArenaPointsStart = 741, // 3.3.5 Reserved + DistArenaPointsOnlineStart = 742, // 3.3.5 Reserved + DistArenaPointsOnlineEnd = 743, // 3.3.5 Reserved + DistArenaPointsTeamStart = 744, // 3.3.5 Reserved + DistArenaPointsTeamEnd = 745, // 3.3.5 Reserved + DistArenaPointsEnd = 746, // 3.3.5 Reserved BgDisabled = 747, ArenaDisabled = 748, - // = 749, See PinfoAccOs + // = 749, See PinfoAccOs BattlegroundPrematureFinishWarning = 750, // "Not Enough Players. This Game Will Close In %U Mins." BattlegroundPrematureFinishWarningSecs = 751, // "Not Enough Players. This Game Will Close In %U Seconds." - // = 752, See PinfoAccIp - // 753-755 - free - // Room For Bg/Arena = 773-784 + // = 752, See PinfoAccIp + // 753-755 - Free + + // Room For Bg/Arena = 773-784 ArenaTesting = 785, AutoAnn = 786, AnnounceColor = 787, - // 788-799 - free + // 788-799 - Free // In Game Strings PetInvalidName = 800, @@ -751,7 +798,7 @@ namespace Framework.Constants NeedCharacterName = 807, PlayerNotExistOrOffline = 808, AccountForPlayerNotFound = 809, - // Unused = 810, + // Unused = 810, GuildMaster = 811, GuildOfficer = 812, GuildVeteran = 813, @@ -806,7 +853,7 @@ namespace Framework.Constants ArenaInfoHeader = 868, ArenaInfoMembers = 869, ArenaLookup = 870, - // = 871, See PinfoChrLevelHigh + // = 871, See PinfoChrLevelHigh CommandWrongemail = 872, NewEmailsNotMatch = 873, CommandEmail = 874, @@ -814,12 +861,12 @@ namespace Framework.Constants CommandNotchangeemail = 876, OldEmailIsNewEmail = 877, CommandEmailOutput = 878, - // = 879, See PinfoChrRegmails + // = 879, See PinfoChrRegmails AccountSecType = 880, RbacEmailRequired = 881, - // = 882, LANG_PINFO_CHR_MAP_WITH_AREA + // = 882, PinfoChrMapWithArea Account = 883, - // Room For In-Game Strings 884-999 Not Used + // Room For In-Game Strings 884-999 Not Used // Level 4 (Cli Only Commands) CommandExit = 1000, @@ -858,7 +905,7 @@ namespace Framework.Constants AccountCreatedBnet = 1033, AccountBnetListHeader = 1034, AccountBnetListNoAccounts = 1035, - // Room For More Level 4 1036-1099 Not Used + // Room For More Level 4 1036-1099 Not Used // Level 3 (Continue) AccountSetaddon = 1100, @@ -945,7 +992,7 @@ namespace Framework.Constants GuildInfoBankGold = 1181, GuildInfoMotd = 1182, GuildInfoExtraInfo = 1183, - ChangeAccountSuccess = 1184, // log + ChangeAccountSuccess = 1184, // Log GroupNotInRaidGroup = 1185, GroupRoleChanged = 1186, LeaderCannotBeAssistant = 1187, @@ -953,14 +1000,14 @@ namespace Framework.Constants CommandNoInstancesMatch = 1189, CommandMultipleInstancesMatch = 1190, CommandMultipleInstancesEntry = 1191, - // 1192 unused, + // 1192 Unused CommandInstanceNoEntrance = 1193, CommandInstanceNoExit = 1194, CommandWentToInstanceGate = 1195, CommandWentToInstanceStart = 1196, CommandGoInstanceGateFailed = 1197, CommandGoInstanceStartFailed = 1198, - // Room for more level 3 1199 not used + // Room For More Level 3 1199 Not Used // Debug Commands CinematicNotExist = 1200, @@ -983,8 +1030,9 @@ namespace Framework.Constants AccountBnetUnlinked = 1216, AccountBnetNotLinked = 1217, DisallowTicketsConfig = 1218, - // 1219-1499 - free + // 1219-1499 - Free + // Command Argument Parsers CmdparserEither = 1500, CmdparserOr = 1501, CmdparserStringValueInvalid = 1502, @@ -1003,15 +1051,20 @@ namespace Framework.Constants CmdparserExactSeqMismatch = 1515, CmdparserCurrencyNoExist = 1516, - // 1516-1998 - free + // 1516-1998 - Free DebugAreatriggerLeft = 1999, - // Ticket Strings 2003-2028 + // Ticket Strings 2000-2030 + CommandTicketnew = 2000, // 3.3.5 Reserved + CommandTicketupdated = 2001, // 3.3.5 Reserved + CommandTicketplayerabandon = 2002, // 3.3.5 Reserved CommandTicketclosed = 2003, CommandTicketdeleted = 2004, CommandTicketnotexist = 2005, CommandTicketclosefirst = 2006, CommandTicketalreadyassigned = 2007, + CommandTicketreload = 2008, // 3.3.5 Reserved CommandTicketshowlist = 2009, + CommandTicketshowonlinelist = 2010, // 3.3.5 Reserved CommandTicketshowclosedlist = 2011, CommandTicketassignerrorA = 2012, CommandTicketassignerrorB = 2013, @@ -1020,16 +1073,20 @@ namespace Framework.Constants CommandTicketcannotclose = 2016, CommandTicketlistguid = 2017, CommandTicketlistname = 2018, + CommandTicketlistage = 2019, // 3.3.5 Reserved CommandTicketlistassignedto = 2020, CommandTicketlistunassigned = 2021, CommandTicketlistmessage = 2022, CommandTicketlistcomment = 2023, CommandTicketlistaddcomment = 2024, CommandTicketlistagecreate = 2025, + CommandTicketshowescalatedlist = 2026, // 3.3.5 Reserved CommandTicketpending = 2027, CommandTicketreset = 2028, + CommandTicketlistresponse = 2029, // 3.3.5 Reserved + CommandTicketcompleted = 2030, // 3.3.5 Reserved - // Trinity Strings 5000-9999 + // Trinity Strings 5000-9999 CommandFreeze = 5000, CommandFreezeError = 5001, CommandFreezeWrong = 5002, @@ -1049,7 +1106,7 @@ namespace Framework.Constants Battleground = 5015, Arena = 5016, Raid = 5017, - NpcinfoReactState = 5018, + NpcinfoReactstate = 5018, CommandTempFrozenPlayer = 5019, NpcinfoPhases = 5020, NpcinfoArmor = 5021, @@ -1062,7 +1119,7 @@ namespace Framework.Constants GoinfoLootid = 5028, CommandLookupMaxResults = 5029, Unauthorized = 5030, - ObjectInfoAIInfo = 5031, + ObjectinfoAiInfo = 5031, CommandNoBattlegroundFound = 5032, CommandNoAchievementCriteriaFound = 5033, CommandNoOutdoorPvpForund = 5034, @@ -1120,17 +1177,16 @@ namespace Framework.Constants ListRespawnsZone = 5078, ListRespawnsListheader = 5079, ListRespawnsOverdue = 5080, - // unused 5081 - // unused 5082 - ObjectInfoAIType = 5083, - + // Unused 5081 + // Unused 5082 + ObjectinfoAiType = 5083, NpcinfoUnitFieldFlags2 = 5084, NpcinfoUnitFieldFlags3 = 5085, NpcinfoNpcFlags = 5086, NpcinfoPhaseIds = 5087, Scenario = 5088, - // Room For More Trinity Strings 5089-6603 + // Room For More Trinity Strings 5089-6603 // Level Requirement Notifications SayReq = 6604, @@ -1148,7 +1204,7 @@ namespace Framework.Constants GmNotify = 6614, GmAnnounceColor = 6615, - GmSilence = 6616, // "Silence Is On For %S" - Spell 1852 + GmSilence = 6616, // "Silence Is On For %S" - Spell 1852 WorldClosed = 7523, WorldOpened = 7524, @@ -1174,8 +1230,8 @@ namespace Framework.Constants LfgRoleNone = 9998, LfgError = 9999, - // Use For Not-In-Offcial-Sources Patches - // 10000-10999 + // Use For Not-In-Official-Sources Patches + // 10000-10999 // Opvp Si OpvpSiCaptureH = 10049, OpvpSiCaptureA = 10050, @@ -1186,9 +1242,9 @@ namespace Framework.Constants OpvpZmGossipAlliance = 10054, OpvpZmGossipHorde = 10055, - // 10056-10066 - free + // 10056-10066 - Free - // Use For Custom Patches 11000-11999 + // Use For Custom Patches 11000-11999 AutoBroadcast = 11000, InvalidRealmid = 11001, diff --git a/Source/Framework/IO/StringArguments.cs b/Source/Framework/IO/StringArguments.cs index 833ea2738..7d7110b3a 100644 --- a/Source/Framework/IO/StringArguments.cs +++ b/Source/Framework/IO/StringArguments.cs @@ -236,7 +236,7 @@ namespace Framework.IO public bool IsAtEnd() { - return activeposition == activestring.Length; + return activestring.IsEmpty() || activeposition == activestring.Length; } public int GetCurrentPosition() diff --git a/Source/Framework/Util/Extensions.cs b/Source/Framework/Util/Extensions.cs index 55b267891..614ec3f12 100644 --- a/Source/Framework/Util/Extensions.cs +++ b/Source/Framework/Util/Extensions.cs @@ -322,6 +322,9 @@ namespace System public static bool Like(this string toSearch, string toFind) { + if (toSearch == null || toFind == null) + return false; + return toSearch.ToLower().Contains(toFind.ToLower()); } @@ -386,6 +389,34 @@ namespace System throw new Exception("Unsuccessful Match."); } } + + public static (string token, string tail) Tokenize(this string args) + { + string token; + string tail = ""; + + int delimPos = args.IndexOf(' '); + if (delimPos != -1) + { + token = args.Substring(0, delimPos); + int tailPos = args.FindFirstNotOf(" ", delimPos); + if (tailPos != -1) + tail = args.Substring(tailPos); + } + else + token = args; + + return (token, tail); + } + + public static int FindFirstNotOf(this string source, string chars, int pos) + { + for (int i = pos; i < source.Length; i++) + if (chars.IndexOf(source[i]) == -1) + return i; + + return -1; + } #endregion #region BinaryReader diff --git a/Source/Game/Chat/CommandArgs.cs b/Source/Game/Chat/CommandArgs.cs index 3e75e9759..030454909 100644 --- a/Source/Game/Chat/CommandArgs.cs +++ b/Source/Game/Chat/CommandArgs.cs @@ -48,10 +48,10 @@ namespace Game.Chat //We found a optional arg and we dont have the correct amount of args args.SetCurrentPosition(oldPos); arguments.Add(default); + index++; } else arguments.Add(value); - } return arguments.ToArray(); @@ -109,25 +109,22 @@ namespace Game.Chat value = args.NextChar(); break; case TypeCode.Object: - if (type.IsGenericType) - type = type.GenericTypeArguments[0].UnderlyingSystemType; - switch (type.Name) { - case nameof(GameTele): - value = Global.ObjectMgr.GetGameTele(args.NextString()); + case nameof(PlayerIdentifier): + value = PlayerIdentifier.ParseFromString(args.NextString()); break; - case nameof(SpellInfo): - value = Global.SpellMgr.GetSpellInfo(args.NextUInt32(), Difficulty.None); + case nameof(AccountIdentifier): + value = AccountIdentifier.ParseFromString(args.NextString()); break; default: return false; } - return true; default: return false; } + return true; } } diff --git a/Source/Game/Chat/CommandAttribute.cs b/Source/Game/Chat/CommandAttribute.cs index 15adfcecb..ee5fcc306 100644 --- a/Source/Game/Chat/CommandAttribute.cs +++ b/Source/Game/Chat/CommandAttribute.cs @@ -23,10 +23,22 @@ namespace Game.Chat [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] public class CommandAttribute : Attribute { + public CommandAttribute(string command) + { + Name = command.ToLower(); + } + public CommandAttribute(string command, RBACPermissions rbac, bool allowConsole = false) { Name = command.ToLower(); - Help = ""; + RBAC = rbac; + AllowConsole = allowConsole; + } + + public CommandAttribute(string command, CypherStrings help, RBACPermissions rbac, bool allowConsole = false) + { + Name = command.ToLower(); + Help = help; RBAC = rbac; AllowConsole = allowConsole; } @@ -37,9 +49,9 @@ namespace Game.Chat public string Name { get; private set; } /// - /// Help text for command. + /// Help String for command. /// - public string Help { get; set; } + public CypherStrings Help { get; set; } /// /// Allow Console? @@ -55,13 +67,13 @@ namespace Game.Chat [AttributeUsage(AttributeTargets.Class)] public class CommandGroupAttribute : CommandAttribute { - //todo fix me. - public CommandGroupAttribute(string command) : base(command, RBACPermissions.Max, true) { } + public CommandGroupAttribute(string command) : base(command) { } } [AttributeUsage(AttributeTargets.Method)] public class CommandNonGroupAttribute : CommandAttribute { + 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) { } } } diff --git a/Source/Game/Chat/CommandHandler.cs b/Source/Game/Chat/CommandHandler.cs index 23d65bcfb..ff8b5a723 100644 --- a/Source/Game/Chat/CommandHandler.cs +++ b/Source/Game/Chat/CommandHandler.cs @@ -37,9 +37,9 @@ namespace Game.Chat _session = session; } - public virtual bool ParseCommand(string text) + public virtual bool ParseCommands(string text) { - if (string.IsNullOrEmpty(text)) + if (text.IsEmpty()) return false; // chat case (.command or !command format) @@ -51,7 +51,10 @@ namespace Game.Chat return false; // ignore messages staring from many dots. - if (text[1] == '!' || text[1] == '.') + if (text[1] == text[0]) + return false; + + if (text[1] == ' ') return false; return _ParseCommands(text.Substring(1)); @@ -59,7 +62,7 @@ namespace Game.Chat public bool _ParseCommands(string text) { - if (ExecuteCommandInTable(CommandManager.GetCommands(), text, text)) + if (ChatCommandNode.TryExecuteCommand(this, text)) return true; // Pretend commands don't exist for regular players @@ -67,205 +70,17 @@ namespace Game.Chat return false; // Send error message for GMs - SendSysMessage(CypherStrings.NoCmd); + SendSysMessage(CypherStrings.CmdInvalid, text); return true; } - public bool ExecuteCommandInTable(ICollection table, string text, string fullcmd) + public virtual bool IsAvailable(ChatCommandNode cmd) { - StringArguments args = new(text); - string cmd = args.NextString(); - - foreach (var command in table) - { - if (!HasStringAbbr(command.Name, cmd)) - continue; - - bool match = false; - if (command.Name.Length > cmd.Length) - { - foreach (var command2 in table) - { - if (!HasStringAbbr(command2.Name, cmd)) - continue; - - if (command2.Name.Equals(cmd)) - { - match = true; - break; - } - } - } - if (match) - continue; - - if (!command.ChildCommands.Empty()) - { - string arg = args.NextString(""); - if (!ExecuteCommandInTable(command.ChildCommands, arg, fullcmd)) - { - if (_session != null && !_session.HasPermission(RBACPermissions.CommandsNotifyCommandNotFoundError)) - return false; - - if (!arg.IsEmpty()) - SendSysMessage(CypherStrings.NoSubcmd); - else - SendSysMessage(CypherStrings.CmdSyntax); - - ShowHelpForCommand(command.ChildCommands, arg); - } - - return true; - } - - // must be available and have handler - if (!command.HasHandler() || !IsAvailable(command)) - continue; - - _sentErrorMessage = false; - if (command.Invoke(this, new StringArguments(!command.Name.IsEmpty() ? args.NextString("") : text))) - { - if (GetSession() == null) // ignore console - return true; - - Player player = GetPlayer(); - if (!Global.AccountMgr.IsPlayerAccount(GetSession().GetSecurity())) - { - ObjectGuid guid = player.GetTarget(); - uint areaId = player.GetAreaId(); - string areaName = "Unknown"; - string zoneName = "Unknown"; - - AreaTableRecord area = CliDB.AreaTableStorage.LookupByKey(areaId); - if (area != null) - { - var locale = GetSessionDbcLocale(); - areaName = area.AreaName[locale]; - AreaTableRecord zone = CliDB.AreaTableStorage.LookupByKey(area.ParentAreaID); - if (zone != null) - zoneName = zone.AreaName[locale]; - } - - Log.outCommand(GetSession().GetAccountId(), "Command: {0} [Player: {1} ({2}) (Account: {3}) Postion: {4} Map: {5} ({6}) Area: {7} ({8}) Zone: {9} Selected: {10} ({11})]", - fullcmd, player.GetName(), player.GetGUID().ToString(), GetSession().GetAccountId(), player.GetPosition(), player.GetMapId(), - player.GetMap() ? player.GetMap().GetMapName() : "Unknown", areaId, areaName, zoneName, (player.GetSelectedUnit()) ? player.GetSelectedUnit().GetName() : "", guid.ToString()); - } - } - else if (!HasSentErrorMessage()) - { - if (!command.Help.IsEmpty()) - SendSysMessage(command.Help); - else - SendSysMessage(CypherStrings.CmdSyntax); - } - - return true; - } - - return false; - } - - public bool ShowHelpForCommand(ICollection table, string text) - { - StringArguments args = new(text); - if (!args.Empty()) - { - string cmd = args.NextString(); - foreach (var command in table) - { - // must be available (ignore handler existence for show command with possible available subcommands) - if (!IsAvailable(command)) - continue; - - if (!HasStringAbbr(command.Name, cmd)) - continue; - - // have subcommand - string subcmd = !cmd.IsEmpty() ? args.NextString() : ""; - if (!command.ChildCommands.Empty() && !subcmd.IsEmpty()) - { - if (ShowHelpForCommand(command.ChildCommands, subcmd)) - return true; - } - - if (!command.Help.IsEmpty()) - SendSysMessage(command.Help); - - if (!command.ChildCommands.Empty()) - if (ShowHelpForSubCommands(command.ChildCommands, command.Name, subcmd)) - return true; - - return !command.Help.IsEmpty(); - } - } - else - { - foreach (var command in table) - { - // must be available (ignore handler existence for show command with possible available subcommands) - if (!IsAvailable(command)) - continue; - - if (!command.Name.IsEmpty()) - continue; - - if (!command.Help.IsEmpty()) - SendSysMessage(command.Help); - - if (!command.ChildCommands.Empty()) - if (ShowHelpForSubCommands(command.ChildCommands, "", "")) - return true; - - return !command.Help.IsEmpty(); - } - } - - return ShowHelpForSubCommands(table, "", text); - } - - public bool ShowHelpForSubCommands(ICollection table, string cmd, string subcmd) - { - string list = ""; - foreach (var command in table) - { - // must be available (ignore handler existence for show command with possible available subcommands) - if (!IsAvailable(command)) - continue; - - // for empty subcmd show all available - if (!subcmd.IsEmpty() && !HasStringAbbr(command.Name, subcmd)) - continue; - - if (GetSession() != null) - list += "\n "; - else - list += "\n\r "; - - list += command.Name; - - if (!command.ChildCommands.Empty()) - list += " ..."; - } - - if (list.IsEmpty()) - return false; - - if (table == CommandManager.GetCommands()) - { - SendSysMessage(CypherStrings.AvailableCmd); - SendSysMessage(list); - } - else - SendSysMessage(CypherStrings.SubcmdsList, cmd, list); - - return true; - } - - public virtual bool IsAvailable(ChatCommand cmd) - { - return HasPermission(cmd.Permission); + return HasPermission(cmd._permission.RequiredPermission); } + public virtual bool IsHumanReadable() { return true; } + public virtual bool HasPermission(RBACPermissions permission) { return _session.HasPermission(permission); } public string ExtractKeyFromLink(StringArguments args, params string[] linkType) @@ -699,7 +514,7 @@ namespace Game.Chat } public Player GetPlayer() { - return _session.GetPlayer(); + return _session?.GetPlayer(); } public string GetCypherString(CypherStrings str) { @@ -822,27 +637,27 @@ namespace Game.Chat public AddonChannelCommandHandler(WorldSession session) : base(session) { } - public override bool ParseCommand(string text) + public override bool ParseCommands(string str) { - if (text.IsEmpty()) + if (str.Length < 5) return false; - if (text.Length < 5) // str[1] through str[4] is 4-character command counter - return false; + char opcode = str[0]; + echo = str.Substring(1); - echo = text.Substring(1); - - switch (text[0]) + switch (opcode) { case 'p': // p Ping SendAck(); return true; case 'h': // h Issue human-readable command case 'i': // i Issue command - if (text.Length < 6) + if (str.Length < 6) return false; - humanReadable = (text[0] == 'h'); - if (_ParseCommands(text + 5)) // actual command starts at str[5] + + humanReadable = opcode == 'h'; + string cmd = str.Substring(5); + if (_ParseCommands(cmd)) // actual command starts at str[5] { if (!hadAck) SendAck(); @@ -853,7 +668,7 @@ namespace Game.Chat } else { - SendSysMessage(CypherStrings.NoCmd); + SendSysMessage(CypherStrings.CmdInvalid, cmd); SendFailed(); } return true; @@ -906,13 +721,15 @@ namespace Game.Chat msg.Append(body, lastpos, pos - lastpos); Send(msg.ToString()); } + + public override bool IsHumanReadable() { return humanReadable; } } public class ConsoleHandler : CommandHandler { - public override bool IsAvailable(ChatCommand cmd) + public override bool IsAvailable(ChatCommandNode cmd) { - return cmd.AllowConsole; + return cmd._permission.AllowConsole; } public override bool HasPermission(RBACPermissions permission) @@ -927,7 +744,7 @@ namespace Game.Chat Log.outInfo(LogFilter.Server, str); } - public override bool ParseCommand(string str) + public override bool ParseCommands(string str) { if (str.IsEmpty()) return false; @@ -969,9 +786,9 @@ namespace Game.Chat _reportToRA = reportToRA; } - public override bool IsAvailable(ChatCommand cmd) + public override bool IsAvailable(ChatCommandNode cmd) { - return cmd.AllowConsole; + return cmd._permission.AllowConsole; } public override bool HasPermission(RBACPermissions permission) @@ -986,7 +803,7 @@ namespace Game.Chat _reportToRA(str); } - public override bool ParseCommand(string str) + public override bool ParseCommands(string str) { if (str.IsEmpty()) return false; diff --git a/Source/Game/Chat/CommandManager.cs b/Source/Game/Chat/CommandManager.cs index 99cf92e01..0463c38eb 100644 --- a/Source/Game/Chat/CommandManager.cs +++ b/Source/Game/Chat/CommandManager.cs @@ -19,6 +19,8 @@ using Framework.Configuration; using Framework.Constants; using Framework.Database; using Framework.IO; +using Game.DataStorage; +using Game.Entities; using System; using System.Collections.Generic; using System.Linq; @@ -38,18 +40,17 @@ namespace Game.Chat var groupAttribute = type.GetCustomAttribute(true); if (groupAttribute != null) { - ChatCommand command = new(groupAttribute); - BuildChildCommandsForCommand(command, type); + ChatCommandNode command = new(groupAttribute); + BuildSubCommandsForCommand(command, type); _commands.Add(groupAttribute.Name, command); } - else + + //This check for any command not part of that group, but saves us from having to add them into a new class. + foreach (var method in type.GetMethods(BindingFlags.Static | BindingFlags.NonPublic)) { - foreach (var method in type.GetMethods(BindingFlags.Static | BindingFlags.NonPublic)) - { - var commandAttribute = method.GetCustomAttribute(true); - if (commandAttribute != null) - _commands.Add(commandAttribute.Name, new ChatCommand(commandAttribute, method)); - } + var commandAttribute = method.GetCustomAttribute(true); + if (commandAttribute != null) + _commands.Add(commandAttribute.Name, new ChatCommandNode(commandAttribute, method)); } } @@ -60,13 +61,45 @@ namespace Game.Chat do { string name = result.Read(0); - SetDataForCommandInTable(GetCommands(), name, result.Read(1), name); + string help = result.Read(1); + + ChatCommandNode cmd = null; + var map = _commands; + foreach (var key in name.Split(' ', StringSplitOptions.RemoveEmptyEntries)) + { + var it = map.LookupByKey(key); + if (it != null) + { + cmd = it; + map = cmd._subCommands; + } + else + { + Log.outError(LogFilter.Sql, $"Table `command` contains data for non-existant command '{name}'. Skipped."); + cmd = null; + break; + } + } + + if (cmd == null) + continue; + + if (!cmd._helpText.IsEmpty()) + Log.outError(LogFilter.Sql, $"Table `command` contains duplicate data for command '{name}'. Skipped."); + + if (cmd._helpString == 0) + cmd._helpText = help; + else + Log.outError(LogFilter.Sql, $"Table `command` contains legacy help text for command '{name}', which uses `trinity_string`. Skipped."); } while (result.NextRow()); } + + foreach (var (name, cmd) in _commands) + cmd.ResolveNames(name); } - static void BuildChildCommandsForCommand(ChatCommand command, Type type) + static void BuildSubCommandsForCommand(ChatCommandNode command, Type type) { foreach (var nestedType in type.GetNestedTypes(BindingFlags.NonPublic)) { @@ -74,9 +107,9 @@ namespace Game.Chat if (groupAttribute == null) continue; - ChatCommand childCommand = new(groupAttribute); - BuildChildCommandsForCommand(childCommand, nestedType); - command.AddChildCommand(childCommand); + ChatCommandNode subCommand = new(groupAttribute); + BuildSubCommandsForCommand(subCommand, nestedType); + command.AddSubCommand(subCommand); } foreach (var method in type.GetMethods(BindingFlags.Static | BindingFlags.NonPublic)) @@ -88,55 +121,8 @@ namespace Game.Chat if (commandAttribute.GetType() == typeof(CommandNonGroupAttribute)) continue; - command.AddChildCommand(new ChatCommand(commandAttribute, method)); + command.AddSubCommand(new ChatCommandNode(commandAttribute, method)); } - - command.SortChildCommands(); - } - - static bool SetDataForCommandInTable(ICollection table, string text, string help, string fullcommand) - { - StringArguments args = new(text); - string cmd = args.NextString().ToLower(); - - foreach (var command in table) - { - // for data fill use full explicit command names - if (command.Name != cmd) - continue; - - // select subcommand from child commands list (including "") - if (!command.ChildCommands.Empty()) - { - var arg = args.NextString(""); - if (SetDataForCommandInTable(command.ChildCommands, arg, help, fullcommand)) - return true; - else if (!arg.IsEmpty()) - return false; - - // fail with "" subcommands, then use normal level up command instead - } - // expected subcommand by full name DB content - else if (!args.NextString().IsEmpty()) - { - Log.outError(LogFilter.Sql, "Table `command` have unexpected subcommand '{0}' in command '{1}', skip.", text, fullcommand); - return false; - } - - command.Help = help; - return true; - } - - // in case "" command let process by caller - if (!cmd.IsEmpty()) - { - if (table == GetCommands()) - Log.outError(LogFilter.Sql, "Table `command` have not existed command '{0}', skip.", cmd); - else - Log.outError(LogFilter.Sql, "Table `command` have not existed subcommand '{0}' in command '{1}', skip.", cmd, fullcommand); - } - - return false; } public static void InitConsole() @@ -150,55 +136,255 @@ namespace Game.Chat var handler = new ConsoleHandler(); while (!Global.WorldMgr.IsStopped) { - handler.ParseCommand(Console.ReadLine()); + handler.ParseCommands(Console.ReadLine()); Console.ForegroundColor = ConsoleColor.Green; Console.Write("Cypher>> "); } } - public static ICollection GetCommands() + public static SortedDictionary GetCommands() { - return _commands.Values; + return _commands; } - static SortedDictionary _commands = new(); + static SortedDictionary _commands = new(); } public delegate bool HandleCommandDelegate(CommandHandler handler, StringArguments args); - public class ChatCommand + public class ChatCommandNode { - public string Name; - public RBACPermissions Permission; - public bool AllowConsole; - public string Help; - public List ChildCommands = new(); + public string _name; + public CommandPermissions _permission; + public string _helpText; + public CypherStrings _helpString; + public SortedDictionary _subCommands = new(); MethodInfo _methodInfo; Type[] parameterTypes; - public ChatCommand(CommandAttribute attribute) + public ChatCommandNode(CommandAttribute attribute) { - Name = attribute.Name; - Permission = attribute.RBAC; - AllowConsole = attribute.AllowConsole; - Help = attribute.Help; + _name = attribute.Name; + _permission = new CommandPermissions(attribute.RBAC, attribute.AllowConsole); + _helpString = attribute.Help; } - public ChatCommand(CommandAttribute attribute, MethodInfo methodInfo) : this(attribute) + public ChatCommandNode(CommandAttribute attribute, MethodInfo methodInfo) : this(attribute) { _methodInfo = methodInfo; parameterTypes = (from parameter in methodInfo.GetParameters() select parameter.ParameterType).ToArray(); } - public void AddChildCommand(ChatCommand command) + public static bool TryExecuteCommand(CommandHandler handler, string cmdStr) { - ChildCommands.Add(command); + ChatCommandNode cmd = null; + var map = CommandManager.GetCommands(); + + cmdStr = cmdStr.Trim(' '); + + string oldTail = cmdStr; + while (!oldTail.IsEmpty()) + { + /* oldTail = token DELIMITER newTail */ + var (token, newTail) = oldTail.Tokenize(); + Cypher.Assert(!token.IsEmpty()); + var listOfPossibleCommands = map.Where(p => p.Key.StartsWith(token) && p.Value.IsVisible(handler)).ToList(); + if (listOfPossibleCommands.Empty()) + break; /* no matching subcommands found */ + + if (!listOfPossibleCommands[0].Key.Equals(token, StringComparison.OrdinalIgnoreCase)) + { /* ok, so it1 points at a partially matching subcommand - let's see if there are others */ + + if (listOfPossibleCommands.Count > 1) + { /* there are multiple matching subcommands - print possibilities and return */ + if (cmd != null) + handler.SendSysMessage(CypherStrings.SubcmdAmbiguous, cmd._name, ' ', token); + else + handler.SendSysMessage(CypherStrings.CmdAmbiguous, token); + + handler.SendSysMessage(listOfPossibleCommands[0].Value.HasVisibleSubCommands(handler) ? CypherStrings.SubcmdsListEntryEllipsis : CypherStrings.SubcmdsListEntry, listOfPossibleCommands[0].Key); + foreach (var (name, command) in listOfPossibleCommands) + handler.SendSysMessage(command.HasVisibleSubCommands(handler) ? CypherStrings.SubcmdsListEntryEllipsis : CypherStrings.SubcmdsListEntry, name); + + return true; + } + } + + /* now we matched exactly one subcommand, and it1 points to it; go down the rabbit hole */ + cmd = listOfPossibleCommands[0].Value; + map = cmd._subCommands; + + oldTail = newTail; + } + + if (cmd != null) + { /* if we matched a command at some point, invoke it */ + if (cmd.IsInvokerVisible(handler) && cmd.Invoke(handler, new StringArguments(oldTail))) + { /* invocation succeeded, log this */ + if (!handler.IsConsole()) + LogCommandUsage(handler.GetSession(), (uint)cmd._permission.RequiredPermission, cmdStr); + } + else if (!handler.HasSentErrorMessage()) + { /* invocation failed, we should show usage */ + cmd.SendCommandHelp(handler); + } + return true; + } + + return false; } - public void SortChildCommands() + public static void SendCommandHelpFor(CommandHandler handler, string cmdStr) { - ChildCommands = ChildCommands.OrderBy(p => string.IsNullOrEmpty(p.Name)).ThenBy(p => p.Name).ToList(); + ChatCommandNode cmd = null; + var map = CommandManager.GetCommands(); + foreach (var token in cmdStr.Split(' ', StringSplitOptions.RemoveEmptyEntries)) + { + var listOfPossibleCommands = map.Where(p => p.Key.StartsWith(token) && p.Value.IsVisible(handler)).ToList(); + if (listOfPossibleCommands.Empty()) + { /* no matching subcommands found */ + if (cmd != null) + { + cmd.SendCommandHelp(handler); + handler.SendSysMessage(CypherStrings.SubcmdInvalid, cmd._name, ' ', token); + } + else + handler.SendSysMessage(CypherStrings.CmdInvalid, token); + return; + } + + if (!listOfPossibleCommands[0].Key.Equals(token, StringComparison.OrdinalIgnoreCase)) + { /* ok, so it1 points at a partially matching subcommand - let's see if there are others */ + + if (listOfPossibleCommands.Count > 1) + { /* there are multiple matching subcommands - print possibilities and return */ + if (cmd != null) + handler.SendSysMessage(CypherStrings.SubcmdAmbiguous, cmd._name, ' ', token); + else + handler.SendSysMessage(CypherStrings.CmdAmbiguous, token); + + handler.SendSysMessage(listOfPossibleCommands[0].Value.HasVisibleSubCommands(handler) ? CypherStrings.SubcmdsListEntryEllipsis : CypherStrings.SubcmdsListEntry, listOfPossibleCommands[0].Key); + foreach (var (name, command) in listOfPossibleCommands) + handler.SendSysMessage(command.HasVisibleSubCommands(handler) ? CypherStrings.SubcmdsListEntryEllipsis : CypherStrings.SubcmdsListEntry, name); + + return; + } + } + + cmd = listOfPossibleCommands[0].Value; + map = cmd._subCommands; + } + + if (cmd != null) + cmd.SendCommandHelp(handler); + else if (cmdStr.IsEmpty()) + { + handler.SendSysMessage(CypherStrings.AvailableCmds); + foreach (var (name, command) in map) + handler.SendSysMessage(command.HasVisibleSubCommands(handler) ? CypherStrings.SubcmdsListEntryEllipsis : CypherStrings.SubcmdsListEntry, name); + } + else + handler.SendSysMessage(CypherStrings.CmdInvalid, cmdStr); + } + + bool IsInvokerVisible(CommandHandler who) + { + if (_methodInfo == null) + return false; + + if (who.IsConsole() && !_permission.AllowConsole) + return false; + + return who.HasPermission(_permission.RequiredPermission); + } + + bool HasVisibleSubCommands(CommandHandler who) + { + foreach (var (_, command) in _subCommands) + if (command.IsVisible(who)) + return true; + return false; + } + + public void ResolveNames(string name) + { + if (_methodInfo != null && (_helpText.IsEmpty() && _helpString == 0)) + Log.outWarn(LogFilter.Sql, $"Table `command` is missing help text for command '{name}'."); + + _name = name; + foreach (var (subToken, cmd) in _subCommands) + cmd.ResolveNames($"{name} {subToken}"); + } + + static void LogCommandUsage(WorldSession session, uint permission, string cmdStr) + { + if (Global.AccountMgr.IsPlayerAccount(session.GetSecurity())) + return; + + if (Global.AccountMgr.GetRBACPermission((uint)RBACPermissions.RolePlayer).GetLinkedPermissions().Contains(permission)) + return; + + Player player = session.GetPlayer(); + ObjectGuid targetGuid = player.GetTarget(); + uint areaId = player.GetAreaId(); + string areaName = "Unknown"; + string zoneName = "Unknown"; + + var area = CliDB.AreaTableStorage.LookupByKey(areaId); + if (area != null) + { + Locale locale = session.GetSessionDbcLocale(); + areaName = area.AreaName[locale]; + var zone = CliDB.AreaTableStorage.LookupByKey(area.ParentAreaID); + if (zone != null) + zoneName = zone.AreaName[locale]; + } + + Log.outCommand(session.GetAccountId(), $"Command: {cmdStr} [Player: {player.GetName()} ({player.GetGUID()}) (Account: {session.GetAccountId()}) " + + $"X: {player.GetPositionX()} Y: {player.GetPositionY()} Z: {player.GetPositionZ()} Map: {player.GetMapId()} ({(player.GetMap() ? player.GetMap().GetMapName() : "Unknown")}) " + + $"Area: {areaId} ({areaName}) Zone: {zoneName} Selected: {(player.GetSelectedUnit() ? player.GetSelectedUnit().GetName() : "")} ({targetGuid})]"); + } + + public void SendCommandHelp(CommandHandler handler) + { + bool hasInvoker = IsInvokerVisible(handler); + if (hasInvoker) + { + if (_helpString != 0) + handler.SendSysMessage(_helpString); + else if (!_helpText.IsEmpty()) + handler.SendSysMessage(_helpText); + else + { + handler.SendSysMessage(CypherStrings.CmdHelpGeneric, _name); + handler.SendSysMessage(CypherStrings.CmdNoHelpAvailable, _name); + } + } + + bool header = false; + foreach (var (_, command) in _subCommands) + { + bool subCommandHasSubCommand = command.HasVisibleSubCommands(handler); + if (!subCommandHasSubCommand && !command.IsInvokerVisible(handler)) + continue; + if (!header) + { + if (!hasInvoker) + handler.SendSysMessage(CypherStrings.CmdHelpGeneric, _name); + handler.SendSysMessage(CypherStrings.SubcmdsList); + header = true; + } + handler.SendSysMessage(subCommandHasSubCommand ? CypherStrings.SubcmdsListEntryEllipsis : CypherStrings.SubcmdsListEntry, command._name); + } + } + + bool IsVisible(CommandHandler who) { return IsInvokerVisible(who) || HasVisibleSubCommands(who); } + + public void AddSubCommand(ChatCommandNode command) + { + if (!_subCommands.TryAdd(command._name, command)) + Log.outError(LogFilter.Commands, $"Error trying to add subcommand, Already exists Command: {_name} SubCommand: {command._name}"); } public bool Invoke(CommandHandler handler, StringArguments args) @@ -209,15 +395,17 @@ namespace Game.Chat return (bool)_methodInfo.Invoke(null, CommandArgs.Parse(handler, parameterTypes, args)); } + } - public bool HasHandler() - { - return _methodInfo != null; - } + public struct CommandPermissions + { + public RBACPermissions RequiredPermission; + public bool AllowConsole; - public override string ToString() + public CommandPermissions(RBACPermissions perm, bool allowConsole) { - return $"Name: {Name} Permission: {Permission} AllowConsole: {AllowConsole} ChildCommandCount: {ChildCommands.Count}"; + RequiredPermission = perm; + AllowConsole = allowConsole; } } } diff --git a/Source/Game/Chat/Commands/AccountCommands.cs b/Source/Game/Chat/Commands/AccountCommands.cs index 8e85fb3ca..ea9330b15 100644 --- a/Source/Game/Chat/Commands/AccountCommands.cs +++ b/Source/Game/Chat/Commands/AccountCommands.cs @@ -25,7 +25,7 @@ namespace Game.Chat [CommandGroup("account")] class AccountCommands { - [Command("", RBACPermissions.CommandAccount)] + [Command("", CypherStrings.CommandAccountHelp, RBACPermissions.CommandAccount)] static bool HandleAccountCommand(CommandHandler handler) { if (handler.GetSession() == null) @@ -68,7 +68,7 @@ namespace Game.Chat return true; } - [Command("addon", RBACPermissions.CommandAccountAddon)] + [Command("addon", CypherStrings.CommandAccAddonHelp, RBACPermissions.CommandAccountAddon)] static bool HandleAccountAddonCommand(CommandHandler handler, byte expansion) { if (expansion > WorldConfig.GetIntValue(WorldCfg.Expansion)) @@ -86,7 +86,7 @@ namespace Game.Chat return true; } - [Command("create", RBACPermissions.CommandAccountCreate, true)] + [Command("create", CypherStrings.CommandAccCreateHelp, RBACPermissions.CommandAccountCreate, true)] static bool HandleAccountCreateCommand(CommandHandler handler, string accountName, string password, string email) { if (accountName.Contains("@")) @@ -128,7 +128,7 @@ namespace Game.Chat return true; } - [Command("delete", RBACPermissions.CommandAccountDelete, true)] + [Command("delete", CypherStrings.CommandAccDeleteHelp, RBACPermissions.CommandAccountDelete, true)] static bool HandleAccountDeleteCommand(CommandHandler handler, string accountName) { uint accountId = Global.AccountMgr.GetId(accountName); @@ -161,7 +161,7 @@ namespace Game.Chat return true; } - [Command("email", RBACPermissions.CommandAccountEmail)] + [Command("email", CypherStrings.CommandAccEmailHelp, RBACPermissions.CommandAccountEmail)] static bool HandleAccountEmailCommand(CommandHandler handler, string oldEmail, string password, string email, string emailConfirm) { if (!Global.AccountMgr.CheckEmail(handler.GetSession().GetAccountId(), oldEmail)) @@ -220,7 +220,7 @@ namespace Game.Chat return true; } - [Command("password", RBACPermissions.CommandAccountPassword)] + [Command("password", CypherStrings.CommandAccPasswordHelp, RBACPermissions.CommandAccountPassword)] static bool HandleAccountPasswordCommand(CommandHandler handler, string oldPassword, string newPassword, string confirmPassword, string confirmEmail) { // First, we check config. What security type (sec type) is it ? Depending on it, the command branches out @@ -277,12 +277,10 @@ namespace Game.Chat return true; } - - [CommandGroup("lock")] class AccountLockCommands { - [Command("country", RBACPermissions.CommandAccountLockCountry)] + [Command("country", CypherStrings.CommandAccLockCountryHelp, RBACPermissions.CommandAccountLockCountry)] static bool HandleAccountLockCountryCommand(CommandHandler handler, bool state) { if (state) @@ -320,7 +318,7 @@ namespace Game.Chat return true; } - [Command("ip", RBACPermissions.CommandAccountLockIp)] + [Command("ip", CypherStrings.CommandAccLockIpHelp, RBACPermissions.CommandAccountLockIp)] static bool HandleAccountLockIpCommand(CommandHandler handler, bool state) { PreparedStatement stmt = DB.Login.GetPreparedStatement(LoginStatements.UPD_ACCOUNT_LOCK); @@ -346,31 +344,31 @@ namespace Game.Chat [CommandGroup("onlinelist")] class AccountOnlineListCommands { - [Command("", RBACPermissions.CommandAccountOnlineList, true)] + [Command("", CypherStrings.CommandAccOnlinelistHelp, RBACPermissions.CommandAccountOnlineList, true)] static bool HandleAccountOnlineListCommand(CommandHandler handler) { return HandleAccountOnlineListCommandWithParameters(handler, null, null, null, null); } - [Command("ip", RBACPermissions.CommandAccountOnlineList, true)] + [Command("ip", CypherStrings.CommandAccOnlinelistHelp, RBACPermissions.CommandAccountOnlineList, true)] static bool HandleAccountOnlineListWithIpFilterCommand(CommandHandler handler, string ipAddress) { return HandleAccountOnlineListCommandWithParameters(handler, ipAddress, null, null, null); } - [Command("limit", RBACPermissions.CommandAccountOnlineList, true)] + [Command("limit", CypherStrings.CommandAccOnlinelistHelp, RBACPermissions.CommandAccountOnlineList, true)] static bool HandleAccountOnlineListWithLimitCommand(CommandHandler handler, uint limit) { return HandleAccountOnlineListCommandWithParameters(handler, null, limit, null, null); } - [Command("map", RBACPermissions.CommandAccountOnlineList, true)] + [Command("map", CypherStrings.CommandAccOnlinelistHelp, RBACPermissions.CommandAccountOnlineList, true)] static bool HandleAccountOnlineListWithMapFilterCommand(CommandHandler handler, uint mapId) { return HandleAccountOnlineListCommandWithParameters(handler, null, null, mapId, null); } - [Command("zone", RBACPermissions.CommandAccountOnlineList, true)] + [Command("zone", CypherStrings.CommandAccOnlinelistHelp, RBACPermissions.CommandAccountOnlineList, true)] static bool HandleAccountOnlineListWithZoneFilterCommand(CommandHandler handler, uint zoneId) { return HandleAccountOnlineListCommandWithParameters(handler, null, null, null, zoneId); @@ -442,7 +440,7 @@ namespace Game.Chat [CommandGroup("set")] class AccountSetCommands { - [Command("addon", RBACPermissions.CommandAccountSetAddon, true)] + [Command("addon", CypherStrings.CommandAccSetAddonHelp, RBACPermissions.CommandAccountSetAddon, true)] static bool HandleAccountSetAddonCommand(CommandHandler handler, string accountName, byte expansion) { uint accountId; @@ -488,13 +486,13 @@ namespace Game.Chat return true; } - [Command("gmlevel", RBACPermissions.CommandAccountSetSecLevel, 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", RBACPermissions.CommandAccountSetPassword, true)] + [Command("password", CypherStrings.CommandAccSetPasswordHelp, RBACPermissions.CommandAccountSetPassword, true)] static bool HandleAccountSetPasswordCommand(CommandHandler handler, string accountName, string password, string confirmPassword) { uint targetAccountId = Global.AccountMgr.GetId(accountName); @@ -535,7 +533,7 @@ namespace Game.Chat return true; } - [Command("seclevel", RBACPermissions.CommandAccountSetSecLevel, true)] + [Command("seclevel", CypherStrings.CommandAccSetSeclevelHelp, RBACPermissions.CommandAccountSetSecLevel, true)] static bool HandleAccountSetSecLevelCommand(CommandHandler handler, string accountName, byte securityLevel, int? realmId) { uint accountId; @@ -615,7 +613,7 @@ namespace Game.Chat [CommandGroup("sec")] class SetSecCommands { - [Command("email", RBACPermissions.CommandAccountSetSecEmail, true)] + [Command("email", CypherStrings.CommandAccSetSecEmailHelp, RBACPermissions.CommandAccountSetSecEmail, true)] static bool HandleAccountSetEmailCommand(CommandHandler handler, string accountName, string email, string confirmEmail) { uint targetAccountId = Global.AccountMgr.GetId(accountName); @@ -657,7 +655,7 @@ namespace Game.Chat return true; } - [Command("regmail", RBACPermissions.CommandAccountSetSecRegmail, true)] + [Command("regmail", CypherStrings.CommandAccSetSecRegmailHelp, RBACPermissions.CommandAccountSetSecRegmail, true)] static bool HandleAccountSetRegEmailCommand(CommandHandler handler, string accountName, string email, string confirmEmail) { uint targetAccountId = Global.AccountMgr.GetId(accountName); diff --git a/Source/Game/Chat/Commands/AchievementCommands.cs b/Source/Game/Chat/Commands/AchievementCommands.cs index e3e3ac5ca..3cc6e4f95 100644 --- a/Source/Game/Chat/Commands/AchievementCommands.cs +++ b/Source/Game/Chat/Commands/AchievementCommands.cs @@ -26,7 +26,7 @@ namespace Game.Chat.Commands [CommandGroup("achievement")] class AchievementCommand { - [Command("add", RBACPermissions.CommandAchievementAdd)] + [Command("add", CypherStrings.CommandAchievementAddHelp, RBACPermissions.CommandAchievementAdd)] static bool HandleAchievementAddCommand(CommandHandler handler, uint achievemntId) { AchievementRecord achievementEntry = CliDB.AchievementStorage.LookupByKey(achievemntId); diff --git a/Source/Game/Chat/Commands/ArenaCommands.cs b/Source/Game/Chat/Commands/ArenaCommands.cs index 06ef82dd1..ced798003 100644 --- a/Source/Game/Chat/Commands/ArenaCommands.cs +++ b/Source/Game/Chat/Commands/ArenaCommands.cs @@ -25,7 +25,7 @@ namespace Game.Chat class ArenaCommands { [Command("create", RBACPermissions.CommandArenaCreate, true)] - static bool HandleArenaCreateCommand(CommandHandler handler, string captainName, string name, ArenaTypes type) + static bool HandleArenaCreateCommand(CommandHandler handler, PlayerIdentifier captain, string name, ArenaTypes type) { if (Global.ArenaTeamMgr.GetArenaTeamByName(name) != null) { @@ -33,7 +33,6 @@ namespace Game.Chat return false; } - var captain = PlayerIdentifier.ParseFromString(captainName); if (captain == null) captain = PlayerIdentifier.FromTargetOrSelf(handler); if (captain == null) @@ -115,7 +114,7 @@ namespace Game.Chat } [Command("captain", RBACPermissions.CommandArenaCaptain)] - static bool HandleArenaCaptainCommand(CommandHandler handler, uint teamId, string targetName) + static bool HandleArenaCaptainCommand(CommandHandler handler, uint teamId, PlayerIdentifier target) { ArenaTeam arena = Global.ArenaTeamMgr.GetArenaTeamById(teamId); if (arena == null) @@ -130,7 +129,6 @@ namespace Game.Chat return false; } - var target = PlayerIdentifier.ParseFromString(targetName); if (target == null) target = PlayerIdentifier.FromTargetOrSelf(handler); if (target == null) diff --git a/Source/Game/Chat/Commands/CharacterCommands.cs b/Source/Game/Chat/Commands/CharacterCommands.cs index ba983885f..1f2c357c9 100644 --- a/Source/Game/Chat/Commands/CharacterCommands.cs +++ b/Source/Game/Chat/Commands/CharacterCommands.cs @@ -31,14 +31,13 @@ namespace Game.Chat class CharacterCommands { [Command("titles", RBACPermissions.CommandCharacterTitles, true)] - static bool HandleCharacterTitlesCommand(CommandHandler handler, string playerName) + static bool HandleCharacterTitlesCommand(CommandHandler handler, PlayerIdentifier player) { - var player = PlayerIdentifier.ParseFromString(playerName); if (player == null) player = PlayerIdentifier.FromTargetOrSelf(handler); if (player == null || !player.IsConnected()) { - handler.SendSysMessage(CypherStrings.PlayerNotExistOrOffline); + handler.SendSysMessage(CypherStrings.PlayerNotFound); return false; } @@ -78,19 +77,18 @@ namespace Game.Chat //rename characters [Command("rename", RBACPermissions.CommandCharacterRename, true)] - static bool HandleCharacterRenameCommand(CommandHandler handler, string playerName, string newName) + static bool HandleCharacterRenameCommand(CommandHandler handler, PlayerIdentifier player, string newName) { - var playerIdentifier = PlayerIdentifier.ParseFromString(playerName); - if (playerIdentifier == null && !newName.IsEmpty()) + if (player == null && !newName.IsEmpty()) return false; - if (playerIdentifier == null) - playerIdentifier = PlayerIdentifier.FromTarget(handler); - if (playerIdentifier == null) + if (player == null) + player = PlayerIdentifier.FromTarget(handler); + if (player == null) return false; // check online security - if (handler.HasLowerSecurity(null, playerIdentifier.GetGUID())) + if (handler.HasLowerSecurity(null, player.GetGUID())) return false; if (!newName.IsEmpty()) @@ -101,7 +99,7 @@ namespace Game.Chat return false; } - if (ObjectManager.CheckPlayerName(newName, playerIdentifier.IsConnected() ? playerIdentifier.GetConnectedPlayer().GetSession().GetSessionDbcLocale() : Global.WorldMgr.GetDefaultDbcLocale(), true) != ResponseCodes.CharNameSuccess) + if (ObjectManager.CheckPlayerName(newName, player.IsConnected() ? player.GetConnectedPlayer().GetSession().GetSessionDbcLocale() : Global.WorldMgr.GetDefaultDbcLocale(), true) != ResponseCodes.CharNameSuccess) { handler.SendSysMessage(CypherStrings.BadValue); return false; @@ -128,10 +126,10 @@ namespace Game.Chat // Remove declined name from db stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_CHAR_DECLINED_NAME); - stmt.AddValue(0, playerIdentifier.GetGUID().GetCounter()); + stmt.AddValue(0, player.GetGUID().GetCounter()); DB.Characters.Execute(stmt); - Player target = playerIdentifier.GetConnectedPlayer(); + Player target = player.GetConnectedPlayer(); if (target != null) { target.SetName(newName); @@ -143,26 +141,26 @@ namespace Game.Chat { stmt = DB.Characters.GetPreparedStatement(CharStatements.UPD_NAME_BY_GUID); stmt.AddValue(0, newName); - stmt.AddValue(1, playerIdentifier.GetGUID().GetCounter()); + stmt.AddValue(1, player.GetGUID().GetCounter()); DB.Characters.Execute(stmt); } - Global.CharacterCacheStorage.UpdateCharacterData(playerIdentifier.GetGUID(), newName); + Global.CharacterCacheStorage.UpdateCharacterData(player.GetGUID(), newName); - handler.SendSysMessage(CypherStrings.RenamePlayerWithNewName, playerIdentifier.GetName(), newName); + handler.SendSysMessage(CypherStrings.RenamePlayerWithNewName, player.GetName(), newName); if (session != null) { - Player player = session.GetPlayer(); - if (player) - Log.outCommand(session.GetAccountId(), "GM {0} (Account: {1}) forced rename {2} to player {3} (Account: {4})", player.GetName(), session.GetAccountId(), newName, player.GetName(), Global.CharacterCacheStorage.GetCharacterAccountIdByGuid(player.GetGUID())); + Player sessionPlayer = session.GetPlayer(); + if (sessionPlayer) + Log.outCommand(session.GetAccountId(), "GM {0} (Account: {1}) forced rename {2} to player {3} (Account: {4})", sessionPlayer.GetName(), session.GetAccountId(), newName, sessionPlayer.GetName(), Global.CharacterCacheStorage.GetCharacterAccountIdByGuid(sessionPlayer.GetGUID())); } else - Log.outCommand(0, "CONSOLE forced rename '{0}' to '{1}' ({2})", playerIdentifier.GetName(), newName, playerIdentifier.GetGUID().ToString()); + Log.outCommand(0, "CONSOLE forced rename '{0}' to '{1}' ({2})", player.GetName(), newName, player.GetGUID().ToString()); } else { - Player target = playerIdentifier.GetConnectedPlayer(); + Player target = player.GetConnectedPlayer(); if (target != null) { handler.SendSysMessage(CypherStrings.RenamePlayer, handler.GetNameLink(target)); @@ -171,14 +169,14 @@ namespace Game.Chat else { // check offline security - if (handler.HasLowerSecurity(null, playerIdentifier.GetGUID())) + if (handler.HasLowerSecurity(null, player.GetGUID())) return false; - handler.SendSysMessage(CypherStrings.RenamePlayerGuid, handler.PlayerLink(playerIdentifier.GetName()), playerIdentifier.GetGUID().ToString()); + handler.SendSysMessage(CypherStrings.RenamePlayerGuid, handler.PlayerLink(player.GetName()), player.GetGUID().ToString()); PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.UPD_ADD_AT_LOGIN_FLAG); stmt.AddValue(0, (ushort)AtLoginFlags.Rename); - stmt.AddValue(1, playerIdentifier.GetGUID().GetCounter()); + stmt.AddValue(1, player.GetGUID().GetCounter()); DB.Characters.Execute(stmt); } } @@ -187,9 +185,8 @@ namespace Game.Chat } [Command("level", RBACPermissions.CommandCharacterLevel, true)] - static bool HandleCharacterLevelCommand(CommandHandler handler, string playerName, short newlevel) + static bool HandleCharacterLevelCommand(CommandHandler handler, PlayerIdentifier player, short newlevel) { - var player = PlayerIdentifier.ParseFromString(playerName); if (player == null) player = PlayerIdentifier.FromTargetOrSelf(handler); if (player == null) @@ -236,9 +233,8 @@ namespace Game.Chat } [Command("customize", RBACPermissions.CommandCharacterCustomize, true)] - static bool HandleCharacterCustomizeCommand(CommandHandler handler, string playerName) + static bool HandleCharacterCustomizeCommand(CommandHandler handler, PlayerIdentifier player) { - var player = PlayerIdentifier.ParseFromString(playerName); if (player == null) player = PlayerIdentifier.FromTarget(handler); if (player == null) @@ -263,15 +259,14 @@ namespace Game.Chat } [Command("changeaccount", RBACPermissions.CommandCharacterChangeaccount, true)] - static bool HandleCharacterChangeAccountCommand(CommandHandler handler, string playerName, string newAccountName) + static bool HandleCharacterChangeAccountCommand(CommandHandler handler, PlayerIdentifier player, AccountIdentifier newAccount) { - var playerIdentifier = PlayerIdentifier.ParseFromString(playerName); - if (playerIdentifier == null) - playerIdentifier = PlayerIdentifier.FromTarget(handler); - if (playerIdentifier == null) + if (player == null) + player = PlayerIdentifier.FromTarget(handler); + if (player == null) return false; - CharacterCacheEntry characterInfo = Global.CharacterCacheStorage.GetCharacterCacheByGuid(playerIdentifier.GetGUID()); + CharacterCacheEntry characterInfo = Global.CharacterCacheStorage.GetCharacterCacheByGuid(player.GetGUID()); if (characterInfo == null) { handler.SendSysMessage(CypherStrings.PlayerNotFound); @@ -279,7 +274,6 @@ namespace Game.Chat } uint oldAccountId = characterInfo.AccountId; - var newAccount = AccountIdentifier.ParseFromString(newAccountName); // nothing to do :) if (newAccount.GetID() == oldAccountId) @@ -295,29 +289,29 @@ namespace Game.Chat } } - Player onlinePlayer = playerIdentifier.GetConnectedPlayer(); + Player onlinePlayer = player.GetConnectedPlayer(); if (onlinePlayer != null) onlinePlayer.GetSession().KickPlayer("HandleCharacterChangeAccountCommand GM Command transferring character to another account"); PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.UPD_ACCOUNT_BY_GUID); stmt.AddValue(0, newAccount.GetID()); - stmt.AddValue(1, playerIdentifier.GetGUID().GetCounter()); + stmt.AddValue(1, player.GetGUID().GetCounter()); DB.Characters.DirectExecute(stmt); Global.WorldMgr.UpdateRealmCharCount(oldAccountId); Global.WorldMgr.UpdateRealmCharCount(newAccount.GetID()); - Global.CharacterCacheStorage.UpdateCharacterAccountId(playerIdentifier.GetGUID(), newAccount.GetID()); + Global.CharacterCacheStorage.UpdateCharacterAccountId(player.GetGUID(), newAccount.GetID()); - handler.SendSysMessage(CypherStrings.ChangeAccountSuccess, playerIdentifier.GetName(), newAccount.GetName()); + handler.SendSysMessage(CypherStrings.ChangeAccountSuccess, player.GetName(), newAccount.GetName()); - string logString = $"changed ownership of player {playerIdentifier.GetName()} ({playerIdentifier.GetGUID()}) from account {oldAccountId} to account {newAccount.GetID()}"; + string logString = $"changed ownership of player {player.GetName()} ({player.GetGUID()}) from account {oldAccountId} to account {newAccount.GetID()}"; WorldSession session = handler.GetSession(); if (session != null) { - Player player = session.GetPlayer(); - if (player != null) - Log.outCommand(session.GetAccountId(), $"GM {player.GetName()} (Account: {session.GetAccountId()}) {logString}"); + Player sessionPlayer = session.GetPlayer(); + if (sessionPlayer != null) + Log.outCommand(session.GetAccountId(), $"GM {sessionPlayer.GetName()} (Account: {session.GetAccountId()}) {logString}"); } else Log.outCommand(0, $"{handler.GetCypherString(CypherStrings.Console)} {logString}"); @@ -325,9 +319,8 @@ namespace Game.Chat } [Command("changefaction", RBACPermissions.CommandCharacterChangefaction, true)] - static bool HandleCharacterChangeFactionCommand(CommandHandler handler, string playerName) + static bool HandleCharacterChangeFactionCommand(CommandHandler handler, PlayerIdentifier player) { - var player = PlayerIdentifier.ParseFromString(playerName); if (player == null) player = PlayerIdentifier.FromTarget(handler); if (player == null) @@ -352,9 +345,8 @@ namespace Game.Chat } [Command("changerace", RBACPermissions.CommandCharacterChangerace, true)] - static bool HandleCharacterChangeRaceCommand(CommandHandler handler, string playerName) + static bool HandleCharacterChangeRaceCommand(CommandHandler handler, PlayerIdentifier player) { - var player = PlayerIdentifier.ParseFromString(playerName); if (player == null) player = PlayerIdentifier.FromTarget(handler); if (player == null) @@ -379,9 +371,8 @@ namespace Game.Chat } [Command("reputation", RBACPermissions.CommandCharacterReputation, true)] - static bool HandleCharacterReputationCommand(CommandHandler handler, string playerName) + static bool HandleCharacterReputationCommand(CommandHandler handler, PlayerIdentifier player) { - var player = PlayerIdentifier.ParseFromString(playerName); if (player == null) player = PlayerIdentifier.FromTargetOrSelf(handler); if (player == null || !player.IsConnected()) @@ -429,11 +420,10 @@ namespace Game.Chat } [Command("erase", RBACPermissions.CommandCharacterErase, true)] - static bool HandleCharacterEraseCommand(CommandHandler handler, string playerName) + static bool HandleCharacterEraseCommand(CommandHandler handler, PlayerIdentifier player) { uint accountId; - var player = PlayerIdentifier.ParseFromString(playerName); Player target = player?.GetConnectedPlayer(); if (target != null) { @@ -498,7 +488,7 @@ namespace Game.Chat } [Command("restore", RBACPermissions.CommandCharacterDeletedRestore, true)] - static bool HandleCharacterDeletedRestoreCommand(CommandHandler handler, string needle, string newCharName, string accountName) + static bool HandleCharacterDeletedRestoreCommand(CommandHandler handler, string needle, string newCharName, AccountIdentifier newAccount) { List foundList = new(); if (!GetDeletedCharacterInfoList(foundList, needle)) @@ -529,7 +519,6 @@ namespace Game.Chat // update name delInfo.name = newCharName; - var newAccount = AccountIdentifier.ParseFromString(accountName); // if new account provided update deleted info if (newAccount != null) { @@ -683,9 +672,8 @@ namespace Game.Chat } [CommandNonGroup("levelup", RBACPermissions.CommandLevelup)] - static bool HandleLevelUpCommand(CommandHandler handler, string playerName, short level) + static bool HandleLevelUpCommand(CommandHandler handler, PlayerIdentifier player, short level) { - var player = PlayerIdentifier.ParseFromString(playerName); if (player == null) player = PlayerIdentifier.FromTargetOrSelf(handler); if (player == null) @@ -736,6 +724,52 @@ namespace Game.Chat [CommandGroup("pdump")] class PdumpCommand { + [Command("copy", RBACPermissions.CommandPdumpCopy, true)] + static bool HandlePDumpCopyCommand(CommandHandler handler, string playerName, string accountName, string characterName, ulong? characterGUID) + { + /* + std::string name; + if (!ValidatePDumpTarget(handler, name, characterName, characterGUID)) + return false; + + std::string dump; + switch (PlayerDumpWriter().WriteDumpToString(dump, player.GetGUID().GetCounter())) + { + case DUMP_SUCCESS: + break; + case DUMP_CHARACTER_DELETED: + handler->PSendSysMessage(LANG_COMMAND_EXPORT_DELETED_CHAR); + handler->SetSentErrorMessage(true); + return false; + case DUMP_FILE_OPEN_ERROR: // this error code should not happen + default: + handler->PSendSysMessage(LANG_COMMAND_EXPORT_FAILED); + handler->SetSentErrorMessage(true); + return false; + } + + switch (PlayerDumpReader().LoadDumpFromString(dump, account, name, characterGUID.value_or(0))) + { + case DUMP_SUCCESS: + break; + case DUMP_TOO_MANY_CHARS: + handler->PSendSysMessage(LANG_ACCOUNT_CHARACTER_LIST_FULL, account.GetName().c_str(), account.GetID()); + handler->SetSentErrorMessage(true); + return false; + case DUMP_FILE_OPEN_ERROR: // this error code should not happen + case DUMP_FILE_BROKEN: // this error code should not happen + default: + handler->PSendSysMessage(LANG_COMMAND_IMPORT_FAILED); + handler->SetSentErrorMessage(true); + return false; + } + + // ToDo: use a new trinity_string for this commands + handler->PSendSysMessage(LANG_COMMAND_IMPORT_SUCCESS); + */ + return true; + } + [Command("load", RBACPermissions.CommandPdumpLoad, true)] static bool HandlePDumpLoadCommand(CommandHandler handler, string fileName, string accountName, string characterName, ulong? characterGuid) { diff --git a/Source/Game/Chat/Commands/DebugCommands.cs b/Source/Game/Chat/Commands/DebugCommands.cs index 81719de4b..866dfc310 100644 --- a/Source/Game/Chat/Commands/DebugCommands.cs +++ b/Source/Game/Chat/Commands/DebugCommands.cs @@ -1082,31 +1082,28 @@ namespace Game.Chat return true; } - [Command("worldstate", RBACPermissions.CommandDebug)] - static bool HandleDebugUpdateWorldStateCommand(CommandHandler handler, uint variable, uint value) + [Command("warden force", RBACPermissions.CommandDebug, true)] + static bool HandleDebugWardenForce(CommandHandler handler, ushort[] checkIds) { - handler.GetPlayer().SendUpdateWorldState(variable, value); + /*if (checkIds.Empty()) + return false; + + Warden warden = handler.GetSession().GetWarden(); + if (warden == null) + { + handler.SendSysMessage("Warden system is not enabled"); + return true; + } + + size_t const nQueued = warden->DEBUG_ForceSpecificChecks(checkIds); + handler->PSendSysMessage("%zu/%zu checks queued for your Warden, they should be sent over the next few minutes (depending on settings)", nQueued, checkIds.size());*/ return true; } [Command("worldstate", RBACPermissions.CommandDebug)] - static bool HandleDebugWorldStateCommand(CommandHandler handler, uint worldStateId, uint? value) + static bool HandleDebugUpdateWorldStateCommand(CommandHandler handler, uint variable, uint value) { - Player target = handler.GetSelectedPlayerOrSelf(); - if (target == null) - { - handler.SendSysMessage(CypherStrings.PlayerNotFound); - return false; - } - - if (value.HasValue) - { - Global.WorldMgr.SetWorldState(worldStateId, value.Value); - target.SendUpdateWorldState(worldStateId, value.Value); - } - else - handler.SendSysMessage($"Worldstate {worldStateId} actual value : {Global.WorldMgr.GetWorldState(worldStateId)}"); - + handler.GetPlayer().SendUpdateWorldState(variable, value); return true; } @@ -1143,8 +1140,18 @@ namespace Game.Chat return true; } + [CommandGroup("asan")] + class DebugAsanCommands + { + [Command("memoryleak", RBACPermissions.CommandDebug, true)] + static bool HandleDebugMemoryLeak(CommandHandler handler) { return true; } + + [Command("outofbounds", RBACPermissions.CommandDebug, true)] + static bool HandleDebugOutOfBounds(CommandHandler handler) { return true; } + } + [CommandGroup("play")] - class PlayCommands + class DebugPlayCommands { [Command("cinematic", RBACPermissions.CommandDebug)] static bool HandleDebugPlayCinematicCommand(CommandHandler handler, uint cinematicId) @@ -1233,7 +1240,7 @@ namespace Game.Chat } [CommandGroup("pvp")] - class PvpCommands + class DebugPvpCommands { [Command("warmode", RBACPermissions.CommandDebug)] static bool HandleDebugWarModeFactionBalanceCommand(CommandHandler handler, string command, int rewardValue = 0) @@ -1267,7 +1274,7 @@ namespace Game.Chat } [CommandGroup("send")] - class SendCommands + class DebugSendCommands { [Command("buyerror", RBACPermissions.CommandDebug)] static bool HandleDebugSendBuyErrorCommand(CommandHandler handler, BuyResult error) @@ -1315,7 +1322,7 @@ namespace Game.Chat [Command("opcode", RBACPermissions.CommandDebug)] static bool HandleDebugSendOpcodeCommand(CommandHandler handler) { - handler.SendSysMessage(CypherStrings.NoCmd); + handler.SendSysMessage(CypherStrings.CmdInvalid); return true; } @@ -1381,6 +1388,28 @@ namespace Game.Chat } } + [CommandGroup("warden")] + class DebugWardenCommands + { + [Command("force", RBACPermissions.CommandDebug, true)] + static bool HandleDebugWardenForce(CommandHandler handler, ushort[] checkIds) + { + /*if (checkIds.Empty()) + return false; + + Warden warden = handler.GetSession().GetWarden(); + if (warden == null) + { + handler.SendSysMessage("Warden system is not enabled"); + return true; + } + + size_t const nQueued = warden->DEBUG_ForceSpecificChecks(checkIds); + handler->PSendSysMessage("%zu/%zu checks queued for your Warden, they should be sent over the next few minutes (depending on settings)", nQueued, checkIds.size());*/ + return true; + } + } + static void HandleDebugGuidLimitsMap(CommandHandler handler, Map map) { handler.SendSysMessage($"Map Id: {map.GetId()} Name: '{map.GetMapName()}' Instance Id: {map.GetInstanceId()} Highest Guid Creature: {map.GenerateLowGuid(HighGuid.Creature)} GameObject: {map.GetMaxLowGuid(HighGuid.GameObject)}"); diff --git a/Source/Game/Chat/Commands/GameObjectCommands.cs b/Source/Game/Chat/Commands/GameObjectCommands.cs index 55d98350d..361333da4 100644 --- a/Source/Game/Chat/Commands/GameObjectCommands.cs +++ b/Source/Game/Chat/Commands/GameObjectCommands.cs @@ -185,10 +185,10 @@ namespace Game.Chat handler.SendSysMessage(CypherStrings.GoinfoName, name); handler.SendSysMessage(CypherStrings.GoinfoSize, gameObjectInfo.size); - handler.SendSysMessage(CypherStrings.ObjectInfoAIInfo, gameObjectInfo.AIName, Global.ObjectMgr.GetScriptName(gameObjectInfo.ScriptId)); + handler.SendSysMessage(CypherStrings.ObjectinfoAiInfo, gameObjectInfo.AIName, Global.ObjectMgr.GetScriptName(gameObjectInfo.ScriptId)); var ai = thisGO != null ? thisGO.GetAI() : null; if (ai != null) - handler.SendSysMessage(CypherStrings.ObjectInfoAIType, nameof(ai)); + handler.SendSysMessage(CypherStrings.ObjectinfoAiType, nameof(ai)); GameObjectDisplayInfoRecord modelInfo = CliDB.GameObjectDisplayInfoStorage.LookupByKey(displayId); if (modelInfo != null) diff --git a/Source/Game/Chat/Commands/GroupCommands.cs b/Source/Game/Chat/Commands/GroupCommands.cs index 7dcada80a..21824d94b 100644 --- a/Source/Game/Chat/Commands/GroupCommands.cs +++ b/Source/Game/Chat/Commands/GroupCommands.cs @@ -120,12 +120,11 @@ namespace Game.Chat } [Command("level", RBACPermissions.CommandCharacterLevel, true)] - static bool HandleGroupLevelCommand(CommandHandler handler, string playerName, short level) + static bool HandleGroupLevelCommand(CommandHandler handler, PlayerIdentifier player, short level) { if (level < 1) return false; - var player = PlayerIdentifier.ParseFromString(playerName); if (player == null) player = PlayerIdentifier.FromTargetOrSelf(handler); if (player == null) diff --git a/Source/Game/Chat/Commands/GuildCommands.cs b/Source/Game/Chat/Commands/GuildCommands.cs index 5afa12e71..c005042ce 100644 --- a/Source/Game/Chat/Commands/GuildCommands.cs +++ b/Source/Game/Chat/Commands/GuildCommands.cs @@ -128,9 +128,8 @@ namespace Game.Chat } [Command("rank", RBACPermissions.CommandGuildRank, true)] - static bool HandleGuildRankCommand(CommandHandler handler, string playerName, byte rank) + static bool HandleGuildRankCommand(CommandHandler handler, PlayerIdentifier player, byte rank) { - var player = PlayerIdentifier.ParseFromString(playerName); if (player == null) player = PlayerIdentifier.FromTargetOrSelf(handler); if (player == null) diff --git a/Source/Game/Chat/Commands/InstanceCommands.cs b/Source/Game/Chat/Commands/InstanceCommands.cs index 370f9a3f5..716f44631 100644 --- a/Source/Game/Chat/Commands/InstanceCommands.cs +++ b/Source/Game/Chat/Commands/InstanceCommands.cs @@ -29,10 +29,8 @@ namespace Game.Chat class InstanceCommands { [Command("getbossstate", RBACPermissions.CommandInstanceGetBossState)] - static bool HandleInstanceGetBossStateCommand(CommandHandler handler, uint encounterId, string playerName) + static bool HandleInstanceGetBossStateCommand(CommandHandler handler, uint encounterId, PlayerIdentifier player) { - var player = PlayerIdentifier.ParseFromString(playerName); - // Character name must be provided when using this from console. if (player == null || handler.GetSession() == null) { @@ -140,10 +138,8 @@ namespace Game.Chat } [Command("setbossstate", RBACPermissions.CommandInstanceSetBossState)] - static bool HandleInstanceSetBossStateCommand(CommandHandler handler, uint encounterId, EncounterState state, string playerName) + static bool HandleInstanceSetBossStateCommand(CommandHandler handler, uint encounterId, EncounterState state, PlayerIdentifier player) { - var player = PlayerIdentifier.ParseFromString(playerName); - // Character name must be provided when using this from console. if (player == null || handler.GetSession() == null) { diff --git a/Source/Game/Chat/Commands/LFGCommands.cs b/Source/Game/Chat/Commands/LFGCommands.cs index 795ca3493..6f16faa97 100644 --- a/Source/Game/Chat/Commands/LFGCommands.cs +++ b/Source/Game/Chat/Commands/LFGCommands.cs @@ -28,9 +28,8 @@ namespace Game.Chat class LFGCommands { [Command("player", RBACPermissions.CommandLfgPlayer, true)] - static bool HandleLfgPlayerInfoCommand(CommandHandler handler, string playerName) + static bool HandleLfgPlayerInfoCommand(CommandHandler handler, PlayerIdentifier player) { - var player = PlayerIdentifier.ParseFromString(playerName); if (player == null) player = PlayerIdentifier.FromTargetOrSelf(handler); if (player == null) @@ -47,9 +46,8 @@ namespace Game.Chat } [Command("group", RBACPermissions.CommandLfgGroup, true)] - static bool HandleLfgGroupInfoCommand(CommandHandler handler, string playerName) + static bool HandleLfgGroupInfoCommand(CommandHandler handler, PlayerIdentifier player) { - var player = PlayerIdentifier.ParseFromString(playerName); if (player == null) player = PlayerIdentifier.FromTargetOrSelf(handler); if (player == null) diff --git a/Source/Game/Chat/Commands/LearnCommands.cs b/Source/Game/Chat/Commands/LearnCommands.cs index 4ce4505a9..65948de79 100644 --- a/Source/Game/Chat/Commands/LearnCommands.cs +++ b/Source/Game/Chat/Commands/LearnCommands.cs @@ -28,7 +28,7 @@ namespace Game.Chat.Commands [CommandGroup("learn")] class LearnCommands { - [Command("", RBACPermissions.CommandLearn)] + [Command("", CypherStrings.CommandLearnHelp, RBACPermissions.CommandLearn)] static bool HandleLearnCommand(CommandHandler handler, uint spellId, string allRanksStr) { Player targetPlayer = handler.GetSelectedPlayerOrSelf(); @@ -69,7 +69,7 @@ namespace Game.Chat.Commands [CommandGroup("all")] class LearnAllCommands { - [Command("blizzard", RBACPermissions.CommandLearnAllGm)] + [Command("blizzard", CypherStrings.CommandLearnAllBlizzardHelp, RBACPermissions.CommandLearnAllGm)] static bool HandleLearnAllGMCommand(CommandHandler handler) { foreach (var skillSpell in Global.SpellMgr.GetSkillLineAbilityMapBounds((uint)SkillType.Internal)) @@ -85,7 +85,7 @@ namespace Game.Chat.Commands return true; } - [Command("debug", RBACPermissions.CommandLearn)] + [Command("debug", CypherStrings.CommandLearnAllDebugHelp, RBACPermissions.CommandLearn)] static bool HandleLearnDebugSpellsCommand(CommandHandler handler) { Player player = handler.GetPlayer(); @@ -99,10 +99,9 @@ namespace Game.Chat.Commands return true; } - [Command("crafts", RBACPermissions.CommandLearnAllCrafts)] - static bool HandleLearnAllCraftsCommand(CommandHandler handler, string playerName) + [Command("crafts", CypherStrings.CommandLearnAllCraftsHelp, RBACPermissions.CommandLearnAllCrafts)] + static bool HandleLearnAllCraftsCommand(CommandHandler handler, PlayerIdentifier player) { - var player = PlayerIdentifier.ParseFromString(playerName); if (player == null) player = PlayerIdentifier.FromTargetOrSelf(handler); if (player == null || !player.IsConnected()) @@ -117,10 +116,9 @@ namespace Game.Chat.Commands return true; } - [Command("default", RBACPermissions.CommandLearnAllDefault)] - static bool HandleLearnAllDefaultCommand(CommandHandler handler, string playerName) + [Command("default", CypherStrings.CommandLearnAllDefaultHelp, RBACPermissions.CommandLearnAllDefault)] + static bool HandleLearnAllDefaultCommand(CommandHandler handler, PlayerIdentifier player) { - var player = PlayerIdentifier.ParseFromString(playerName); if (player == null) player = PlayerIdentifier.FromTargetOrSelf(handler); if (player == null || !player.IsConnected()) @@ -135,7 +133,7 @@ namespace Game.Chat.Commands return true; } - [Command("languages", RBACPermissions.CommandLearnAllLang)] + [Command("languages", CypherStrings.CommandLearnAllLanguagesHelp, RBACPermissions.CommandLearnAllLang)] static bool HandleLearnAllLangCommand(CommandHandler handler, StringArguments args) { Global.LanguageMgr.ForEachLanguage((_, languageDesc) => @@ -150,7 +148,7 @@ namespace Game.Chat.Commands return true; } - [Command("recipes", RBACPermissions.CommandLearnAllRecipes)] + [Command("recipes", CypherStrings.CommandLearnAllRecipesHelp, RBACPermissions.CommandLearnAllRecipes)] static bool HandleLearnAllRecipesCommand(CommandHandler handler, string namePart) { // Learns all recipes of specified profession and sets skill to max @@ -212,7 +210,7 @@ namespace Game.Chat.Commands return true; } - [Command("talents", RBACPermissions.CommandLearnAllTalents)] + [Command("talents", CypherStrings.CommandLearnAllTalentsHelp, RBACPermissions.CommandLearnAllTalents)] static bool HandleLearnAllMyTalentsCommand(CommandHandler handler, StringArguments args) { Player player = handler.GetSession().GetPlayer(); @@ -241,7 +239,7 @@ namespace Game.Chat.Commands return true; } - [Command("pettalents", RBACPermissions.CommandLearnMyPetTalents)] + [Command("pettalents", CypherStrings.CommandLearnAllPettalentHelp, RBACPermissions.CommandLearnMyPetTalents)] static bool HandleLearnAllMyPetTalentsCommand(CommandHandler handler, StringArguments args) { return true; } static void HandleLearnSkillRecipesHelper(Player player, uint skillId) @@ -278,7 +276,7 @@ namespace Game.Chat.Commands [CommandGroup("my")] class LearnAllMyCommands { - [Command("quests", RBACPermissions.CommandLearnAllMySpells)] + [Command("quests", CypherStrings.CommandLearnMyQuestsHelp, RBACPermissions.CommandLearnAllMySpells)] static bool HandleLearnMyQuestsCommand(CommandHandler handler) { Player player = handler.GetPlayer(); @@ -290,7 +288,7 @@ namespace Game.Chat.Commands return true; } - [Command("trainer", RBACPermissions.CommandLearnAllMySpells)] + [Command("trainer", CypherStrings.CommandLearnMyTrainerHelp, RBACPermissions.CommandLearnAllMySpells)] static bool HandleLearnMySpellsCommand(CommandHandler handler) { ChrClassesRecord classEntry = CliDB.ChrClassesStorage.LookupByKey(handler.GetPlayer().GetClass()); @@ -329,7 +327,7 @@ namespace Game.Chat.Commands } } - [CommandNonGroup("unlearn", RBACPermissions.CommandUnlearn)] + [CommandNonGroup("unlearn", CypherStrings.CommandUnlearnHelp, RBACPermissions.CommandUnlearn)] static bool HandleUnLearnCommand(CommandHandler handler, uint spellId, string allRanksStr) { Player target = handler.GetSelectedPlayer(); diff --git a/Source/Game/Chat/Commands/LookupCommands.cs b/Source/Game/Chat/Commands/LookupCommands.cs index 30c99b955..619382da7 100644 --- a/Source/Game/Chat/Commands/LookupCommands.cs +++ b/Source/Game/Chat/Commands/LookupCommands.cs @@ -644,7 +644,7 @@ namespace Game.Chat } [CommandGroup("item")] - class ItemCommandGroup + class LookupItemCommands { [Command("", RBACPermissions.CommandLookupItem, true)] static bool HandleLookupItemCommand(CommandHandler handler, string namePart) @@ -708,14 +708,76 @@ namespace Game.Chat return true; } + + [Command("set", RBACPermissions.CommandLookupItemset, true)] + static bool HandleLookupItemSetCommand(CommandHandler handler, string namePart) + { + if (namePart.IsEmpty()) + return false; + + bool found = false; + uint count = 0; + uint maxResults = WorldConfig.GetUIntValue(WorldCfg.MaxResultsLookupCommands); + + // Search in ItemSet.dbc + foreach (var (id, set) in CliDB.ItemSetStorage) + { + Locale locale = handler.GetSessionDbcLocale(); + string name = set.Name[locale]; + if (name.IsEmpty()) + continue; + + if (!name.Equals(namePart, StringComparison.OrdinalIgnoreCase)) + { + locale = Locale.enUS; + for (; locale < Locale.Total; ++locale) + { + if (locale == handler.GetSessionDbcLocale()) + continue; + + name = set.Name[locale]; + if (name.IsEmpty()) + continue; + + if (name.Equals(namePart, StringComparison.OrdinalIgnoreCase)) + break; + } + } + + if (locale < Locale.Total) + { + if (maxResults != 0 && count++ == maxResults) + { + handler.SendSysMessage(CypherStrings.CommandLookupMaxResults, maxResults); + return true; + } + + // send item set in "id - [namedlink locale]" format + if (handler.GetSession()) + handler.SendSysMessage(CypherStrings.ItemsetListChat, id, id, name, ""); + else + handler.SendSysMessage(CypherStrings.ItemsetListConsole, id, name, ""); + + if (!found) + found = true; + } + } + if (!found) + handler.SendSysMessage(CypherStrings.CommandNoitemsetfound); + + return true; + } } [CommandGroup("map")] - class MapCommandGroup + class LookupMapCommands { - [Command("", RBACPermissions.CommandLookupMap, true)] + [Command("map", RBACPermissions.CommandLookupMap, true)] static bool HandleLookupMapCommand(CommandHandler handler, string namePart) { + if (namePart.IsEmpty()) + return false; + uint counter = 0; // search in Map.dbc @@ -785,7 +847,7 @@ namespace Game.Chat return true; } - [Command("", RBACPermissions.CommandLookupMap, true)] + [Command("id", RBACPermissions.CommandLookupMapId, true)] static bool HandleLookupMapIdCommand(CommandHandler handler, uint id) { var mapInfo = CliDB.MapStorage.LookupByKey(id); @@ -834,7 +896,7 @@ namespace Game.Chat } [CommandGroup("player")] - class PlayerCommandGroup + class LookupPlayerCommands { [Command("ip", RBACPermissions.CommandLookupPlayerIp)] static bool HandleLookupPlayerIpCommand(CommandHandler handler, string ip, int limit = -1) @@ -922,7 +984,7 @@ namespace Game.Chat } [CommandGroup("quest")] - class QuestCommandGroup + class LookupQuestCommands { [Command("", RBACPermissions.CommandLookupQuest, true)] static bool HandleLookupQuestCommand(CommandHandler handler, string namePart) @@ -1134,7 +1196,7 @@ namespace Game.Chat } [CommandGroup("spell")] - class SpellCommandGroup + class LookupSpellCommands { [Command("", RBACPermissions.CommandLookupSpell)] static bool HandleLookupSpellCommand(CommandHandler handler, string namePart) diff --git a/Source/Game/Chat/Commands/MMapsCommands.cs b/Source/Game/Chat/Commands/MMapsCommands.cs index 79c0caafb..ab3eee757 100644 --- a/Source/Game/Chat/Commands/MMapsCommands.cs +++ b/Source/Game/Chat/Commands/MMapsCommands.cs @@ -227,7 +227,7 @@ namespace Game.Chat } [Command("testarea", RBACPermissions.CommandMmapTestarea)] - static bool TestArea(CommandHandler handler, StringArguments args) + static bool TestArea(CommandHandler handler) { float radius = 40.0f; WorldObject obj = handler.GetPlayer(); diff --git a/Source/Game/Chat/Commands/MiscCommands.cs b/Source/Game/Chat/Commands/MiscCommands.cs index 3404a1c2d..08874c184 100644 --- a/Source/Game/Chat/Commands/MiscCommands.cs +++ b/Source/Game/Chat/Commands/MiscCommands.cs @@ -34,236 +34,6 @@ namespace Game.Chat { class MiscCommands { - [CommandNonGroup("additem", RBACPermissions.CommandAdditem)] - static bool HandleAddItemCommand(CommandHandler handler, StringArguments args) - { - if (args.Empty()) - return false; - - uint itemId = 0; - - if (args[0] == '[') // [name] manual form - { - string itemName = args.NextString("]"); - - if (!string.IsNullOrEmpty(itemName)) - { - var record = CliDB.ItemSparseStorage.Values.FirstOrDefault(itemSparse => - { - for (Locale i = 0; i < Locale.Total; ++i) - if (itemName == itemSparse.Display[i]) - return true; - return false; - }); - - if (record == null) - { - handler.SendSysMessage(CypherStrings.CommandCouldnotfind, itemName); - return false; - } - itemId = record.Id; - } - else - return false; - } - else // item_id or [name] Shift-click form |color|Hitem:item_id:0:0:0|h[name]|h|r - { - string idStr = handler.ExtractKeyFromLink(args, "Hitem"); - if (string.IsNullOrEmpty(idStr)) - return false; - - if (!uint.TryParse(idStr, out itemId)) - return false; - } - - int count = args.NextInt32(); - if (count == 0) - count = 1; - - List bonusListIDs = new(); - var bonuses = args.NextString(); - var context = args.NextString(); - - // semicolon separated bonuslist ids (parse them after all arguments are extracted by strtok!) - if (!bonuses.IsEmpty()) - { - var tokens = new StringArray(bonuses, ';'); - for (var i = 0; i < tokens.Length; ++i) - { - if (uint.TryParse(tokens[i], out uint id)) - bonusListIDs.Add(id); - } - } - - ItemContext itemContext = ItemContext.None; - if (!context.IsEmpty()) - { - itemContext = context.ToEnum(); - if (itemContext != ItemContext.None && itemContext < ItemContext.Max) - { - var contextBonuses = Global.DB2Mgr.GetDefaultItemBonusTree(itemId, itemContext); - bonusListIDs.AddRange(contextBonuses); - } - } - - Player player = handler.GetSession().GetPlayer(); - Player playerTarget = handler.GetSelectedPlayer(); - if (!playerTarget) - playerTarget = player; - - ItemTemplate itemTemplate = Global.ObjectMgr.GetItemTemplate(itemId); - if (itemTemplate == null) - { - handler.SendSysMessage(CypherStrings.CommandItemidinvalid, itemId); - return false; - } - - // Subtract - if (count < 0) - { - uint destroyedItemCount = playerTarget.DestroyItemCount(itemId, (uint)-count, true, false); - - if (destroyedItemCount > 0) - { - // output the amount of items successfully destroyed - handler.SendSysMessage(CypherStrings.Removeitem, itemId, destroyedItemCount, handler.GetNameLink(playerTarget)); - - // check to see if we were unable to destroy all of the amount requested. - uint unableToDestroyItemCount = (uint)(-count - destroyedItemCount); - if (unableToDestroyItemCount > 0) - { - // output message for the amount of items we couldn't destroy - handler.SendSysMessage(CypherStrings.RemoveitemFailure, itemId, unableToDestroyItemCount, handler.GetNameLink(playerTarget)); - } - } - else - { - // failed to destroy items of the amount requested - handler.SendSysMessage(CypherStrings.RemoveitemFailure, itemId, -count, handler.GetNameLink(playerTarget)); - } - return true; - } - - // Adding items - uint noSpaceForCount = 0; - - // check space and find places - List dest = new(); - InventoryResult msg = playerTarget.CanStoreNewItem(ItemConst.NullBag, ItemConst.NullSlot, dest, itemId, (uint)count, out noSpaceForCount); - if (msg != InventoryResult.Ok) // convert to possible store amount - count -= (int)noSpaceForCount; - - if (count == 0 || dest.Empty()) // can't add any - { - handler.SendSysMessage(CypherStrings.ItemCannotCreate, itemId, noSpaceForCount); - return false; - } - - Item item = playerTarget.StoreNewItem(dest, itemId, true, ItemEnchantmentManager.GenerateItemRandomBonusListId(itemId), null, itemContext, bonusListIDs); - - // remove binding (let GM give it to another player later) - if (player == playerTarget) - { - foreach (var posCount in dest) - { - Item item1 = player.GetItemByPos(posCount.pos); - if (item1) - item1.SetBinding(false); - } - } - - if (count > 0 && item) - { - player.SendNewItem(item, (uint)count, false, true); - handler.SendSysMessage(CypherStrings.Additem, itemId, count, handler.GetNameLink(playerTarget)); - if (player != playerTarget) - playerTarget.SendNewItem(item, (uint)count, true, false); - } - - if (noSpaceForCount > 0) - handler.SendSysMessage(CypherStrings.ItemCannotCreate, itemId, noSpaceForCount); - - return true; - } - - [CommandNonGroup("additem set", RBACPermissions.CommandAdditemset)] - static bool HandleAddItemSetCommand(CommandHandler handler, uint itemSetId, string bonuses, string context) - { - // prevent generation all items with itemset field value '0' - if (itemSetId == 0) - { - handler.SendSysMessage(CypherStrings.NoItemsFromItemsetFound, itemSetId); - return false; - } - - List bonusListIDs = new(); - - // semicolon separated bonuslist ids (parse them after all arguments are extracted by strtok!) - if (!bonuses.IsEmpty()) - { - var tokens = new StringArray(bonuses, ';'); - for (var i = 0; i < tokens.Length; ++i) - { - if (uint.TryParse(tokens[i], out uint id)) - bonusListIDs.Add(id); - } - } - - ItemContext itemContext = ItemContext.None; - if (!context.IsEmpty()) - itemContext = context.ToEnum(); - - Player player = handler.GetSession().GetPlayer(); - Player playerTarget = handler.GetSelectedPlayer(); - if (!playerTarget) - playerTarget = player; - - Log.outDebug(LogFilter.Server, Global.ObjectMgr.GetCypherString(CypherStrings.Additemset), itemSetId); - - bool found = false; - var its = Global.ObjectMgr.GetItemTemplates(); - foreach (var template in its) - { - if (template.Value.GetItemSet() != itemSetId) - continue; - - found = true; - List dest = new(); - InventoryResult msg = playerTarget.CanStoreNewItem(ItemConst.NullBag, ItemConst.NullSlot, dest, template.Value.GetId(), 1); - if (msg == InventoryResult.Ok) - { - List bonusListIDsForItem = new(bonusListIDs); // copy, bonuses for each depending on context might be different for each item - if (itemContext != ItemContext.None && itemContext < ItemContext.Max) - { - var contextBonuses = Global.DB2Mgr.GetDefaultItemBonusTree(template.Value.GetId(), itemContext); - bonusListIDsForItem.AddRange(contextBonuses); - } - - Item item = playerTarget.StoreNewItem(dest, template.Value.GetId(), true, 0, null, itemContext, bonusListIDsForItem); - - // remove binding (let GM give it to another player later) - if (player == playerTarget) - item.SetBinding(false); - - player.SendNewItem(item, 1, false, true); - if (player != playerTarget) - playerTarget.SendNewItem(item, 1, true, false); - } - else - { - player.SendEquipError(msg, null, null, template.Value.GetId()); - handler.SendSysMessage(CypherStrings.ItemCannotCreate, template.Value.GetId(), 1); - } - } - - if (!found) - { - handler.SendSysMessage(CypherStrings.CommandNoitemsetfound, itemSetId); - return false; - } - return true; - } - // Teleport to Player [CommandNonGroup("appear", RBACPermissions.CommandAppear)] static bool HandleAppearCommand(CommandHandler handler, StringArguments args) @@ -468,7 +238,7 @@ namespace Game.Chat [CommandNonGroup("commands", RBACPermissions.CommandCommands, true)] static bool HandleCommandsCommand(CommandHandler handler) { - handler.ShowHelpForCommand(CommandManager.GetCommands(), ""); + ChatCommandNode.SendCommandHelpFor(handler, ""); return true; } @@ -683,32 +453,32 @@ namespace Game.Chat switch (guidHigh) { case HighGuid.Player: + { + obj = Global.ObjAccessor.FindPlayer(ObjectGuid.Create(HighGuid.Player, guidLow)); + if (!obj) { - obj = Global.ObjAccessor.FindPlayer(ObjectGuid.Create(HighGuid.Player, guidLow)); - if (!obj) - { - handler.SendSysMessage(CypherStrings.PlayerNotFound); - } - break; + handler.SendSysMessage(CypherStrings.PlayerNotFound); } + break; + } case HighGuid.Creature: + { + obj = handler.GetCreatureFromPlayerMapByDbGuid(guidLow); + if (!obj) { - obj = handler.GetCreatureFromPlayerMapByDbGuid(guidLow); - if (!obj) - { - handler.SendSysMessage(CypherStrings.CommandNocreaturefound); - } - break; + handler.SendSysMessage(CypherStrings.CommandNocreaturefound); } + break; + } case HighGuid.GameObject: + { + obj = handler.GetObjectFromPlayerMapByDbGuid(guidLow); + if (!obj) { - obj = handler.GetObjectFromPlayerMapByDbGuid(guidLow); - if (!obj) - { - handler.SendSysMessage(CypherStrings.CommandNogameobjectfound); - } - break; + handler.SendSysMessage(CypherStrings.CommandNogameobjectfound); } + break; + } default: return false; } @@ -835,32 +605,32 @@ namespace Game.Chat switch (guidHigh) { case HighGuid.Player: + { + obj = Global.ObjAccessor.FindPlayer(ObjectGuid.Create(HighGuid.Player, guidLow)); + if (!obj) { - obj = Global.ObjAccessor.FindPlayer(ObjectGuid.Create(HighGuid.Player, guidLow)); - if (!obj) - { - handler.SendSysMessage(CypherStrings.PlayerNotFound); - } - break; + handler.SendSysMessage(CypherStrings.PlayerNotFound); } + break; + } case HighGuid.Creature: + { + obj = handler.GetCreatureFromPlayerMapByDbGuid(guidLow); + if (!obj) { - obj = handler.GetCreatureFromPlayerMapByDbGuid(guidLow); - if (!obj) - { - handler.SendSysMessage(CypherStrings.CommandNocreaturefound); - } - break; + handler.SendSysMessage(CypherStrings.CommandNocreaturefound); } + break; + } case HighGuid.GameObject: + { + obj = handler.GetObjectFromPlayerMapByDbGuid(guidLow); + if (!obj) { - obj = handler.GetObjectFromPlayerMapByDbGuid(guidLow); - if (!obj) - { - handler.SendSysMessage(CypherStrings.CommandNogameobjectfound); - } - break; + handler.SendSysMessage(CypherStrings.CommandNogameobjectfound); } + break; + } default: return false; } @@ -963,18 +733,11 @@ namespace Game.Chat } [CommandNonGroup("help", RBACPermissions.CommandHelp, true)] - static bool HandleHelpCommand(CommandHandler handler, string cmdArg) + static bool HandleHelpCommand(CommandHandler handler, string cmd) { - if (cmdArg.IsEmpty()) - { - handler.ShowHelpForCommand(CommandManager.GetCommands(), "help"); - handler.ShowHelpForCommand(CommandManager.GetCommands(), ""); - } - else - { - if (!handler.ShowHelpForCommand(CommandManager.GetCommands(), cmdArg)) - handler.SendSysMessage(CypherStrings.NoHelpCmd); - } + ChatCommandNode.SendCommandHelpFor(handler, cmd); + if (cmd.IsEmpty()) + ChatCommandNode.SendCommandHelpFor(handler, "help"); return true; } @@ -1242,12 +1005,11 @@ namespace Game.Chat // mute player for the specified duration [CommandNonGroup("mute", RBACPermissions.CommandMute, true)] - static bool HandleMuteCommand(CommandHandler handler, string playerName, uint muteTime, string muteReason) + static bool HandleMuteCommand(CommandHandler handler, PlayerIdentifier player, uint muteTime, string muteReason) { if (muteReason.IsEmpty()) muteReason = handler.GetCypherString(CypherStrings.NoReason); - var player = PlayerIdentifier.ParseFromString(playerName); if (player == null) player = PlayerIdentifier.FromTarget(handler); if (player == null) @@ -1417,7 +1179,7 @@ namespace Game.Chat [CommandNonGroup("pinfo", RBACPermissions.CommandPinfo, true)] static bool HandlePInfoCommand(CommandHandler handler, StringArguments args) - { + { // Define ALL the player variables! Player target; ObjectGuid targetGuid; @@ -1589,10 +1351,10 @@ namespace Game.Chat if (handler.HasPermission(RBACPermissions.CommandsPinfoCheckPersonalData) && // RBAC Perm. 48, Role 39 (!handler.GetSession() || handler.GetSession().GetSecurity() >= (AccountTypes)security)) { - eMail = result0.Read (2); - regMail = result0.Read (3); - lastIp = result0.Read (4); - lastLogin = result0.Read (5); + eMail = result0.Read(2); + regMail = result0.Read(3); + lastIp = result0.Read(4); + lastLogin = result0.Read(5); } else { @@ -1601,12 +1363,12 @@ namespace Game.Chat lastIp = handler.GetCypherString(CypherStrings.Unauthorized); lastLogin = handler.GetCypherString(CypherStrings.Unauthorized); } - muteTime = (long)result0.Read (6); - muteReason = result0.Read (7); - muteBy = result0.Read (8); - failedLogins = result0.Read (9); - locked = result0.Read (10); - OS = result0.Read (11); + muteTime = (long)result0.Read(6); + muteReason = result0.Read(7); + muteBy = result0.Read(8); + failedLogins = result0.Read(9); + locked = result0.Read(10); + OS = result0.Read(11); } // Creates a chat link to the character. Returns nameLink @@ -2332,7 +2094,7 @@ namespace Game.Chat { handler.SendSysMessage(CypherStrings.WeatherDisabled); return false; - } + } Player player = handler.GetSession().GetPlayer(); uint zoneid = player.GetZoneId(); @@ -2348,4 +2110,399 @@ namespace Game.Chat return true; } } + + [CommandGroup("additem")] + class MiscAddItemCommands + { + [Command("", RBACPermissions.CommandAdditem)] + static bool HandleAddItemCommand(CommandHandler handler, StringArguments args) + { + if (args.Empty()) + return false; + + uint itemId = 0; + + if (args[0] == '[') // [name] manual form + { + string itemName = args.NextString("]"); + + if (!string.IsNullOrEmpty(itemName)) + { + var record = CliDB.ItemSparseStorage.Values.FirstOrDefault(itemSparse => + { + for (Locale i = 0; i < Locale.Total; ++i) + if (itemName == itemSparse.Display[i]) + return true; + return false; + }); + + if (record == null) + { + handler.SendSysMessage(CypherStrings.CommandCouldnotfind, itemName); + return false; + } + itemId = record.Id; + } + else + return false; + } + else // item_id or [name] Shift-click form |color|Hitem:item_id:0:0:0|h[name]|h|r + { + string idStr = handler.ExtractKeyFromLink(args, "Hitem"); + if (string.IsNullOrEmpty(idStr)) + return false; + + if (!uint.TryParse(idStr, out itemId)) + return false; + } + + int count = args.NextInt32(); + if (count == 0) + count = 1; + + List bonusListIDs = new(); + var bonuses = args.NextString(); + var context = args.NextString(); + + // semicolon separated bonuslist ids (parse them after all arguments are extracted by strtok!) + if (!bonuses.IsEmpty()) + { + var tokens = new StringArray(bonuses, ';'); + for (var i = 0; i < tokens.Length; ++i) + { + if (uint.TryParse(tokens[i], out uint id)) + bonusListIDs.Add(id); + } + } + + ItemContext itemContext = ItemContext.None; + if (!context.IsEmpty()) + { + itemContext = context.ToEnum(); + if (itemContext != ItemContext.None && itemContext < ItemContext.Max) + { + var contextBonuses = Global.DB2Mgr.GetDefaultItemBonusTree(itemId, itemContext); + bonusListIDs.AddRange(contextBonuses); + } + } + + Player player = handler.GetSession().GetPlayer(); + Player playerTarget = handler.GetSelectedPlayer(); + if (!playerTarget) + playerTarget = player; + + ItemTemplate itemTemplate = Global.ObjectMgr.GetItemTemplate(itemId); + if (itemTemplate == null) + { + handler.SendSysMessage(CypherStrings.CommandItemidinvalid, itemId); + return false; + } + + // Subtract + if (count < 0) + { + uint destroyedItemCount = playerTarget.DestroyItemCount(itemId, (uint)-count, true, false); + + if (destroyedItemCount > 0) + { + // output the amount of items successfully destroyed + handler.SendSysMessage(CypherStrings.Removeitem, itemId, destroyedItemCount, handler.GetNameLink(playerTarget)); + + // check to see if we were unable to destroy all of the amount requested. + uint unableToDestroyItemCount = (uint)(-count - destroyedItemCount); + if (unableToDestroyItemCount > 0) + { + // output message for the amount of items we couldn't destroy + handler.SendSysMessage(CypherStrings.RemoveitemFailure, itemId, unableToDestroyItemCount, handler.GetNameLink(playerTarget)); + } + } + else + { + // failed to destroy items of the amount requested + handler.SendSysMessage(CypherStrings.RemoveitemFailure, itemId, -count, handler.GetNameLink(playerTarget)); + } + return true; + } + + // Adding items + uint noSpaceForCount = 0; + + // check space and find places + List dest = new(); + InventoryResult msg = playerTarget.CanStoreNewItem(ItemConst.NullBag, ItemConst.NullSlot, dest, itemId, (uint)count, out noSpaceForCount); + if (msg != InventoryResult.Ok) // convert to possible store amount + count -= (int)noSpaceForCount; + + if (count == 0 || dest.Empty()) // can't add any + { + handler.SendSysMessage(CypherStrings.ItemCannotCreate, itemId, noSpaceForCount); + return false; + } + + Item item = playerTarget.StoreNewItem(dest, itemId, true, ItemEnchantmentManager.GenerateItemRandomBonusListId(itemId), null, itemContext, bonusListIDs); + + // remove binding (let GM give it to another player later) + if (player == playerTarget) + { + foreach (var posCount in dest) + { + Item item1 = player.GetItemByPos(posCount.pos); + if (item1) + item1.SetBinding(false); + } + } + + if (count > 0 && item) + { + player.SendNewItem(item, (uint)count, false, true); + handler.SendSysMessage(CypherStrings.Additem, itemId, count, handler.GetNameLink(playerTarget)); + if (player != playerTarget) + playerTarget.SendNewItem(item, (uint)count, true, false); + } + + if (noSpaceForCount > 0) + handler.SendSysMessage(CypherStrings.ItemCannotCreate, itemId, noSpaceForCount); + + return true; + } + + [Command("set", RBACPermissions.CommandAdditemset)] + static bool HandleAddItemSetCommand(CommandHandler handler, uint itemSetId, string bonuses, string context) + { + // prevent generation all items with itemset field value '0' + if (itemSetId == 0) + { + handler.SendSysMessage(CypherStrings.NoItemsFromItemsetFound, itemSetId); + return false; + } + + List bonusListIDs = new(); + + // semicolon separated bonuslist ids (parse them after all arguments are extracted by strtok!) + if (!bonuses.IsEmpty()) + { + var tokens = new StringArray(bonuses, ';'); + for (var i = 0; i < tokens.Length; ++i) + { + if (uint.TryParse(tokens[i], out uint id)) + bonusListIDs.Add(id); + } + } + + ItemContext itemContext = ItemContext.None; + if (!context.IsEmpty()) + itemContext = context.ToEnum(); + + Player player = handler.GetSession().GetPlayer(); + Player playerTarget = handler.GetSelectedPlayer(); + if (!playerTarget) + playerTarget = player; + + Log.outDebug(LogFilter.Server, Global.ObjectMgr.GetCypherString(CypherStrings.Additemset), itemSetId); + + bool found = false; + var its = Global.ObjectMgr.GetItemTemplates(); + foreach (var template in its) + { + if (template.Value.GetItemSet() != itemSetId) + continue; + + found = true; + List dest = new(); + InventoryResult msg = playerTarget.CanStoreNewItem(ItemConst.NullBag, ItemConst.NullSlot, dest, template.Value.GetId(), 1); + if (msg == InventoryResult.Ok) + { + List bonusListIDsForItem = new(bonusListIDs); // copy, bonuses for each depending on context might be different for each item + if (itemContext != ItemContext.None && itemContext < ItemContext.Max) + { + var contextBonuses = Global.DB2Mgr.GetDefaultItemBonusTree(template.Value.GetId(), itemContext); + bonusListIDsForItem.AddRange(contextBonuses); + } + + Item item = playerTarget.StoreNewItem(dest, template.Value.GetId(), true, 0, null, itemContext, bonusListIDsForItem); + + // remove binding (let GM give it to another player later) + if (player == playerTarget) + item.SetBinding(false); + + player.SendNewItem(item, 1, false, true); + if (player != playerTarget) + playerTarget.SendNewItem(item, 1, true, false); + } + else + { + player.SendEquipError(msg, null, null, template.Value.GetId()); + handler.SendSysMessage(CypherStrings.ItemCannotCreate, template.Value.GetId(), 1); + } + } + + if (!found) + { + handler.SendSysMessage(CypherStrings.CommandNoitemsetfound, itemSetId); + return false; + } + return true; + } + + [Command("to", RBACPermissions.CommandAdditemset)] + static bool HandleAddItemToCommand(CommandHandler handler, StringArguments args) + { + if (args.Empty()) + return false; + + Player player = handler.GetSession().GetPlayer(); + Player playerTarget = null; + if (!handler.ExtractPlayerTarget(args, out playerTarget)) + return false; + + StringArguments tailArgs = new StringArguments(args.NextString("")); + if (tailArgs.Empty()) + return false; + + uint itemId = 0; + + if (tailArgs[0] == '[') // [name] manual form + { + string itemNameStr = tailArgs.NextString("]"); + + if (!itemNameStr.IsEmpty()) + { + string itemName = itemNameStr.Substring(1); + var itr = CliDB.ItemSparseStorage.Values.FirstOrDefault(sparse => + { + for (Locale i = Locale.enUS; i < Locale.Total; ++i) + if (itemName == sparse.Display[i]) + return true; + return false; + }); + + if (itr == null) + { + handler.SendSysMessage(CypherStrings.CommandCouldnotfind, itemName); + return false; + } + + itemId = itr.Id; + } + else + return false; + } + else // item_id or [name] Shift-click form |color|Hitem:item_id:0:0:0|h[name]|h|r + { + string id = handler.ExtractKeyFromLink(tailArgs, "Hitem"); + if (id.IsEmpty()) + return false; + itemId = uint.Parse(id); + } + + string ccount = tailArgs.NextString(); + + int count = 1; + if (!ccount.IsEmpty()) + count = int.Parse(ccount); + + if (count == 0) + count = 1; + + List bonusListIDs = new(); + string bonuses = tailArgs.NextString(); + + string context = tailArgs.NextString(); + + ItemContext itemContext = ItemContext.None; + if (!context.IsEmpty()) + { + itemContext = context.ToEnum(); + if (itemContext != ItemContext.None && itemContext < ItemContext.Max) + { + var contextBonuses = Global.DB2Mgr.GetDefaultItemBonusTree(itemId, itemContext); + bonusListIDs.AddRange(contextBonuses); + } + } + + // semicolon separated bonuslist ids + if (!bonuses.IsEmpty()) + { + foreach (var token in bonuses.Split(';', StringSplitOptions.RemoveEmptyEntries)) + { + if (uint.TryParse(token, out uint bonusListId)) + bonusListIDs.Add(bonusListId); + } + } + + ItemTemplate itemTemplate = Global.ObjectMgr.GetItemTemplate(itemId); + if (itemTemplate == null) + { + handler.SendSysMessage(CypherStrings.CommandItemidinvalid, itemId); + return false; + } + + // Subtract + if (count < 0) + { + uint destroyedItemCount = playerTarget.DestroyItemCount(itemId, (uint)-count, true, false); + + if (destroyedItemCount > 0) + { + // output the amount of items successfully destroyed + handler.SendSysMessage(CypherStrings.Removeitem, itemId, destroyedItemCount, handler.GetNameLink(playerTarget)); + + // check to see if we were unable to destroy all of the amount requested. + uint unableToDestroyItemCount = (uint)(-count - destroyedItemCount); + if (unableToDestroyItemCount > 0) + { + // output message for the amount of items we couldn't destroy + handler.SendSysMessage(CypherStrings.RemoveitemFailure, itemId, unableToDestroyItemCount, handler.GetNameLink(playerTarget)); + } + } + else + { + // failed to destroy items of the amount requested + handler.SendSysMessage(CypherStrings.RemoveitemFailure, itemId, -count, handler.GetNameLink(playerTarget)); + } + + return true; + } + + // Adding items + uint noSpaceForCount = 0; + + // check space and find places + List dest = new(); + InventoryResult msg = playerTarget.CanStoreNewItem(ItemConst.NullBag, ItemConst.NullSlot, dest, itemId, (uint)count, out noSpaceForCount); + if (msg != InventoryResult.Ok) // convert to possible store amount + count -= (int)noSpaceForCount; + + if (count == 0 || dest.Empty()) // can't add any + { + handler.SendSysMessage(CypherStrings.ItemCannotCreate, itemId, noSpaceForCount); + return false; + } + + Item item = playerTarget.StoreNewItem(dest, itemId, true, ItemEnchantmentManager.GenerateItemRandomBonusListId(itemId), null, itemContext, bonusListIDs); + + // remove binding (let GM give it to another player later) + if (player == playerTarget) + { + foreach (var itemPostCount in dest) + { + Item item1 = player.GetItemByPos(itemPostCount.pos); + if (item1 != null) + item1.SetBinding(false); + } + } + + if (count > 0 && item) + { + player.SendNewItem(item, (uint)count, false, true); + if (player != playerTarget) + playerTarget.SendNewItem(item, (uint)count, true, false); + } + + if (noSpaceForCount > 0) + handler.SendSysMessage(CypherStrings.ItemCannotCreate, itemId, noSpaceForCount); + + return true; + } + } } \ No newline at end of file diff --git a/Source/Game/Chat/Commands/ModifyCommands.cs b/Source/Game/Chat/Commands/ModifyCommands.cs index 96b6225d5..a8acae02a 100644 --- a/Source/Game/Chat/Commands/ModifyCommands.cs +++ b/Source/Game/Chat/Commands/ModifyCommands.cs @@ -674,6 +674,35 @@ namespace Game.Chat return true; } + [Command("xp", RBACPermissions.CommandModifyXp)] + static bool HandleModifyXPCommand(CommandHandler handler, StringArguments args) + { + if (args.Empty()) + return false; + + int xp = args.NextInt32(); + + if (xp < 1) + { + handler.SendSysMessage(CypherStrings.BadValue); + return false; + } + + Player target = handler.GetSelectedPlayerOrSelf(); + if (!target) + { + handler.SendSysMessage(CypherStrings.NoCharSelected); + return false; + } + + if (handler.HasLowerSecurity(target, ObjectGuid.Empty)) + return false; + + // we can run the command + target.GiveXP((uint)xp, null); + return true; + } + [CommandNonGroup("morph", RBACPermissions.CommandMorph)] static bool HandleModifyMorphCommand(CommandHandler handler, StringArguments args) { @@ -711,35 +740,6 @@ namespace Game.Chat return true; } - [Command("xp", RBACPermissions.CommandModifyXp)] - static bool HandleModifyXPCommand(CommandHandler handler, StringArguments args) - { - if (args.Empty()) - return false; - - int xp = args.NextInt32(); - - if (xp < 1) - { - handler.SendSysMessage(CypherStrings.BadValue); - return false; - } - - Player target = handler.GetSelectedPlayerOrSelf(); - if (!target) - { - handler.SendSysMessage(CypherStrings.NoCharSelected); - return false; - } - - if (handler.HasLowerSecurity(target, ObjectGuid.Empty)) - return false; - - // we can run the command - target.GiveXP((uint)xp, null); - return true; - } - [CommandGroup("speed")] class ModifySpeed { diff --git a/Source/Game/Chat/Commands/NPCCommands.cs b/Source/Game/Chat/Commands/NPCCommands.cs index 1060c2ad5..507369293 100644 --- a/Source/Game/Chat/Commands/NPCCommands.cs +++ b/Source/Game/Chat/Commands/NPCCommands.cs @@ -149,11 +149,11 @@ namespace Game.Chat handler.SendSysMessage(CypherStrings.NpcinfoArmor, target.GetArmor()); handler.SendSysMessage(CypherStrings.NpcinfoPosition, target.GetPositionX(), target.GetPositionY(), target.GetPositionZ()); - handler.SendSysMessage(CypherStrings.ObjectInfoAIInfo, target.GetAIName(), target.GetScriptName()); - handler.SendSysMessage(CypherStrings.NpcinfoReactState, target.GetReactState()); + handler.SendSysMessage(CypherStrings.ObjectinfoAiInfo, target.GetAIName(), target.GetScriptName()); + handler.SendSysMessage(CypherStrings.NpcinfoReactstate, target.GetReactState()); var ai = target.GetAI(); if (ai != null) - handler.SendSysMessage(CypherStrings.ObjectInfoAIType, nameof(ai)); + handler.SendSysMessage(CypherStrings.ObjectinfoAiType, nameof(ai)); handler.SendSysMessage(CypherStrings.NpcinfoFlagsExtra, cInfo.FlagsExtra); foreach (uint value in Enum.GetValues(typeof(CreatureFlagsExtra))) if (cInfo.FlagsExtra.HasAnyFlag((CreatureFlagsExtra)value)) @@ -331,43 +331,43 @@ namespace Game.Chat return false; } - handler.SendSysMessage(CypherStrings.CommandNpcShowLootHeader, creatureTarget.GetName(), creatureTarget.GetEntry()); - handler.SendSysMessage(CypherStrings.CommandNpcShowLootMoney, loot.gold / MoneyConstants.Gold, (loot.gold % MoneyConstants.Gold) / MoneyConstants.Silver, loot.gold % MoneyConstants.Silver); + handler.SendSysMessage(CypherStrings.CommandNpcShowlootHeader, creatureTarget.GetName(), creatureTarget.GetEntry()); + handler.SendSysMessage(CypherStrings.CommandNpcShowlootMoney, loot.gold / MoneyConstants.Gold, (loot.gold % MoneyConstants.Gold) / MoneyConstants.Silver, loot.gold % MoneyConstants.Silver); if (all.Equals("all", StringComparison.OrdinalIgnoreCase)) // nonzero from strcmp <. not equal { - handler.SendSysMessage(CypherStrings.CommandNpcShowLootLabel, "Standard items", loot.items.Count); + handler.SendSysMessage(CypherStrings.CommandNpcShowlootLabel, "Standard items", loot.items.Count); foreach (LootItem item in loot.items) if (!item.is_looted) _ShowLootEntry(handler, item.itemid, item.count); - handler.SendSysMessage(CypherStrings.CommandNpcShowLootLabel, "Quest items", loot.quest_items.Count); + handler.SendSysMessage(CypherStrings.CommandNpcShowlootLabel, "Quest items", loot.quest_items.Count); foreach (LootItem item in loot.quest_items) if (!item.is_looted) _ShowLootEntry(handler, item.itemid, item.count); } else { - handler.SendSysMessage(CypherStrings.CommandNpcShowLootLabel, "Standard items", loot.items.Count); + handler.SendSysMessage(CypherStrings.CommandNpcShowlootLabel, "Standard items", loot.items.Count); foreach (LootItem item in loot.items) if (!item.is_looted && !item.freeforall && item.conditions.Empty()) _ShowLootEntry(handler, item.itemid, item.count); if (!loot.GetPlayerQuestItems().Empty()) { - handler.SendSysMessage(CypherStrings.CommandNpcShowLootLabel2, "Per-player quest items"); + handler.SendSysMessage(CypherStrings.CommandNpcShowlootLabel2, "Per-player quest items"); _IterateNotNormalLootMap(handler, loot.GetPlayerQuestItems(), loot.quest_items); } if (!loot.GetPlayerFFAItems().Empty()) { - handler.SendSysMessage(CypherStrings.CommandNpcShowLootLabel2, "FFA items per allowed player"); + handler.SendSysMessage(CypherStrings.CommandNpcShowlootLabel2, "FFA items per allowed player"); _IterateNotNormalLootMap(handler, loot.GetPlayerFFAItems(), loot.items); } if (!loot.GetPlayerNonQuestNonFFAConditionalItems().Empty()) { - handler.SendSysMessage(CypherStrings.CommandNpcShowLootLabel2, "Per-player conditional items"); + handler.SendSysMessage(CypherStrings.CommandNpcShowlootLabel2, "Per-player conditional items"); _IterateNotNormalLootMap(handler, loot.GetPlayerNonQuestNonFFAConditionalItems(), loot.items); } } @@ -548,7 +548,7 @@ namespace Game.Chat if (itemTemplate != null) name = itemTemplate.GetName(handler.GetSessionDbcLocale()); - handler.SendSysMessage(alternateString ? CypherStrings.CommandNpcShowLootEntry2 : CypherStrings.CommandNpcShowLootEntry, + handler.SendSysMessage(alternateString ? CypherStrings.CommandNpcShowlootEntry2 : CypherStrings.CommandNpcShowlootEntry, itemCount, ItemConst.ItemQualityColors[(int)(itemTemplate != null ? itemTemplate.GetQuality() : ItemQuality.Poor)], itemId, name, itemId); } static void _IterateNotNormalLootMap(CommandHandler handler, MultiMap map, List items) @@ -561,7 +561,7 @@ namespace Game.Chat var list = map[key]; Player player = Global.ObjAccessor.FindConnectedPlayer(key); - handler.SendSysMessage(CypherStrings.CommandNpcShowLootSublabel, player ? player.GetName() : $"Offline player (GUID {key})", list.Count); + handler.SendSysMessage(CypherStrings.CommandNpcShowlootSublabel, player ? player.GetName() : $"Offline player (GUID {key})", list.Count); foreach (var it in list) { diff --git a/Source/Game/Chat/Commands/RbacCommands.cs b/Source/Game/Chat/Commands/RbacCommands.cs index 921139c13..85ea72288 100644 --- a/Source/Game/Chat/Commands/RbacCommands.cs +++ b/Source/Game/Chat/Commands/RbacCommands.cs @@ -63,9 +63,8 @@ namespace Game.Chat.Commands class RbacAccountCommands { [Command("deny", RBACPermissions.CommandRbacAccPermDeny, true)] - static bool HandleRBACPermDenyCommand(CommandHandler handler, string accountName, uint permId, int? realmId) + static bool HandleRBACPermDenyCommand(CommandHandler handler, AccountIdentifier account, uint permId, int? realmId) { - var account = AccountIdentifier.ParseFromString(accountName); if (account == null) account = AccountIdentifier.FromTarget(handler); if (account == null) @@ -107,9 +106,8 @@ namespace Game.Chat.Commands } [Command("grant", RBACPermissions.CommandRbacAccPermGrant, true)] - static bool HandleRBACPermGrantCommand(CommandHandler handler, string accountName, uint permId, int? realmId) + static bool HandleRBACPermGrantCommand(CommandHandler handler, AccountIdentifier account, uint permId, int? realmId) { - var account = AccountIdentifier.ParseFromString(accountName); if (account == null) account = AccountIdentifier.FromTarget(handler); if (account == null) @@ -151,9 +149,8 @@ namespace Game.Chat.Commands } [Command("list", RBACPermissions.CommandRbacAccPermList, true)] - static bool HandleRBACPermListCommand(CommandHandler handler, string accountName) + static bool HandleRBACPermListCommand(CommandHandler handler, AccountIdentifier account) { - var account = AccountIdentifier.ParseFromString(accountName); if (account == null) account = AccountIdentifier.FromTarget(handler); if (account == null) @@ -203,9 +200,8 @@ namespace Game.Chat.Commands } [Command("revoke", RBACPermissions.CommandRbacAccPermRevoke, true)] - static bool HandleRBACPermRevokeCommand(CommandHandler handler, string accountName, uint permId, int? realmId) + static bool HandleRBACPermRevokeCommand(CommandHandler handler, AccountIdentifier account, uint permId, int? realmId) { - var account = AccountIdentifier.ParseFromString(accountName); if (account == null) account = AccountIdentifier.FromTarget(handler); if (account == null) diff --git a/Source/Game/Chat/Commands/ReloadCommand.cs b/Source/Game/Chat/Commands/ReloadCommand.cs index cd52fc8c0..5f8aac30f 100644 --- a/Source/Game/Chat/Commands/ReloadCommand.cs +++ b/Source/Game/Chat/Commands/ReloadCommand.cs @@ -849,6 +849,17 @@ namespace Game.Chat return true; } + [Command("spell_script_names", RBACPermissions.CommandReloadSpellScriptNames, true)] + static bool HandleReloadSpellScriptNamesCommand(CommandHandler handler) + { + Log.outInfo(LogFilter.Misc, "Reloading spell_script_names table..."); + Global.ObjectMgr.LoadSpellScriptNames(); + //Global.ScriptMgr.NotifyScriptIDUpdate(); + Global.ObjectMgr.ValidateSpellScripts(); + handler.SendGlobalGMSysMessage("Spell scripts reloaded."); + return true; + } + [Command("spell_target_position", RBACPermissions.CommandReloadSpellTargetPosition, true)] static bool HandleReloadSpellTargetPositionCommand(CommandHandler handler, StringArguments args) { diff --git a/Source/Game/Chat/Commands/ServerCommands.cs b/Source/Game/Chat/Commands/ServerCommands.cs index f0c8b4f79..966469d6f 100644 --- a/Source/Game/Chat/Commands/ServerCommands.cs +++ b/Source/Game/Chat/Commands/ServerCommands.cs @@ -26,20 +26,20 @@ namespace Game.Chat class ServerCommands { [Command("corpses", RBACPermissions.CommandServerCorpses, true)] - static bool HandleServerCorpsesCommand(CommandHandler handler, StringArguments args) + static bool HandleServerCorpsesCommand(CommandHandler handler) { Global.WorldMgr.RemoveOldCorpses(); return true; } [Command("debug", RBACPermissions.CommandServerCorpses, true)] - static bool HandleServerDebugCommand(CommandHandler handler, StringArguments args) + static bool HandleServerDebugCommand(CommandHandler handler) { return false;//todo fix me } [Command("exit", RBACPermissions.CommandServerExit, true)] - static bool HandleServerExitCommand(CommandHandler handler, StringArguments args) + static bool HandleServerExitCommand(CommandHandler handler) { handler.SendSysMessage(CypherStrings.CommandExit); Global.WorldMgr.StopNow(ShutdownExitCode.Shutdown); @@ -47,7 +47,7 @@ namespace Game.Chat } [Command("info", RBACPermissions.CommandServerInfo, true)] - static bool HandleServerInfoCommand(CommandHandler handler, StringArguments args) + static bool HandleServerInfoCommand(CommandHandler handler) { uint playersNum = Global.WorldMgr.GetPlayerCount(); uint maxPlayersNum = Global.WorldMgr.GetMaxPlayerCount(); @@ -70,7 +70,7 @@ namespace Game.Chat } [Command("motd", RBACPermissions.CommandServerMotd, true)] - static bool HandleServerMotdCommand(CommandHandler handler, StringArguments args) + static bool HandleServerMotdCommand(CommandHandler handler) { string motd = ""; foreach (var line in Global.WorldMgr.GetMotd()) @@ -240,7 +240,7 @@ namespace Game.Chat } [Command("cancel", RBACPermissions.CommandServerIdlerestartCancel, true)] - static bool HandleServerShutDownCancelCommand(CommandHandler handler, StringArguments args) + static bool HandleServerShutDownCancelCommand(CommandHandler handler) { uint timer = Global.WorldMgr.ShutdownCancel(); if (timer != 0) @@ -259,7 +259,7 @@ namespace Game.Chat } [Command("cancel", RBACPermissions.CommandServerIdleshutdownCancel, true)] - static bool HandleServerShutDownCancelCommand(CommandHandler handler, StringArguments args) + static bool HandleServerShutDownCancelCommand(CommandHandler handler) { uint timer = Global.WorldMgr.ShutdownCancel(); if (timer != 0) @@ -279,7 +279,7 @@ namespace Game.Chat } [Command("cancel", RBACPermissions.CommandServerRestartCancel, true)] - static bool HandleServerShutDownCancelCommand(CommandHandler handler, StringArguments args) + static bool HandleServerShutDownCancelCommand(CommandHandler handler) { uint timer = Global.WorldMgr.ShutdownCancel(); if (timer != 0) @@ -305,7 +305,7 @@ namespace Game.Chat } [Command("cancel", RBACPermissions.CommandServerShutdownCancel, true)] - static bool HandleServerShutDownCancelCommand(CommandHandler handler, StringArguments args) + static bool HandleServerShutDownCancelCommand(CommandHandler handler) { uint timer = Global.WorldMgr.ShutdownCancel(); if (timer != 0) @@ -353,7 +353,7 @@ namespace Game.Chat } [Command("motd", RBACPermissions.CommandServerSetMotd, true)] - static bool SetMotd(CommandHandler handler, StringArguments args) + static bool HandleServerSetMotdCommand(CommandHandler handler, StringArguments args) { Global.WorldMgr.SetMotd(args.NextString("")); handler.SendSysMessage(CypherStrings.MotdNew, args.GetString()); @@ -361,7 +361,7 @@ namespace Game.Chat } [Command("closed", RBACPermissions.CommandServerSetClosed, true)] - static bool SetClosed(CommandHandler handler, StringArguments args) + static bool HandleServerSetClosedCommand(CommandHandler handler, StringArguments args) { string arg1 = args.NextString(); if (arg1.Equals("on", StringComparison.OrdinalIgnoreCase)) diff --git a/Source/Game/Chat/Commands/TeleCommands.cs b/Source/Game/Chat/Commands/TeleCommands.cs index feb14cfe6..bf4e58b87 100644 --- a/Source/Game/Chat/Commands/TeleCommands.cs +++ b/Source/Game/Chat/Commands/TeleCommands.cs @@ -92,7 +92,7 @@ namespace Game.Chat } else { - handler.SendSysMessage(CypherStrings.CommandTpAddedError); + handler.SendSysMessage(CypherStrings.CommandTpAddedErr); return false; } @@ -240,9 +240,8 @@ namespace Game.Chat class TeleNameCommands { [Command("", RBACPermissions.CommandTeleName, true)] - static bool HandleTeleNameCommand(CommandHandler handler, string playerName, string where) + static bool HandleTeleNameCommand(CommandHandler handler, PlayerIdentifier player, string where) { - var player = PlayerIdentifier.ParseFromString(playerName); if (player == null) player = PlayerIdentifier.FromTargetOrSelf(handler); if (player == null) @@ -284,9 +283,8 @@ namespace Game.Chat class TeleNameNpcCommands { [Command("guid", RBACPermissions.CommandTeleName, true)] - static bool HandleTeleNameNpcSpawnIdCommand(CommandHandler handler, string playerName, ulong spawnId) + static bool HandleTeleNameNpcSpawnIdCommand(CommandHandler handler, PlayerIdentifier player, ulong spawnId) { - var player = PlayerIdentifier.ParseFromString(playerName); if (player == null) return false; @@ -303,9 +301,8 @@ namespace Game.Chat } [Command("id", RBACPermissions.CommandTeleName, true)] - static bool HandleTeleNameNpcIdCommand(CommandHandler handler, string playerName, uint creatureId) + static bool HandleTeleNameNpcIdCommand(CommandHandler handler, PlayerIdentifier player, uint creatureId) { - var player = PlayerIdentifier.ParseFromString(playerName); if (player == null) return false; @@ -336,9 +333,8 @@ namespace Game.Chat } [Command("name", RBACPermissions.CommandTeleName, true)] - static bool HandleTeleNameNpcNameCommand(CommandHandler handler, string playerName, string name) + static bool HandleTeleNameNpcNameCommand(CommandHandler handler, PlayerIdentifier player, string name) { - var player = PlayerIdentifier.ParseFromString(playerName); if (player == null) return false; diff --git a/Source/Game/Chat/Hyperlink.cs b/Source/Game/Chat/Hyperlink.cs index 45f5f102b..a1e904b10 100644 --- a/Source/Game/Chat/Hyperlink.cs +++ b/Source/Game/Chat/Hyperlink.cs @@ -73,44 +73,18 @@ namespace Game.Chat return true; } case TypeCode.Object: - return TryParseToObject(out value, type, info); - } - - return false; - } - - public static bool TryParseToObject(out dynamic value, Type type, HyperlinkInfo info) - { - value = default; - - switch (type.Name) - { - case nameof(CurrencyTypesRecord): { - HyperlinkDataTokenizer t = new(info.Data); - if (!t.TryConsumeTo(out uint currencyId)) - return false; - - value = CliDB.CurrencyTypesStorage.LookupByKey(currencyId); - return true; - } - case nameof(GameTele): - { - HyperlinkDataTokenizer t = new(info.Data); - if (!t.TryConsumeTo(out uint teleId)) - return false; - - value = Global.ObjectMgr.GetGameTele(teleId); - return true; - } - case nameof(SpellInfo): - { - HyperlinkDataTokenizer t = new(info.Data); - if (!t.TryConsumeTo(out uint spellId)) - return false; - - value = Global.SpellMgr.GetSpellInfo(spellId, Difficulty.None); - + switch (type.Name) + { + case nameof(PlayerIdentifier): + value = PlayerIdentifier.ParseFromString(args.NextString()); + break; + case nameof(AccountIdentifier): + value = AccountIdentifier.ParseFromString(args.NextString()); + break; + default: + return false; + } return true; } } diff --git a/Source/Game/Handlers/ChatHandler.cs b/Source/Game/Handlers/ChatHandler.cs index 99485bf33..91fc328cb 100644 --- a/Source/Game/Handlers/ChatHandler.cs +++ b/Source/Game/Handlers/ChatHandler.cs @@ -173,7 +173,7 @@ namespace Game if (string.IsNullOrEmpty(msg)) return; - if (new CommandHandler(this).ParseCommand(msg)) + if (new CommandHandler(this).ParseCommands(msg)) return; switch (type) @@ -398,7 +398,7 @@ namespace Game if (!WorldConfig.GetBoolValue(WorldCfg.AddonChannel)) return; - if (prefix == AddonChannelCommandHandler.PREFIX && new AddonChannelCommandHandler(this).ParseCommand(text)) + if (prefix == AddonChannelCommandHandler.PREFIX && new AddonChannelCommandHandler(this).ParseCommands(text)) return; switch (type) diff --git a/Source/Game/Networking/RASocket.cs b/Source/Game/Networking/RASocket.cs index 548946977..fa54a66fc 100644 --- a/Source/Game/Networking/RASocket.cs +++ b/Source/Game/Networking/RASocket.cs @@ -210,7 +210,7 @@ namespace Game.Networking } RemoteAccessHandler cmd = new(CommandPrint); - cmd.ParseCommand(command); + cmd.ParseCommands(command); return true; }