From 6c5aca3c3af564f075c4d54dd33386826dd0de13 Mon Sep 17 00:00:00 2001 From: rfi Date: Mon, 13 Nov 2023 19:10:02 +0700 Subject: [PATCH] command yay! --- AscNet.Common/Database/Stage.cs | 5 +- AscNet.Common/MsgPack/Types.cs | 21 +-- AscNet.GameServer/Commands/Command.cs | 132 ++++++++++++++++++ AscNet.GameServer/Commands/StageCommand.cs | 73 ++++++++++ AscNet.GameServer/Handlers/AccountModule.cs | 4 +- AscNet.GameServer/Handlers/FightModule.cs | 29 +++- AscNet.GameServer/Packet.cs | 2 +- AscNet.GameServer/Server.cs | 11 +- AscNet.SDKServer/AscNet.SDKServer.csproj | 1 + .../Controllers/CommandController.cs | 69 +++++++++ AscNet.SDKServer/Models/CommandApi.cs | 11 ++ AscNet/Program.cs | 13 +- 12 files changed, 335 insertions(+), 36 deletions(-) create mode 100644 AscNet.GameServer/Commands/Command.cs create mode 100644 AscNet.GameServer/Commands/StageCommand.cs create mode 100644 AscNet.SDKServer/Controllers/CommandController.cs create mode 100644 AscNet.SDKServer/Models/CommandApi.cs diff --git a/AscNet.Common/Database/Stage.cs b/AscNet.Common/Database/Stage.cs index aa10fce..04b04a6 100644 --- a/AscNet.Common/Database/Stage.cs +++ b/AscNet.Common/Database/Stage.cs @@ -52,7 +52,10 @@ namespace AscNet.Common.Database public void AddStage(StageDatum stageData) { - Stages.Add(stageData.StageId, stageData); + if (Stages.ContainsKey(stageData.StageId)) + Stages[stageData.StageId] = stageData; + else + Stages.Add(stageData.StageId, stageData); } public void Save() diff --git a/AscNet.Common/MsgPack/Types.cs b/AscNet.Common/MsgPack/Types.cs index 8a2bce3..5e7641f 100644 --- a/AscNet.Common/MsgPack/Types.cs +++ b/AscNet.Common/MsgPack/Types.cs @@ -2452,26 +2452,7 @@ namespace AscNet.Common.MsgPack [global::MessagePack.MessagePackObject(true)] public class NotifyStageData { - [global::MessagePack.MessagePackObject(true)] - public class NotifyStageDataStage - { - public UInt32 StageId { get; set; } - public Int32 StarsMark { get; set; } - public Boolean Passed { get; set; } - public Int32 PassTimesToday { get; set; } - public Int32 PassTimesTotal { get; set; } - public Int32 BuyCount { get; set; } - public Int32 Score { get; set; } - public UInt32 LastPassTime { get; set; } - public UInt32 RefreshTime { get; set; } - public UInt32 CreateTime { get; set; } - public Int32 BestRecordTime { get; set; } - public Int32 LastRecordTime { get; set; } - public List BestCardIds { get; set; } = new(); - public List LastCardIds { get; set; } = new(); - } - - public List StageList { get; set; } = new(); + public List StageList { get; set; } = new(); } diff --git a/AscNet.GameServer/Commands/Command.cs b/AscNet.GameServer/Commands/Command.cs new file mode 100644 index 0000000..c736895 --- /dev/null +++ b/AscNet.GameServer/Commands/Command.cs @@ -0,0 +1,132 @@ +using System.Reflection; +using System.Text.RegularExpressions; +using AscNet.Logging; + +namespace AscNet.GameServer.Commands +{ + public abstract class Command + { + protected Session session; + protected string[] args; + + public abstract string Help { get; } + + /// + /// Make sure to handle me well... + /// + /// + /// + /// + public Command(Session session, string[] args, bool validate = true) + { + this.session = session; + this.args = args; + + string? ret = Validate(); + if (ret is not null && validate) + throw new ArgumentException(ret); + } + + public string? Validate() + { + List argsProperties = GetType().GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).Where(x => x.GetCustomAttribute(typeof(ArgumentAttribute)) is not null).ToList(); + if (argsProperties.Count != args.Length) + return "Invalid args length!"; + + foreach (var argProp in argsProperties) + { + ArgumentAttribute attr = (ArgumentAttribute)argProp.GetCustomAttribute(typeof(ArgumentAttribute))!; + if (!attr.Pattern.IsMatch(args[attr.Position])) + return $"Argument {argProp.Name} is invalid!"; + + argProp.SetValue(this, args[attr.Position]); + } + return null; + } + + public abstract void Execute(); + } + + [AttributeUsage(AttributeTargets.Property)] + public class ArgumentAttribute : Attribute + { + public int Position { get; } + public Regex Pattern { get; } + public string? Description { get; } + + public ArgumentAttribute(int position, string pattern, string? description = null) + { + Position = position; + Pattern = new(pattern); + Description = description; + } + } + + [AttributeUsage(AttributeTargets.Class)] + public class CommandNameAttribute : Attribute + { + public string Name { get; } + + public CommandNameAttribute(string name) + { + Name = name; + } + } + + [CommandName("help")] + internal class HelpCommand : Command + { + public HelpCommand(Session session, string[] args, bool validate = true) : base(session, args, validate) { } + + public override string Help => "Show this help."; + + public override void Execute() + { + string helpText = string.Empty; + + foreach (var command in CommandFactory.commands.Keys) + { + Command? cmd = CommandFactory.CreateCommand(command, session, args, false); + if (cmd is not null) + helpText += $"{command}\n\t└─{cmd.Help}\n"; + } + } + } + + public static class CommandFactory + { + public static readonly Dictionary commands = new(); + + internal static readonly Logger log = new(typeof(CommandFactory), LogLevel.DEBUG, LogLevel.DEBUG); + + public static void LoadCommands() + { + log.LogLevelColor[LogLevel.INFO] = ConsoleColor.White; + log.Info("Loading commands..."); + + IEnumerable classes = from t in Assembly.GetExecutingAssembly().GetTypes() + where t.IsClass && t.GetCustomAttribute() is not null + select t; + + foreach (var command in classes) + { + CommandNameAttribute nameAttr = command.GetCustomAttribute()!; + commands.Add(nameAttr.Name, command); +#if DEBUG + log.Info($"Loaded {nameAttr.Name} command"); +#endif + } + + log.Info("Finished loading commands"); + } + + public static Command? CreateCommand(string name, Session session, string[] args, bool validate = true) + { + Type? command = commands.GetValueOrDefault(name); + if (command is null) + return null; + + return (Command)Activator.CreateInstance(command, new object[] { session, args, validate })!; + } + } +} diff --git a/AscNet.GameServer/Commands/StageCommand.cs b/AscNet.GameServer/Commands/StageCommand.cs new file mode 100644 index 0000000..b3f4b41 --- /dev/null +++ b/AscNet.GameServer/Commands/StageCommand.cs @@ -0,0 +1,73 @@ +using AscNet.Common.MsgPack; +using AscNet.Table.share.fuben; + +namespace AscNet.GameServer.Commands +{ + [CommandName("stage")] + internal class StageCommand : Command + { + public StageCommand(Session session, string[] args, bool validate = true) : base(session, args, validate) { } + + [Argument(0, @"^[0-9]+$|^all$", "The target stage, value is stage id or 'all'")] + string TargetStage { get; set; } = string.Empty; + + public override string Help => "Modify the stage completion status of the account."; + + public override void Execute() + { + if (TargetStage == "all") + { + session.stage.Stages.Clear(); + foreach (var stageData in StageTableReader.Instance.All) + { + session.stage.Stages.Add(stageData.StageId, new() + { + StageId = stageData.StageId, + StarsMark = 7, + Passed = true, + PassTimesToday = 0, + PassTimesTotal = 1, + BuyCount = 0, + Score = 0, + LastPassTime = DateTimeOffset.Now.ToUnixTimeSeconds(), + RefreshTime = DateTimeOffset.Now.ToUnixTimeSeconds(), + CreateTime = DateTimeOffset.Now.ToUnixTimeSeconds(), + BestRecordTime = 0, + LastRecordTime = 0, + BestCardIds = new List { 1021001 }, + LastCardIds = new List { 1021001 } + }); + } + + session.SendPush(new NotifyStageData() { StageList = session.stage.Stages.Select(x => x.Value).ToList() }); + } + else + { + StageTable? stageData = StageTableReader.Instance.FromStageId(int.Parse(TargetStage)); + if (stageData is not null && !session.stage.Stages.ContainsKey(stageData.StageId)) + { + StageDatum stage = new() + { + StageId = stageData.StageId, + StarsMark = 7, + Passed = true, + PassTimesToday = 0, + PassTimesTotal = 1, + BuyCount = 0, + Score = 0, + LastPassTime = DateTimeOffset.Now.ToUnixTimeSeconds(), + RefreshTime = DateTimeOffset.Now.ToUnixTimeSeconds(), + CreateTime = DateTimeOffset.Now.ToUnixTimeSeconds(), + BestRecordTime = 0, + LastRecordTime = 0, + BestCardIds = new List { 1021001 }, + LastCardIds = new List { 1021001 } + }; + session.stage.Stages.Add(stageData.StageId, stage); + + session.SendPush(new NotifyStageData() { StageList = new() { stage } }); + } + } + } + } +} diff --git a/AscNet.GameServer/Handlers/AccountModule.cs b/AscNet.GameServer/Handlers/AccountModule.cs index 52211b2..18f7938 100644 --- a/AscNet.GameServer/Handlers/AccountModule.cs +++ b/AscNet.GameServer/Handlers/AccountModule.cs @@ -1,5 +1,6 @@ using AscNet.Common.Database; using AscNet.Common.MsgPack; +using AscNet.Table.share.fuben; using AscNet.Table.share.guide; using MessagePack; using Newtonsoft.Json; @@ -103,7 +104,7 @@ namespace AscNet.GameServer.Handlers BaseEquipLoginData = new(), FubenData = new() { - StageData = session.stage.Stages, + StageData = session.stage.Stages.ToDictionary(x => x.Key, x => x.Value), FubenBaseData = new() }, FubenMainLineData = new(), @@ -116,7 +117,6 @@ namespace AscNet.GameServer.Handlers notifyLogin.FashionList.AddRange(session.character.Fashions); #if DEBUG - // Per account settings flag(?) notifyLogin.PlayerData.GuideData = GuideGroupTableReader.Instance.All.Select(x => (long)x.Id).ToList(); #endif diff --git a/AscNet.GameServer/Handlers/FightModule.cs b/AscNet.GameServer/Handlers/FightModule.cs index e19620b..4ec2296 100644 --- a/AscNet.GameServer/Handlers/FightModule.cs +++ b/AscNet.GameServer/Handlers/FightModule.cs @@ -5,6 +5,8 @@ using MessagePack; namespace AscNet.GameServer.Handlers { + #region MsgPackScheme +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. [MessagePackObject(true)] public class Operation { @@ -54,7 +56,7 @@ namespace AscNet.GameServer.Handlers { public bool IsWin { get; set; } public bool IsForceExit { get; set; } - public int StageId { get; set; } + public uint StageId { get; set; } public int StageLevel { get; set; } public long FightId { get; set; } public int RebootCount { get; set; } @@ -99,7 +101,9 @@ namespace AscNet.GameServer.Handlers { public FightSettleResult Result { get; set; } } - +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + #endregion + internal class FightModule { [RequestPacketHandler("PreFightRequest")] @@ -168,7 +172,26 @@ namespace AscNet.GameServer.Handlers { FightSettleRequest req = MessagePackSerializer.Deserialize(packet.Content); - session.SendPush("NotifyStageData", MessagePackSerializer.ConvertFromJson($"{{\"StageList\": [{{\"StageId\": {req.Result.StageId}, \"StarsMark\": 7, \"Passed\": true, \"PassTimesToday\": 1, \"PassTimesTotal\": 2, \"BuyCount\": 0, \"Score\": 0, \"LastPassTime\": {DateTimeOffset.UtcNow.ToUnixTimeSeconds()}, \"RefreshTime\": {DateTimeOffset.UtcNow.ToUnixTimeSeconds()}, \"CreateTime\": 1626546618, \"BestRecordTime\": 17, \"LastRecordTime\": 17, \"BestCardIds\": [1021001, 1031003, 1051001], \"LastCardIds\": [1021001, 1031003, 1051001]}}]}}")); + StageDatum stageData = new() + { + StageId = req.Result.StageId, + StarsMark = 7, + Passed = true, + PassTimesToday = 0, + PassTimesTotal = 1, + BuyCount = 0, + Score = 0, + LastPassTime = (uint)DateTimeOffset.Now.ToUnixTimeSeconds(), + RefreshTime = (uint)DateTimeOffset.Now.ToUnixTimeSeconds(), + CreateTime = (uint)DateTimeOffset.Now.ToUnixTimeSeconds(), + BestRecordTime = 0, + LastRecordTime = 0, + BestCardIds = req.Result.NpcDpsTable.Where(x => x.Value.CharacterId > 0).Select(x => (long)x.Value.CharacterId).ToList(), + LastCardIds = req.Result.NpcDpsTable.Where(x => x.Value.CharacterId > 0).Select(x => (long)x.Value.CharacterId).ToList() + }; + session.stage.AddStage(stageData); + + session.SendPush(new NotifyStageData() { StageList = new() { stageData } }); session.SendResponse(MessagePackSerializer.Deserialize(MessagePackSerializer.ConvertFromJson($"{{\"Code\": 0, \"Settle\": {{\"IsWin\": true, \"StageId\": {req.Result.StageId}, \"StarsMark\": 7, \"RewardGoodsList\": [{{\"RewardType\": 1, \"TemplateId\": 1, \"Count\": 1947, \"Level\": 0, \"Quality\": 0, \"Grade\": 0, \"Breakthrough\": 0, \"ConvertFrom\": 0, \"Id\": 0}}, {{\"RewardType\": 1, \"TemplateId\": 30011, \"Count\": 1, \"Level\": 0, \"Quality\": 0, \"Grade\": 0, \"Breakthrough\": 0, \"ConvertFrom\": 0, \"Id\": 0}}, {{\"RewardType\": 1, \"TemplateId\": 30011, \"Count\": 1, \"Level\": 0, \"Quality\": 0, \"Grade\": 0, \"Breakthrough\": 0, \"ConvertFrom\": 0, \"Id\": 0}}, {{\"RewardType\": 3, \"TemplateId\": 3052001, \"Count\": 1, \"Level\": 1, \"Quality\": 0, \"Grade\": 0, \"Breakthrough\": 0, \"ConvertFrom\": 0, \"Id\": 0}}, {{\"RewardType\": 3, \"TemplateId\": 3034002, \"Count\": 1, \"Level\": 1, \"Quality\": 0, \"Grade\": 0, \"Breakthrough\": 0, \"ConvertFrom\": 0, \"Id\": 0}}], \"LeftTime\": 282, \"NpcHpInfo\": {{\"9\": {{\"CharacterId\": 0, \"NpcId\": 91030, \"Type\": 4, \"Level\": 7, \"BuffIds\": [9003, 900007, 900050, 701022, 900011, 900051, 910300, 715531, 700053, 715075, 700007, 900080, 700045, 100062, 700030, 700029, 710076, 700027, 700215, 700028], \"AttrTable\": {{\"1\": {{\"Value\": 1, \"MaxValue\": 751}}, \"2\": {{\"Value\": 0, \"MaxValue\": 100}}, \"3\": {{\"Value\": 84, \"MaxValue\": 84}}, \"4\": {{\"Value\": 84, \"MaxValue\": 84}}, \"5\": {{\"Value\": 418, \"MaxValue\": 418}}, \"11\": {{\"Value\": 50, \"MaxValue\": 50}}, \"12\": {{\"Value\": 50, \"MaxValue\": 50}}, \"13\": {{\"Value\": 50, \"MaxValue\": 50}}, \"14\": {{\"Value\": 50, \"MaxValue\": 50}}, \"15\": {{\"Value\": 50, \"MaxValue\": 50}}, \"23\": {{\"Value\": 31, \"MaxValue\": 31}}, \"24\": {{\"Value\": 37, \"MaxValue\": 37}}, \"32\": {{\"Value\": 30, \"MaxValue\": 30}}, \"34\": {{\"Value\": 2030, \"MaxValue\": 2030}}, \"35\": {{\"Value\": 2030, \"MaxValue\": 2030}}, \"36\": {{\"Value\": 2030, \"MaxValue\": 2030}}, \"37\": {{\"Value\": 2030, \"MaxValue\": 2030}}, \"40\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"41\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"42\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"44\": {{\"Value\": 1, \"MaxValue\": 1}}, \"46\": {{\"Value\": 20000, \"MaxValue\": 20000}}, \"54\": {{\"Value\": 1000, \"MaxValue\": 1000}}, \"68\": {{\"Value\": 99, \"MaxValue\": 99}}, \"74\": {{\"Value\": 349, \"MaxValue\": 349}}}}}}, \"10\": {{\"CharacterId\": 0, \"NpcId\": 92090, \"Type\": 4, \"Level\": 7, \"BuffIds\": [9009, 900007, 900050, 900055, 900011, 900051, 900072, 715531, 700053, 715075, 700007, 900080, 700028, 700045, 100062, 700030, 700029, 701022, 710076, 700027, 700215], \"AttrTable\": {{\"1\": {{\"Value\": 1, \"MaxValue\": 301}}, \"2\": {{\"Value\": 0, \"MaxValue\": 100}}, \"3\": {{\"Value\": 84, \"MaxValue\": 84}}, \"4\": {{\"Value\": 84, \"MaxValue\": 84}}, \"5\": {{\"Value\": 418, \"MaxValue\": 418}}, \"11\": {{\"Value\": 50, \"MaxValue\": 50}}, \"12\": {{\"Value\": 50, \"MaxValue\": 50}}, \"13\": {{\"Value\": 50, \"MaxValue\": 50}}, \"14\": {{\"Value\": 50, \"MaxValue\": 50}}, \"15\": {{\"Value\": 50, \"MaxValue\": 50}}, \"23\": {{\"Value\": 31, \"MaxValue\": 31}}, \"24\": {{\"Value\": 37, \"MaxValue\": 37}}, \"32\": {{\"Value\": 30, \"MaxValue\": 30}}, \"34\": {{\"Value\": 2030, \"MaxValue\": 2030}}, \"35\": {{\"Value\": 2030, \"MaxValue\": 2030}}, \"36\": {{\"Value\": 2030, \"MaxValue\": 2030}}, \"37\": {{\"Value\": 2030, \"MaxValue\": 2030}}, \"40\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"41\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"42\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"44\": {{\"Value\": 1, \"MaxValue\": 1}}, \"46\": {{\"Value\": 20000, \"MaxValue\": 20000}}, \"54\": {{\"Value\": 1000, \"MaxValue\": 1000}}, \"68\": {{\"Value\": 99, \"MaxValue\": 99}}, \"74\": {{\"Value\": 349, \"MaxValue\": 349}}}}}}, \"11\": {{\"CharacterId\": 0, \"NpcId\": 92090, \"Type\": 4, \"Level\": 7, \"BuffIds\": [9009, 900007, 900050, 900072, 900011, 900051, 700028, 715531, 700053, 715075, 700007, 900080, 100063, 100068, 700030, 700045, 700029, 701022, 710076, 700027, 700215], \"AttrTable\": {{\"1\": {{\"Value\": 1, \"MaxValue\": 301}}, \"2\": {{\"Value\": 0, \"MaxValue\": 100}}, \"3\": {{\"Value\": 84, \"MaxValue\": 84}}, \"4\": {{\"Value\": 84, \"MaxValue\": 84}}, \"5\": {{\"Value\": 418, \"MaxValue\": 418}}, \"11\": {{\"Value\": 50, \"MaxValue\": 50}}, \"12\": {{\"Value\": 50, \"MaxValue\": 50}}, \"13\": {{\"Value\": 50, \"MaxValue\": 50}}, \"14\": {{\"Value\": 50, \"MaxValue\": 50}}, \"15\": {{\"Value\": 50, \"MaxValue\": 50}}, \"23\": {{\"Value\": 31, \"MaxValue\": 31}}, \"24\": {{\"Value\": 37, \"MaxValue\": 37}}, \"32\": {{\"Value\": 30, \"MaxValue\": 30}}, \"34\": {{\"Value\": 2030, \"MaxValue\": 2030}}, \"35\": {{\"Value\": 2030, \"MaxValue\": 2030}}, \"36\": {{\"Value\": 2030, \"MaxValue\": 2030}}, \"37\": {{\"Value\": 2030, \"MaxValue\": 2030}}, \"40\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"41\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"42\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"44\": {{\"Value\": 1, \"MaxValue\": 1}}, \"46\": {{\"Value\": 20000, \"MaxValue\": 20000}}, \"54\": {{\"Value\": 1000, \"MaxValue\": 1000}}, \"68\": {{\"Value\": 99, \"MaxValue\": 99}}, \"74\": {{\"Value\": 349, \"MaxValue\": 349}}}}}}, \"12\": {{\"CharacterId\": 0, \"NpcId\": 91100, \"Type\": 4, \"Level\": 7, \"BuffIds\": [9010, 900007, 900050, 900055, 900011, 900051, 900082, 715531, 700053, 715075, 700007, 900080, 700030, 700029, 700045, 700028, 701022, 710076, 700027, 700215], \"AttrTable\": {{\"1\": {{\"Value\": 1, \"MaxValue\": 844}}, \"2\": {{\"Value\": 0, \"MaxValue\": 100}}, \"3\": {{\"Value\": 199, \"MaxValue\": 199}}, \"4\": {{\"Value\": 99, \"MaxValue\": 99}}, \"5\": {{\"Value\": 418, \"MaxValue\": 418}}, \"11\": {{\"Value\": 38, \"MaxValue\": 38}}, \"12\": {{\"Value\": 38, \"MaxValue\": 38}}, \"13\": {{\"Value\": 38, \"MaxValue\": 38}}, \"14\": {{\"Value\": 38, \"MaxValue\": 38}}, \"15\": {{\"Value\": 38, \"MaxValue\": 38}}, \"23\": {{\"Value\": 31, \"MaxValue\": 31}}, \"24\": {{\"Value\": 18, \"MaxValue\": 18}}, \"32\": {{\"Value\": 30, \"MaxValue\": 30}}, \"34\": {{\"Value\": 2030, \"MaxValue\": 2030}}, \"35\": {{\"Value\": 2030, \"MaxValue\": 2030}}, \"36\": {{\"Value\": 2030, \"MaxValue\": 2030}}, \"37\": {{\"Value\": 2030, \"MaxValue\": 2030}}, \"40\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"41\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"42\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"44\": {{\"Value\": 1, \"MaxValue\": 1}}, \"46\": {{\"Value\": 20000, \"MaxValue\": 20000}}, \"54\": {{\"Value\": 1000, \"MaxValue\": 1000}}, \"68\": {{\"Value\": 99, \"MaxValue\": 99}}, \"74\": {{\"Value\": 349, \"MaxValue\": 349}}}}}}, \"14\": {{\"CharacterId\": 0, \"NpcId\": 91090, \"Type\": 4, \"Level\": 7, \"BuffIds\": [9009, 900007, 900050, 900055, 900011, 900051, 900082, 715531, 700053, 715075, 700007, 900080, 100062, 100063, 100068, 700030, 700029, 700045, 700028, 701022, 710076, 700027, 700215], \"AttrTable\": {{\"1\": {{\"Value\": 1, \"MaxValue\": 751}}, \"2\": {{\"Value\": 0, \"MaxValue\": 100}}, \"3\": {{\"Value\": 84, \"MaxValue\": 84}}, \"4\": {{\"Value\": 84, \"MaxValue\": 84}}, \"5\": {{\"Value\": 418, \"MaxValue\": 418}}, \"11\": {{\"Value\": 50, \"MaxValue\": 50}}, \"12\": {{\"Value\": 50, \"MaxValue\": 50}}, \"13\": {{\"Value\": 50, \"MaxValue\": 50}}, \"14\": {{\"Value\": 50, \"MaxValue\": 50}}, \"15\": {{\"Value\": 50, \"MaxValue\": 50}}, \"23\": {{\"Value\": 31, \"MaxValue\": 31}}, \"24\": {{\"Value\": 37, \"MaxValue\": 37}}, \"32\": {{\"Value\": 30, \"MaxValue\": 30}}, \"34\": {{\"Value\": 2030, \"MaxValue\": 2030}}, \"35\": {{\"Value\": 2030, \"MaxValue\": 2030}}, \"36\": {{\"Value\": 2030, \"MaxValue\": 2030}}, \"37\": {{\"Value\": 2030, \"MaxValue\": 2030}}, \"40\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"41\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"42\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"44\": {{\"Value\": 1, \"MaxValue\": 1}}, \"46\": {{\"Value\": 20000, \"MaxValue\": 20000}}, \"54\": {{\"Value\": 1000, \"MaxValue\": 1000}}, \"68\": {{\"Value\": 99, \"MaxValue\": 99}}, \"74\": {{\"Value\": 349, \"MaxValue\": 349}}}}}}, \"13\": {{\"CharacterId\": 0, \"NpcId\": 91090, \"Type\": 4, \"Level\": 7, \"BuffIds\": [9009, 900007, 900050, 900082, 900011, 900051, 700030, 715531, 700053, 715075, 700007, 900080, 100063, 100068, 700029, 700045, 700028, 701022, 710076, 700027, 700215], \"AttrTable\": {{\"1\": {{\"Value\": 1, \"MaxValue\": 751}}, \"2\": {{\"Value\": 0, \"MaxValue\": 100}}, \"3\": {{\"Value\": 84, \"MaxValue\": 84}}, \"4\": {{\"Value\": 84, \"MaxValue\": 84}}, \"5\": {{\"Value\": 418, \"MaxValue\": 418}}, \"11\": {{\"Value\": 50, \"MaxValue\": 50}}, \"12\": {{\"Value\": 50, \"MaxValue\": 50}}, \"13\": {{\"Value\": 50, \"MaxValue\": 50}}, \"14\": {{\"Value\": 50, \"MaxValue\": 50}}, \"15\": {{\"Value\": 50, \"MaxValue\": 50}}, \"23\": {{\"Value\": 31, \"MaxValue\": 31}}, \"24\": {{\"Value\": 37, \"MaxValue\": 37}}, \"32\": {{\"Value\": 30, \"MaxValue\": 30}}, \"34\": {{\"Value\": 2030, \"MaxValue\": 2030}}, \"35\": {{\"Value\": 2030, \"MaxValue\": 2030}}, \"36\": {{\"Value\": 2030, \"MaxValue\": 2030}}, \"37\": {{\"Value\": 2030, \"MaxValue\": 2030}}, \"40\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"41\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"42\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"44\": {{\"Value\": 1, \"MaxValue\": 1}}, \"46\": {{\"Value\": 20000, \"MaxValue\": 20000}}, \"54\": {{\"Value\": 1000, \"MaxValue\": 1000}}, \"68\": {{\"Value\": 99, \"MaxValue\": 99}}, \"74\": {{\"Value\": 349, \"MaxValue\": 349}}}}}}, \"16\": {{\"CharacterId\": 0, \"NpcId\": 91120, \"Type\": 4, \"Level\": 7, \"BuffIds\": [9012, 900007, 900050, 700030, 900011, 900051, 700029, 715531, 700933, 715075, 700053, 700007, 900080, 700045, 700028, 701022, 710076, 700027, 700215, 700008, 900052], \"AttrTable\": {{\"1\": {{\"Value\": 1, \"MaxValue\": 751}}, \"2\": {{\"Value\": 0, \"MaxValue\": 100}}, \"3\": {{\"Value\": 99, \"MaxValue\": 99}}, \"4\": {{\"Value\": 99, \"MaxValue\": 99}}, \"5\": {{\"Value\": 418, \"MaxValue\": 418}}, \"11\": {{\"Value\": 50, \"MaxValue\": 50}}, \"12\": {{\"Value\": 50, \"MaxValue\": 50}}, \"13\": {{\"Value\": 50, \"MaxValue\": 50}}, \"14\": {{\"Value\": 50, \"MaxValue\": 50}}, \"15\": {{\"Value\": 50, \"MaxValue\": 50}}, \"23\": {{\"Value\": 31, \"MaxValue\": 31}}, \"24\": {{\"Value\": 37, \"MaxValue\": 37}}, \"32\": {{\"Value\": 30, \"MaxValue\": 30}}, \"34\": {{\"Value\": 2030, \"MaxValue\": 2030}}, \"35\": {{\"Value\": 2030, \"MaxValue\": 2030}}, \"36\": {{\"Value\": 2030, \"MaxValue\": 2030}}, \"37\": {{\"Value\": 2030, \"MaxValue\": 2030}}, \"40\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"41\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"42\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"44\": {{\"Value\": 1, \"MaxValue\": 1}}, \"46\": {{\"Value\": 20000, \"MaxValue\": 20000}}, \"54\": {{\"Value\": 1000, \"MaxValue\": 1000}}, \"68\": {{\"Value\": 99, \"MaxValue\": 99}}, \"74\": {{\"Value\": 349, \"MaxValue\": 349}}}}}}, \"15\": {{\"CharacterId\": 0, \"NpcId\": 91120, \"Type\": 4, \"Level\": 7, \"BuffIds\": [9012, 900007, 900050, 900055, 900011, 900051, 900082, 715531, 700030, 715075, 700053, 700007, 900080, 700029, 700045, 700028, 701022, 710076, 700027, 700215], \"AttrTable\": {{\"1\": {{\"Value\": 1, \"MaxValue\": 751}}, \"2\": {{\"Value\": 0, \"MaxValue\": 100}}, \"3\": {{\"Value\": 99, \"MaxValue\": 99}}, \"4\": {{\"Value\": 99, \"MaxValue\": 99}}, \"5\": {{\"Value\": 418, \"MaxValue\": 418}}, \"11\": {{\"Value\": 50, \"MaxValue\": 50}}, \"12\": {{\"Value\": 50, \"MaxValue\": 50}}, \"13\": {{\"Value\": 50, \"MaxValue\": 50}}, \"14\": {{\"Value\": 50, \"MaxValue\": 50}}, \"15\": {{\"Value\": 50, \"MaxValue\": 50}}, \"23\": {{\"Value\": 31, \"MaxValue\": 31}}, \"24\": {{\"Value\": 37, \"MaxValue\": 37}}, \"32\": {{\"Value\": 30, \"MaxValue\": 30}}, \"34\": {{\"Value\": 2030, \"MaxValue\": 2030}}, \"35\": {{\"Value\": 2030, \"MaxValue\": 2030}}, \"36\": {{\"Value\": 2030, \"MaxValue\": 2030}}, \"37\": {{\"Value\": 2030, \"MaxValue\": 2030}}, \"40\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"41\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"42\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"44\": {{\"Value\": 1, \"MaxValue\": 1}}, \"46\": {{\"Value\": 20000, \"MaxValue\": 20000}}, \"54\": {{\"Value\": 1000, \"MaxValue\": 1000}}, \"68\": {{\"Value\": 99, \"MaxValue\": 99}}, \"74\": {{\"Value\": 349, \"MaxValue\": 349}}}}}}, \"1\": {{\"CharacterId\": 1021001, \"NpcId\": 10210012, \"Type\": 1, \"Level\": 50, \"BuffIds\": [100054, 1002, 100050, 100051, 100074, 100085, 100201, 715587, 100219, 100243, 502101, 620701, 620705, 620801, 100055, 100056, 100057, 100058, 900081, 199931, 100052, 100053, 100204, 100294, 100295, 100296, 100297, 100001, 105535, 410011, 410012, 731103, 100016, 100007, 100093, 100091, 100000, 100021, 100076], \"AttrTable\": {{\"1\": {{\"Value\": 5211, \"MaxValue\": 5211}}, \"2\": {{\"Value\": 42, \"MaxValue\": 120}}, \"3\": {{\"Value\": 249, \"MaxValue\": 249}}, \"4\": {{\"Value\": 249, \"MaxValue\": 249}}, \"5\": {{\"Value\": 610, \"MaxValue\": 610}}, \"6\": {{\"Value\": 20019980, \"MaxValue\": 20019980}}, \"11\": {{\"Value\": 1076, \"MaxValue\": 1076}}, \"12\": {{\"Value\": 1076, \"MaxValue\": 1076}}, \"13\": {{\"Value\": 1076, \"MaxValue\": 1076}}, \"14\": {{\"Value\": 1076, \"MaxValue\": 1076}}, \"15\": {{\"Value\": 1076, \"MaxValue\": 1076}}, \"23\": {{\"Value\": 676, \"MaxValue\": 676}}, \"25\": {{\"Value\": 1000, \"MaxValue\": 1000}}, \"40\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"41\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"42\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"44\": {{\"Value\": 527, \"MaxValue\": 527}}, \"46\": {{\"Value\": 20000, \"MaxValue\": 20000}}, \"54\": {{\"Value\": 1000, \"MaxValue\": 1000}}, \"55\": {{\"Value\": 0, \"MaxValue\": 1000}}, \"56\": {{\"Value\": -96, \"MaxValue\": -96}}, \"57\": {{\"Value\": 0, \"MaxValue\": 100}}, \"68\": {{\"Value\": 199, \"MaxValue\": 199}}, \"74\": {{\"Value\": 699, \"MaxValue\": 699}}}}}}, \"2\": {{\"CharacterId\": 1031003, \"NpcId\": 10310033, \"Type\": 1, \"Level\": 45, \"BuffIds\": [100054, 102389, 1023, 100050, 100051, 100074, 100088, 102339, 102340, 102348, 410011, 503101, 620201, 620202, 620217, 620301, 620302, 620304, 620307, 100055, 100056, 100057, 100058, 199931, 100052, 100053, 105535, 410012], \"AttrTable\": {{\"1\": {{\"Value\": 2271, \"MaxValue\": 2271}}, \"2\": {{\"Value\": 0, \"MaxValue\": 120}}, \"3\": {{\"Value\": 249, \"MaxValue\": 249}}, \"4\": {{\"Value\": 249, \"MaxValue\": 249}}, \"5\": {{\"Value\": 610, \"MaxValue\": 610}}, \"6\": {{\"Value\": 20019980, \"MaxValue\": 20019980}}, \"11\": {{\"Value\": 470, \"MaxValue\": 470}}, \"12\": {{\"Value\": 470, \"MaxValue\": 470}}, \"13\": {{\"Value\": 470, \"MaxValue\": 470}}, \"14\": {{\"Value\": 470, \"MaxValue\": 470}}, \"15\": {{\"Value\": 470, \"MaxValue\": 470}}, \"23\": {{\"Value\": 302, \"MaxValue\": 302}}, \"40\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"41\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"42\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"44\": {{\"Value\": 263, \"MaxValue\": 263}}, \"46\": {{\"Value\": 20000, \"MaxValue\": 20000}}, \"51\": {{\"Value\": 2471, \"MaxValue\": 2471}}, \"54\": {{\"Value\": 1000, \"MaxValue\": 1000}}, \"55\": {{\"Value\": 800, \"MaxValue\": 800}}, \"56\": {{\"Value\": 4, \"MaxValue\": 4}}, \"57\": {{\"Value\": 0, \"MaxValue\": 4}}, \"68\": {{\"Value\": 199, \"MaxValue\": 199}}, \"74\": {{\"Value\": 699, \"MaxValue\": 699}}}}}}, \"3\": {{\"CharacterId\": 1051001, \"NpcId\": 10510012, \"Type\": 1, \"Level\": 45, \"BuffIds\": [100054, 1005, 100050, 100051, 100074, 100086, 100541, 410011, 505101, 620401, 620413, 620501, 620503, 620506, 100055, 100056, 100057, 100058, 199931, 100052, 100053, 105535, 410012], \"AttrTable\": {{\"1\": {{\"Value\": 2678, \"MaxValue\": 2678}}, \"2\": {{\"Value\": 0, \"MaxValue\": 120}}, \"3\": {{\"Value\": 249, \"MaxValue\": 249}}, \"4\": {{\"Value\": 249, \"MaxValue\": 249}}, \"5\": {{\"Value\": 610, \"MaxValue\": 610}}, \"6\": {{\"Value\": 20019980, \"MaxValue\": 20019980}}, \"11\": {{\"Value\": 544, \"MaxValue\": 544}}, \"12\": {{\"Value\": 544, \"MaxValue\": 544}}, \"13\": {{\"Value\": 544, \"MaxValue\": 544}}, \"14\": {{\"Value\": 544, \"MaxValue\": 544}}, \"15\": {{\"Value\": 544, \"MaxValue\": 544}}, \"23\": {{\"Value\": 303, \"MaxValue\": 303}}, \"40\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"41\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"42\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"44\": {{\"Value\": 314, \"MaxValue\": 314}}, \"46\": {{\"Value\": 20000, \"MaxValue\": 20000}}, \"54\": {{\"Value\": 7500, \"MaxValue\": 7500}}, \"55\": {{\"Value\": 1000, \"MaxValue\": 1000}}, \"56\": {{\"Value\": 4, \"MaxValue\": 4}}, \"57\": {{\"Value\": 0, \"MaxValue\": 100}}, \"68\": {{\"Value\": 199, \"MaxValue\": 199}}, \"74\": {{\"Value\": 699, \"MaxValue\": 699}}}}}}, \"4\": {{\"CharacterId\": 0, \"NpcId\": 2006, \"Type\": 5, \"Level\": 99999, \"BuffIds\": [900064, 900065, 900056, 905068, 710193, 710195, 715587, 710301, 700230, 700007, 701022, 710076, 700017, 715707, 715678, 700501, 700053], \"AttrTable\": {{\"1\": {{\"Value\": 499990010, \"MaxValue\": 499990010}}, \"2\": {{\"Value\": 0, \"MaxValue\": 500}}, \"3\": {{\"Value\": 249, \"MaxValue\": 249}}, \"4\": {{\"Value\": 249, \"MaxValue\": 249}}, \"5\": {{\"Value\": 209, \"MaxValue\": 209}}, \"6\": {{\"Value\": 19999980, \"MaxValue\": 19999980}}, \"11\": {{\"Value\": 15, \"MaxValue\": 15}}, \"12\": {{\"Value\": 499990, \"MaxValue\": 499990}}, \"13\": {{\"Value\": 499990, \"MaxValue\": 499990}}, \"14\": {{\"Value\": 499990, \"MaxValue\": 499990}}, \"15\": {{\"Value\": 499990, \"MaxValue\": 499990}}, \"24\": {{\"Value\": 249994, \"MaxValue\": 249994}}, \"25\": {{\"Value\": 149996, \"MaxValue\": 149996}}, \"34\": {{\"Value\": 2000, \"MaxValue\": 2000}}, \"35\": {{\"Value\": 2000, \"MaxValue\": 2000}}, \"36\": {{\"Value\": 2000, \"MaxValue\": 2000}}, \"37\": {{\"Value\": 2000, \"MaxValue\": 2000}}, \"40\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"41\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"42\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"44\": {{\"Value\": 249994, \"MaxValue\": 249994}}, \"53\": {{\"Value\": 3300034, \"MaxValue\": 3300034}}, \"54\": {{\"Value\": -19000, \"MaxValue\": -19000}}, \"55\": {{\"Value\": 1000, \"MaxValue\": 1000}}, \"56\": {{\"Value\": 4, \"MaxValue\": 4}}, \"57\": {{\"Value\": 0, \"MaxValue\": 100}}, \"68\": {{\"Value\": 99, \"MaxValue\": 99}}, \"74\": {{\"Value\": 349, \"MaxValue\": 349}}, \"75\": {{\"Value\": 0, \"MaxValue\": 100}}, \"76\": {{\"Value\": 0, \"MaxValue\": 100}}, \"77\": {{\"Value\": 0, \"MaxValue\": 100}}, \"78\": {{\"Value\": 0, \"MaxValue\": 100}}}}}}, \"5\": {{\"CharacterId\": 0, \"NpcId\": 2006, \"Type\": 5, \"Level\": 21, \"BuffIds\": [900064, 900065, 900056, 905068, 710193, 710195], \"AttrTable\": {{\"1\": {{\"Value\": 100010, \"MaxValue\": 100010}}, \"2\": {{\"Value\": 0, \"MaxValue\": 500}}, \"3\": {{\"Value\": 249, \"MaxValue\": 249}}, \"4\": {{\"Value\": 249, \"MaxValue\": 249}}, \"5\": {{\"Value\": 209, \"MaxValue\": 209}}, \"6\": {{\"Value\": 19999980, \"MaxValue\": 19999980}}, \"11\": {{\"Value\": 15, \"MaxValue\": 15}}, \"12\": {{\"Value\": 100, \"MaxValue\": 100}}, \"13\": {{\"Value\": 100, \"MaxValue\": 100}}, \"14\": {{\"Value\": 100, \"MaxValue\": 100}}, \"15\": {{\"Value\": 100, \"MaxValue\": 100}}, \"24\": {{\"Value\": 49, \"MaxValue\": 49}}, \"25\": {{\"Value\": 29, \"MaxValue\": 29}}, \"34\": {{\"Value\": 2000, \"MaxValue\": 2000}}, \"35\": {{\"Value\": 2000, \"MaxValue\": 2000}}, \"36\": {{\"Value\": 2000, \"MaxValue\": 2000}}, \"37\": {{\"Value\": 2000, \"MaxValue\": 2000}}, \"40\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"41\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"42\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"44\": {{\"Value\": 49, \"MaxValue\": 49}}, \"53\": {{\"Value\": 760, \"MaxValue\": 760}}, \"54\": {{\"Value\": 1000, \"MaxValue\": 1000}}, \"55\": {{\"Value\": 1000, \"MaxValue\": 1000}}, \"56\": {{\"Value\": 4, \"MaxValue\": 4}}, \"57\": {{\"Value\": 0, \"MaxValue\": 100}}, \"68\": {{\"Value\": 99, \"MaxValue\": 99}}, \"74\": {{\"Value\": 349, \"MaxValue\": 349}}, \"75\": {{\"Value\": 0, \"MaxValue\": 100}}, \"76\": {{\"Value\": 0, \"MaxValue\": 100}}, \"77\": {{\"Value\": 0, \"MaxValue\": 100}}, \"78\": {{\"Value\": 0, \"MaxValue\": 100}}}}}}, \"6\": {{\"CharacterId\": 0, \"NpcId\": 2006, \"Type\": 5, \"Level\": 1, \"BuffIds\": [900064, 900065, 900056, 905068, 710193, 710195], \"AttrTable\": {{\"1\": {{\"Value\": 10, \"MaxValue\": 10}}, \"2\": {{\"Value\": 0, \"MaxValue\": 500}}, \"3\": {{\"Value\": 249, \"MaxValue\": 249}}, \"4\": {{\"Value\": 249, \"MaxValue\": 249}}, \"5\": {{\"Value\": 209, \"MaxValue\": 209}}, \"6\": {{\"Value\": 19999980, \"MaxValue\": 19999980}}, \"11\": {{\"Value\": 15, \"MaxValue\": 15}}, \"34\": {{\"Value\": 2000, \"MaxValue\": 2000}}, \"35\": {{\"Value\": 2000, \"MaxValue\": 2000}}, \"36\": {{\"Value\": 2000, \"MaxValue\": 2000}}, \"37\": {{\"Value\": 2000, \"MaxValue\": 2000}}, \"40\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"41\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"42\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"53\": {{\"Value\": 100, \"MaxValue\": 100}}, \"54\": {{\"Value\": 1000, \"MaxValue\": 1000}}, \"55\": {{\"Value\": 1000, \"MaxValue\": 1000}}, \"56\": {{\"Value\": 4, \"MaxValue\": 4}}, \"57\": {{\"Value\": 0, \"MaxValue\": 100}}, \"68\": {{\"Value\": 99, \"MaxValue\": 99}}, \"74\": {{\"Value\": 349, \"MaxValue\": 349}}, \"75\": {{\"Value\": 0, \"MaxValue\": 100}}, \"76\": {{\"Value\": 0, \"MaxValue\": 100}}, \"77\": {{\"Value\": 0, \"MaxValue\": 100}}, \"78\": {{\"Value\": 0, \"MaxValue\": 100}}}}}}, \"7\": {{\"CharacterId\": 0, \"NpcId\": 2006, \"Type\": 5, \"Level\": 1, \"BuffIds\": [900064, 900065, 900056, 905068, 710193, 710195, 709001], \"AttrTable\": {{\"1\": {{\"Value\": 10, \"MaxValue\": 10}}, \"2\": {{\"Value\": 0, \"MaxValue\": 500}}, \"3\": {{\"Value\": 249, \"MaxValue\": 249}}, \"4\": {{\"Value\": 249, \"MaxValue\": 249}}, \"5\": {{\"Value\": 209, \"MaxValue\": 209}}, \"6\": {{\"Value\": 19999980, \"MaxValue\": 19999980}}, \"11\": {{\"Value\": 15, \"MaxValue\": 15}}, \"34\": {{\"Value\": 2000, \"MaxValue\": 2000}}, \"35\": {{\"Value\": 2000, \"MaxValue\": 2000}}, \"36\": {{\"Value\": 2000, \"MaxValue\": 2000}}, \"37\": {{\"Value\": 2000, \"MaxValue\": 2000}}, \"40\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"41\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"42\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"53\": {{\"Value\": 100, \"MaxValue\": 100}}, \"54\": {{\"Value\": 1000, \"MaxValue\": 1000}}, \"55\": {{\"Value\": 1000, \"MaxValue\": 1000}}, \"56\": {{\"Value\": 4, \"MaxValue\": 4}}, \"57\": {{\"Value\": 0, \"MaxValue\": 100}}, \"68\": {{\"Value\": 99, \"MaxValue\": 99}}, \"74\": {{\"Value\": 349, \"MaxValue\": 349}}, \"75\": {{\"Value\": 0, \"MaxValue\": 100}}, \"76\": {{\"Value\": 0, \"MaxValue\": 100}}, \"77\": {{\"Value\": 0, \"MaxValue\": 100}}, \"78\": {{\"Value\": 0, \"MaxValue\": 100}}}}}}, \"8\": {{\"CharacterId\": 0, \"NpcId\": 2006, \"Type\": 5, \"Level\": 1, \"BuffIds\": [900064, 900065, 900056, 905068, 710193, 710195, 709003], \"AttrTable\": {{\"1\": {{\"Value\": 10, \"MaxValue\": 10}}, \"2\": {{\"Value\": 0, \"MaxValue\": 500}}, \"3\": {{\"Value\": 249, \"MaxValue\": 249}}, \"4\": {{\"Value\": 249, \"MaxValue\": 249}}, \"5\": {{\"Value\": 209, \"MaxValue\": 209}}, \"6\": {{\"Value\": 19999980, \"MaxValue\": 19999980}}, \"11\": {{\"Value\": 15, \"MaxValue\": 15}}, \"34\": {{\"Value\": 2000, \"MaxValue\": 2000}}, \"35\": {{\"Value\": 2000, \"MaxValue\": 2000}}, \"36\": {{\"Value\": 2000, \"MaxValue\": 2000}}, \"37\": {{\"Value\": 2000, \"MaxValue\": 2000}}, \"40\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"41\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"42\": {{\"Value\": 10000, \"MaxValue\": 10000}}, \"53\": {{\"Value\": 100, \"MaxValue\": 100}}, \"54\": {{\"Value\": 1000, \"MaxValue\": 1000}}, \"55\": {{\"Value\": 1000, \"MaxValue\": 1000}}, \"56\": {{\"Value\": 4, \"MaxValue\": 4}}, \"57\": {{\"Value\": 0, \"MaxValue\": 100}}, \"68\": {{\"Value\": 99, \"MaxValue\": 99}}, \"74\": {{\"Value\": 349, \"MaxValue\": 349}}, \"75\": {{\"Value\": 0, \"MaxValue\": 100}}, \"76\": {{\"Value\": 0, \"MaxValue\": 100}}, \"77\": {{\"Value\": 0, \"MaxValue\": 100}}, \"78\": {{\"Value\": 0, \"MaxValue\": 100}}}}}}}}, \"UrgentEnventId\": 0, \"ClientAssistInfo\": null, \"FlopRewardList\": [], \"ArenaResult\": null, \"MultiRewardGoodsList\": [], \"ChallengeCount\": 0, \"UnionKillResult\": null, \"InfestorBossFightResult\": null, \"GuildBossFightResult\": null, \"WorldBossFightResult\": null, \"BossSingleFightResult\": null, \"NieRBossFightResult\": null, \"TRPGBossFightResult\": null, \"ExpeditionFightResult\": null, \"ChessPursuitResult\": [], \"StrongholdFightResult\": null, \"AreaWarFightResult\": null, \"GuildWarFightResult\": null, \"ReformFightResult\": null, \"KillZoneStageResult\": null, \"EpisodeFightResult\": {{}}, \"StTargetStageFightResult\": null, \"StMapTierDataOperation\": null, \"SimulateTrainFightResult\": null, \"SuperSmashBrosBattleResult\": null, \"SpecialTrainRankFightResult\": null, \"DoubleTowerFightResult\": null, \"TaikoMasterSettleResult\": null, \"MultiDimFightResult\": null, \"MoewarParkourSettleResult\": null, \"SpecialTrainBreakthroughResult\": null}}}}")), packet.Id); } } diff --git a/AscNet.GameServer/Packet.cs b/AscNet.GameServer/Packet.cs index d087787..2716efc 100644 --- a/AscNet.GameServer/Packet.cs +++ b/AscNet.GameServer/Packet.cs @@ -120,7 +120,7 @@ namespace AscNet.GameServer #endif } - log.Info("Finished Loading Packet Handlers"); + log.Info("Finished loading packet handlers"); } public static RequestPacketHandlerDelegate? GetRequestPacketHandler(string name) diff --git a/AscNet.GameServer/Server.cs b/AscNet.GameServer/Server.cs index a5d2999..61d9ac5 100644 --- a/AscNet.GameServer/Server.cs +++ b/AscNet.GameServer/Server.cs @@ -19,12 +19,16 @@ namespace AscNet.GameServer } } - public Server() + static Server() { // TODO: add loglevel based on appsettings LogLevel logLevel = LogLevel.DEBUG; LogLevel fileLogLevel = LogLevel.DEBUG; log = new(typeof(Server), logLevel, fileLogLevel); + } + + public Server() + { listener = new(IPAddress.Parse("0.0.0.0"), Common.Common.config.GameServer.Port); } @@ -54,5 +58,10 @@ namespace AscNet.GameServer } } } + + public Session? SessionFromUID(long uid) + { + return Sessions.FirstOrDefault(x => x.Value.player.PlayerData.Id == uid).Value; + } } } \ No newline at end of file diff --git a/AscNet.SDKServer/AscNet.SDKServer.csproj b/AscNet.SDKServer/AscNet.SDKServer.csproj index a3754a8..35b5773 100644 --- a/AscNet.SDKServer/AscNet.SDKServer.csproj +++ b/AscNet.SDKServer/AscNet.SDKServer.csproj @@ -13,6 +13,7 @@ + diff --git a/AscNet.SDKServer/Controllers/CommandController.cs b/AscNet.SDKServer/Controllers/CommandController.cs new file mode 100644 index 0000000..5c61d50 --- /dev/null +++ b/AscNet.SDKServer/Controllers/CommandController.cs @@ -0,0 +1,69 @@ +using AscNet.Common.Database; +using AscNet.GameServer; +using AscNet.GameServer.Commands; +using AscNet.SDKServer.Models ; +using Microsoft.AspNetCore.Mvc; +using Newtonsoft.Json; + +namespace AscNet.SDKServer.Controllers +{ + public class CommandController : IRegisterable + { + public static void Register(WebApplication app) + { + app.MapGet("/api/AscNet/commands", (HttpContext ctx) => + { + List commands = new(); + + foreach (var command in CommandFactory.commands.Keys) + { + Command? cmd = CommandFactory.CreateCommand(command, null!, Array.Empty(), false); + if (cmd is not null) + commands.Add(new + { + name = command, + help = cmd.Help + }); + } + + return ctx.Response.WriteAsync(JsonConvert.SerializeObject(new { code = 0, msg = "OK", data = commands })); + }); + + app.MapPost("/api/AscNet/command/{command}", ([FromHeader] string authorization, [FromBody] ExecuteCommandBody body, string command, HttpContext ctx) => + { + Player? player = Player.FromToken(authorization); + if (player is null) + { + ctx.Response.StatusCode = 401; + return ctx.Response.WriteAsync(JsonConvert.SerializeObject(new { msg = "Invalid token!" })); + } + + Session? session = Server.Instance.SessionFromUID(player.PlayerData.Id); + if (session is null) + { + ctx.Response.StatusCode = 400; + return ctx.Response.WriteAsync(JsonConvert.SerializeObject(new { msg = "Player is offline!" })); + } + + try + { + Command? cmd = CommandFactory.CreateCommand(command, session, body.Args); + if (cmd is null) + { + ctx.Response.StatusCode = 404; + return ctx.Response.WriteAsync(JsonConvert.SerializeObject(new { msg = "Command does not exists!" })); + } + + cmd.Execute(); + } + catch (Exception ex) + { + ctx.Response.StatusCode = 400; + return ctx.Response.WriteAsync(JsonConvert.SerializeObject(new { msg = "Execution error!", err = ex.InnerException?.Message ?? ex.Message })); + } + + return ctx.Response.WriteAsync(JsonConvert.SerializeObject(new { msg = "OK" })); + }); + } + } +} diff --git a/AscNet.SDKServer/Models/CommandApi.cs b/AscNet.SDKServer/Models/CommandApi.cs new file mode 100644 index 0000000..6ea0ee9 --- /dev/null +++ b/AscNet.SDKServer/Models/CommandApi.cs @@ -0,0 +1,11 @@ +using Newtonsoft.Json; + +namespace AscNet.SDKServer.Models +{ +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + public class ExecuteCommandBody + { + [JsonProperty("args", NullValueHandling = NullValueHandling.Ignore)] + public string[] Args { get; set; } + } +} diff --git a/AscNet/Program.cs b/AscNet/Program.cs index ff6bc69..be3b788 100644 --- a/AscNet/Program.cs +++ b/AscNet/Program.cs @@ -1,7 +1,6 @@ -using AscNet.Common.Util; -using AscNet.GameServer; +using AscNet.GameServer; +using AscNet.GameServer.Commands; using AscNet.Logging; -using Newtonsoft.Json; namespace AscNet { @@ -9,20 +8,18 @@ namespace AscNet { static void Main(string[] args) { - // TODO: Add loglevel parsing from appsettings file + // TODO: Add LogLevel parsing from appsettings file LoggerFactory.InitializeLogger(new Logger(typeof(Program), LogLevel.DEBUG, LogLevel.DEBUG)); LoggerFactory.Logger.Info("Starting..."); - /*byte[] encryptedTest = Miscs.HexStringToByteArray("9020fb38a6adbaaf1555aeaf1fc30e6fda2dec7b6e36607f665165121469ea921f0b5fe44a3e2ae9dbb22c63742f515cfa49804d4bc6ef6375665fdf7bd556fb8965d31dd531b684350fcc098406371cc366aa1a32bde1e31a62a495b938ab426104bc2bede03e1abdf2df300052e9f8effd3c86167f8cc2c1bba7eacd378d2779b6780310b32d5273efbe1dbc47814588f069ac99a43ab8c3239784d3b6f9e3f059acc9ce06024eb4dce4b7bfb1924b45e67e54a62cef878a61201c178f5c84c4ba2a36b3127dc37b7aa1f2b3e73145c332fd6379531844f75cd5c8eb01779eac6ec2f9de5ca0776abe882662078e88b2595c5636e8f8d7ae075f42516805d787fdab29fa602d8802107e739e8dfef0ce07677a1c0a030fb7cc8c561161bb14284cc77a742398c2a2ef18379d5691d6f94ec6e15cd8d8860ad159de442c9b19918bbd7a858c86a90f0d9cf523f75ee53fcf05fa655b7fbeb0a5a22b733815bd22e0adbb3011460b5c777fe96be6ab243162316c7c060fcf909cd02b9a3a00d794d52a4de959e751498f538635e0d4abec6d56e07afa6ac0d6c497a228ef5aab4d24c3cbe5f60c41e859be350433e73bd2f1ae8b3d824b553b8872c79ba85a1b6f57457e842ec9b581940da0e4947577819696a484cb2f0651012bed1b03fe0ce7cc4cc1340287f0e107a716ef7cf34f4222ad326359addfdeb8ab0f983d6d89cfbe036050437009289da1d0b840b3dbe655f95b6a1c561e950db1cf71b93c0f3499da3b381b0624d6ab3b5b91839834e22a884406c24caf47cf495152df40ca6602d588eea87dbe4d5544ad8fa0408939b6a536ba7af5ae8d3359856035c043358bb578e65cebb98a43e60114ad77a9cba0a70716b0da1dc67825f042733a7a382c971766c02b9a1f1cb565ca285197263807a25d102a604f74e6b9cc4adea0790dab0f46364a7e331b76573fde8a41454c55356acff4a2bbab133ed0b56e57bd3edc996de0b8578703005ca722d70d7516612388f0d75c8e48a7a37803cd99360be3da7da7fcd1c8bb2b9ba97e6aab32a81dd291ecdd4efcfc0dd6a11f2944f3d2f9faa6babc65175da91cdfd6afc0d8034ebf39b42f458c032ef3ae709f26098889427917bb099dfff0f930abf5202ca08d596103dc908c62776604fa643fd0499483ae605c6588b79e30cde719312a0d039cb6fdb4ba3a33b34ee37ce37288da6384d1fcd8b0c4a9aaebfeb497d6f7d75c776b0f14f3b0ee5eeefec0f22aae3829f31778f26e80a785cfec3351ec01e0da809146eb75c662ab6179a20f6a8d549a25170634ead19cfc00d3a2259f386156884b5d669f49b6eb63bf37232d8694fdd4cc7d3e1ff93e16634f05a54ff04f6c784dfb9e9b4b58b02e1ac6bfbab043a51eeabc6e90f41fdd76fdddffd1921d781ce5bf96cc78f1093c3a6301b7e2b43fa8cdec6fc33af403dab6853569e22777ad2896071c46aff09afd4f8cb5b43e5875228909fe02ef08eb9d970e316fb7c8fb255dec8d57bc94575ec183e51ceaa8b8f2a4bcfeaceb0d135155e86b536c7f69c225ba639f86d0d921d01cf7c4b0375880a72d6681fc01f55d872c31b3095989d5df45160d5d6679aedc579901bec0bd333506d2aec1eb5459aac910dc80f9648ee8f9642f3e31c9db3ddb4efeefea8e94f31b8082ea5c06a286706981633e4b9480911f5de8fa650f880b3f4626a351edaf1240e74555735128cb6de807a71da7cfb6d5f981a6e358072c2dbf252d7d537e5f28d92203c4e96d2b7ffcca14708ea512a3ed5561532be30d7dcd21445004108af561f26cd5700242d3637563b75f6cd013229f7f000803b52f955e9317feacb547dcc02e98620a99de2056a85f87e087c134f94ce6df3dbe6d72e24ca99921fd6510e105a27d2ebe4e0fcd168f2b798321ebd6c75a1d7f66cef3aee05428370279058935dc1d597d8618cdb08f52f50f662dfaee02dc22a6dd0bfa44c4aa0c8234d5057d8bcb00e6d7938c1804563a38daa15264adbe65faf7631f1eac773ccc147b186fbc1374c9f09d339ade16af225b084842a885c1c8a974aeb80ff837dcfdf3f8bc763ee09b5f9f65be9874e65fbae3bd27c6fa34dd015ed2e2ba660ba69dde0babd1cdfbcae998cbd5c0ffe58b178d4907ddd66710f1c901c58a0d49897cb3545dfe1018aa6ad2e13d3b511ea7d843712528b56d31cfa2a2333a38b110a4a65d0c3d0efefcd7c5997748c6267dabfc55d607b9d1145e32a2d80750d39e880e58731c0838d5208fed5375d736f011aca45e4a9d442c9c2705bcf8a6aef5bad027262df7970b6ad38b50886a76ece951c43ebde9ffde106e0cb9d66860cb87c8e797f0565418b6a77a332b1ff1d9392bdc4dfe0fd34a2d2d17bae6054043e24c17d343e87044997f57c40ab17429553f30a7f0578c1fdc50d8ee35b7ae0381a8a45b30576fa2a0c3e0b6b9e5ae3431e1f4c5948d4aeb74a2bbfa357057721f62f4422f55d3f4f5575e2d724bcde74ccc3e3e5f2a2cb1a2dc48e05ea78aedca7a3afa4f949cfde5efa4636101e6e40bdf06ca9cc5bb36971660eca6017cf09087fbdfd0d2ab9ca5cbfdb7ba2f57c434a393661d443e2f5d77c2033c30b741bc6c74ebe85ae1043ebc8230b378025ce317dfe62ea8e18735e74bc7c203bb9cba2549e9532fdea53d52465fca53cd271c2b98379c19cd0ffd7bd08006d0b1e5b9ce0866e3ee179f98820c98a43a6b86cd654be2f479bf20b54db1b41cdbbcfcfa12af73a8069f7c6ec3242df4ed679e7716a4828afe667dfb77aa73d1ccfadb8452511f559ed8af51772486890cb0adb53a8d9699b32ce832a2e8d79664e64c7311a960867e2d28674e08e067f2934f4a97a67c4d66f73a3c3a9e7082e36fd1e91833b5f18df0d23152c33211194005af2e381cfc373099628d1dd66b8c28e4a939ab2213c75c2c8f3560337cd9b150fcd9629171699db047e9cb0c14e8f05f26d59d98633e0b4ec69318ad6d4a3125fd306c542b5d84efaa4146442f7b343ac6bcff576a14b784bb65732e32bb6a329050a89bfd04f9cbd3558df21d9cfbeffcbdc7d4d45ef9aaa35125452b3cc887ee33372d00225521a9b48c26b9f9f9af6cc4f283bd53fc5808f0b65985309a825980bf0f9302a8439d4633d438672745a43077e77f70095846f7913b471090e60d5fdf94f2dcc81d6046c10c587d7a04bd335c287037183595826de8a333b5c6d6a205c70bf65660bf767f4d03120d394956617c79d551706ccd18ba687963ab552873a4257a3dd5697b1a0b9bf33ca290244a6dd28381b1e438936b7a0197107b067b8c2f0b9285e09fc170e200bd50dfb5d4ac9add854e4e0f3764190338106d373c280ba23b2dd0d044a7e513fb14e6ecf643c617639f1cb37cf2f83c229358e43c071ebc27835b054ba2c2b445d80ef394df5ba2d7ff31c0de2c80a598e3d4f1048829d299ca0ec7dfb18d1e3c91cece64030f8a71a1ce91410b9f0f2d7f76f6a682a1ac93024f387e8e3b878ca3a8008c4e75cbc459da12338bdeeddeed9845f0d59378616dd13137cb466da0d1b5539d34e1a5c171306f31ea1fc9e71710904cc84b8b834c578c312e68289d19a4366c5d9f417f46f4683d8e4201a4338eaa348a4e8bd30df2b7d6c218ae3a8c46323555f8a29bd88965dccfe8cda2df630136c3e6d34093a5192563def140ea78b9ea6cb06f6105501c79184808068683db4bf2a16e7de71ec9166d03c6eb32d71c522fa6db8761a2b5a83f1b5fe91def4a2223bb484b9c550da2a4886f0a3bcbd9953c4a942d98b64fe570bceafa3788079d582b029676be89ce97f908989bcef05deaa11626cfc173dd254ee06605afccd92133e9fbab41cd05662c23019ea28c7bacdee557b7a260d44db3f19b6571251713c1031acf3432715e02889d84cff670192c460c51bd843776fe533bdca12161bad003a49b97f8807f3e127333832cc6a78bdc58c8dc3d3a89e6edc3ab61559f1d8dc33d4efb64ef95d176569981109342609f64064d6fad58c2ef5fc71426a4691e86784416334266bd77072fe6db0561fa6e1bd60edcab3505d3789fd6436b7a86cb7ba65bc1814ef4914e336970ab167ed0e36fa55fe93701acfa778c63a474ab6a99ec8ea303baca2ab97eb6860cf0a1ccc473bcfe3ec23a6cb191534366717d42f4eacf230b8ec9d0455fb82289df3b9834e872e6a46bacb9322fd51b8843095324b9829353205da9a592456a16c3117824984fec4ced66616534e061c9ff213b30f150e11f51eeafed9dac8420e1c0a2b34ffdafc408c32b44df43ea6973ba1c2c4b46c83416d1c08dae422fcd548f4f523757294744bcfdbf915181af88bf8a3af2d785cf48be081132184449f7a6ece7f3da60b690c45e4e4de5dfc0d4b295d30ff5bddecdf9fa247e21c53cd933b5884ae37e3a414b1ec2288074b3cd3957c45c12e832d837fb72a7d332fab194f9b2f8d7c9c5efd8bb7a1963b6ed8d0d09bce952bc9970e558c465ccb506b3cdd87149a8f49e2a6a49a902653a1666f391d0be46566ce0ea01e54762dda305e254b6670efc37f31663df0fe72ea7505aa606494d1fda4f8d5306a71789660c494793ede084a8de19f51b6255ff0067a78603cce2c1418d5556c7a6e099b846f72d73e864f87c2ce543994caca5796dc2d63b008b0d2fc1080322b3fc14b4be437750308427094b9c3c40ba44b928b1a1df363ea8e5689d44b568e78af6197fcf62f88e85c1cd9e76a6ae05836c46ebf7129bf0b269c32884ab2f8f3fa42b1505b5fbb7bc7b7bcf26f24293629e392cd14d80e733cad210c91fa8b56aa08cdc3100d345c837c2cf0dafd87f5a2fe844162768e7a3caa935915e1a3c3355132c4b50f9b204bcbcb55c5ef494c909fa6e73550a06d9a420826ca55d11a406d9e300774b66bf51e7d96eada3eb29b4aea18703f9d3d41d78a08efd9851458cbdbe82d0cf1786802beea6cea68576fb2a8ffae6051b1f40b25af608e1e919b77a7a0766310feb39aa8b861fca97aaa44d97e4f31bf205a16ecf696771317eb8fc8ceec20b9c161aaa06438afca9c03551080951f8d1902c41bfd17f90318d87783ba4e3302b373dcc70f0adda7ab26fe5c8cab5e12346bafdafb89715ef65c4376ace3bc97bd2f8663fda3d8c616c7feec653bddb5f83ccf40d925a8a99b87f26bcb84d4d06280a9fee6df0fcb01d8611a83468f12ee052bd7c482790a5638082680b4b4030667d8d7fc3070ca6ffe89a9747968ddd16e4da008ed05d20cea917d43c1f8297510b8f26b8d0257e3ea38f1243d9413595b058ac5a6c48319be975f7cfb53026cf7f91869735d639b1a4224670ced26b2c2e040cb75d5804e21ca2c7b80a783372cf07828054e800401de32e442082a4decb7d33e34171b27f8e6bfeb54235177a7249cdfc8b9534ac774181cbf8b17c2ce52a30c7d74c6545eaf1738b1bec9f85959e986bf41e9166028f386b0254ab5076e47a1e26e9d502a63f77974b851c56cd5fe10c444cc788c0724c06098911897f74bbedd752ebd40c425135ad18493c5d04b591f8dc2838a3ceb5f5fe4707aea202aa8b5a0e05c33d2e78b3f84efb915d94e588c678fc4d23daec39a0b8d810c8fc6b5d3750855d279d3c5d7beb028ddbd559469668636e8b34cfe2d62ff083e113c1adee1f394a2ae2ffa7fc2c1368a58650007f5a4e7770da94f016c65f31b98c9795515d5b9ab2c73061af12555f3e902a1e97fe50257575a1f4a0a46709372e7040357215256fe38a6f6914ca3037f8444e0026a2e152fdfb2a599aba4740919bab639c8a8f716cd8827fc3314ce9153b0448d69154814af58bbd6152a6834d6929d3ac643733fcc9f69d230051e0953b92cb0b9c9bb1c111a823bdc1419d63ac5e99db9e2530176f6b42bec4f984c3e8668107f30416504af60e7e4ed72028ecb9e2ff3b1354c6b206b9d2ffbe68dd45804814fa8f301dabc0ee4e2dd54e6b8dcae49343583e8d3a133d92f29b73156308840288c34110cc48044aaf19666bf16dbecdc44d9fd98c41ecfdb2ea95984708203a1b82acd5bffaa81068877823ac6ed7bbb5c29a10f15bc2cec4e9b0e3d6009265be0a2c8352b80fbaff94e5b9a75c4dd1dcd2820bc9f855aa62cff8ca7dfd8fecc727fbaa1a065667666a1a9e41bf903abe420df6a25b9400a24c7538ad0d29a5190590e005d7660f4d2a51cbc3a2a0b556386a925467a2070a19cb155e6899b7db57e6c20748d7383bab9a87bee7e982975ee4e4b0b53cfb25283ea03f5ad71c4f17aa72240779e9744b588dd8e9846ef3196e5a43d3d4672996318b20b5479891d720cb3ccf9ce9a3190e675fbd670fbfb8e1601bfcad0f399bc7c9fcc64154c4f856097c5dd2e73acd82e54b7a969ff0b859b3f534d9d779b7b3f9d7cbf72f220560e743ebeefc25ea5d0a80eff3c27e24d1b0ce63895f21745c3c8a6208a803e0c43ebcf2760acc70a483df3813e3f28986dc316e7861f4129196cada295b58d6085b040e8635ebc1982c56af04d48d746a04b5fb10b96fc00307d72f08e6176f3a3117381e7bf5fff6784788fa314c586c9cf8638189a28f90310467f69f27cc57d1035a8c69ae8c566a4701cf092d377c327b563c3edee47cd2c8ab90363dca58d3e905acf33ec3457d29e2931b191789744ddb353f3818ed1aef88b850884bec805fc84e9496c061884cbbf17846da1cf5ac54a5226b3a66976f044416a3822d36c52ce5e73ac6d229273b9b8f78ed449aa860b4134244c7221b0bc4028bb7d17c8447bdd131ed3b9cfb2b157302dcaf3f1efb632e63f1fea272d2a9317abab79ba53653aa7fa5d635abc12c08f62e6843ad240579a46cc4d486002a446695e1a6be9bd6f24dd3aa64a3285554b7a31632df2e2d8b5f6f2e39416994378a4f1bbbb2aaccccc73d36e19e25a08c995bc3b7c4a9f5b100bd556737de791f3a77f3e1f69e0b1e86e5bb65d267bfd483f12d63e6c32f5a76f6e2ca54c7d95c9e1ea67d6a833d3424fa178a1847362260612b5fe3f46dfae43618078b6de4c47d1a14f38df2dd7f14a762298f3d9760f0c4e7103e014b4cba5e5edf8533546285294ef13c0ff5b395ccddd18a37816eff40074052b14e63d363c2715ffe5d19b580a257c6b22128c5e03252a47e01b337cdf2335e9518275deffbffd52ff5cc7407d5d131a799754c63daa91aa27e6d230c38a1a09fb3bc021053c118b62a7622b86dc29817716667ebe90f11d63d60e4a113583381d794e91ac69dab6fa4641edb3a3ab15fb390d682a73ae799dece63b4dde2a9eeb24283cb23b715fcb564643457e6fa0c568ce89144ad62b3a31106b2c4d2efbb6f67645bd4ef93ae6bd6b42d4a433ae019e94d8270fc7408793012918856b2deb904507f39904d93583450f132ea8f4f90dfe0eab1291b667d60f89a56bee8185e7e6233dec5d9164c61f046204ba79936a2b9c0d4058505533e2b662e6930ea00a67ff56f576e69e18e9a56e31010fd32b762bfed763a1a56af4cccdb249a57f77c7e1c90c022af4784a03fbda838e26712399e2d58c3271a5037b348fbf1a5c849d319e03d32513050a9bea615736c66d61412acdca9b71cf0d62de2ec9fba5638ea9b85d68cf668837bb97cea1e3fce7cf6c165b69b25abd1455a7afac9ad43d9915dc2f38736288688a5fac09606df959716c191e5a82e6f89082e5baeb351a7317c966fe0dd0d0cbf14b8db768dfbca050c22276c6743bce34ec1776410bdcb7ea1d68da6cd40dffcd6102736e199d07e2776f0541cbf5b3150bda0eed03b4df02b3a2a2c17c8a30448ca77e3697a81a3d4944b433365978d6856110c2f85362642f4d7c5b09fbe48014ec6cf8425c009bcecc89ff84be45de2732ff05024e2cc71703fa96b3840f67743be39fc7301cda9734ec5c63492a3d88e3c2e48eb2af00107cff0b539454480ac20d70937e1074b975da289031a648d68146e6eb3ba1a8c55a949c01a5fb8d264f020bc2d7925fabff4857aae033dbdcd96d84c1486edd5cf03b8c587ef097b04e5ae02e81441a6f8e852be3b0eff9aca87fe0e638fbda058c48856f09cd03a627581b762f75f5942daf979a00a2cccc5cf8ae3852e04b3c82e5021bc1257f05988a4c2ff4f75fe00306881ca9e3b86640be32c863d1cb55e19219573a6722e1de1a698c0210ad7a454eb6754a2b8dd16ec7e08e81b44b12450eb5064d396c95bcdda35a780b56a530be0265415b7fa6192d51f5c5d586c84f5d5032d43afdea4a4e33648300947179c07a59e5019d14405fb15e5e4d5ccc9859756b33a2467b2296ab3eee7279cd4b68084f678061e8ff2127f53bd6a1bb369524ffb9cc0f0aea159f6f943a0290ca55b9ce9a0f82f46a4c11184ed2a5c70a9d394afb216bc91bd405da33319c9c988b19fc9077dd8dbbaca82e730f49a8f7f1ace058e7c7d0128115e33db6f68ed82707585c0737320a05904d1445d9fb9d267a27a7bc109c2a6ebc6fca9727a44353e166520851e4ba18dd02dae2b6463ebe355418d626c4941eccb53600efe4c499084a65ff6469aed1c6b8cd12793dccf213f741e8a31133f38b220b937f08eeed2b2135322d20a9d14b759d891b6c9ebf599ecd7040b2c6bddb1b6200c619a4e5ff0777059515884e3497932675525cc1c791670d8e73c7b0ea2e11e5d196ea71e0adaf4b049cd5633df0297bbd1f05f89183c8371e37937c8912f9583381da06f858a78e890afaeca041aeb59c07af1d03b70a0e0e0d82e12e21ab32f16f07eae5e3d870d17139484b2eb467cf50e57f3e452a01e68d1250279b135e4b16a8c3c5e92f34ba939d4ab5ab372d5efad66c2e18d1786cd56f2cb46cbfcdd487c25f9880866320205c5ae23e71e3dbf61d8bd4c509a87041d35ece1b8994f6e2effd54167c6a316cbe7a723d69f380f5ba706c79f6ae57770cb74927ccf1bfa38d503c1cca1d22d75fe67105fbdab0acec02fc086c842d3c8fe0b44db5253b368df2749312282c67203a91794e8447d11fed4a77b14f7b08092d2f792854742572a90313b460a1421b45aac45fd4f9198e9f9d07004082c841eff3484e282bb9bce90b49fba5ee5c1094fcda4268987cf3166398f98914b161262f8041112378544124813ce467c2a38be62419d5769f74e7ef53037fc661a6eb625019f373cbaac5ab6d9b753572df1e6cd14b2e7765a08bafa22f43cec7864fef0cea943d6628e9665a243314ac9c53dedd456bbe009e5df36e670d05f598c92169264e76a409f0f6104c8460d66ad0e98207b5e1535186f2015491901f48bde63fe266cebfb5ebf46a8651516092d74921de32fa3129cfe32be6e70f070876bbeb5f19943b96450ebfa558b2799daaa80c7a49f9295b23a27cc0ab575479ee0b8d466f62643fa34d07a6a071e1ee80bbf53739ec22f56d6f155821ac9648a24caeba8dcc2e77885b2fd1108dc5b34f528745974b65e1736ee0a636ae5612367e57e64fe3ddb351d9c541547ff1cb895b95f8f03898c19b6a0c0dda245efe81ca9c6d333eeb01070b26f3e40daeac1691d46dd505eec2ec538ecd9e8b29ee2e1899abd60446f57759b09e65dc1ea0066c05366422fc62ed05921710b859fc45d2fcb76e06336b48cb0e84c2c315feaf37d6ed0c095368330dfabe70c16f932839b43dbe0a18b7f774d347f4130ab8d7780da8cad97acff78aa44ffb69a955138d6912e514027b3fd50535728ab6aaa580fd1fc05dacc604848394cda24fa5b10b462835a4f6ed03387a79bf7e7dd258ded40b486d5846ca1070665715e32b829746f2bf0267bc5188d4fde246a434ac5eccfd0b8948c1a3f3b7090c939bf94cbacc5d214f90e8f636fca7ae52ac0ce50cd8912f88d9aeb776eba31abf876ae96f6114687a5dbff140bccb198274d2bc6cf432c2423ed3dfbe922b40caac3fb01c2382ea431e46158fc3b3a4503aaf568343a398358aac2229426e8784f3920be3280b428dc9614c055b9daa2db8c7c7ff1740488203850675291ca81f6d51515f39a2f81a76f83b8f3e2d44b1fb33a2af0ccd73feb7e70f1f6c3df4ff6678a5c610211f100d4b7beecb1b7cdf724567f51a87d44859ebcb4acc1ef27258b72e95c044bccf784cfce60d85a6a93104e5bb5960e703acc8c750b1c0687f43f10cedbbe40708aec8ee52d2099f95c3402ee5d81192fea74b809ee91ce690216c344bb50d0bfd235bb3ba87b22c4644c19f078a667531a0fd548e612088784f43d7a96d4a127fb27c30ac1afbcd958f9c2592dce88deb6ea7768e29910c809108f99e5f2fcec33f152e9ac079fe8cdb686f72156c4e3c188b36db2aec8317db697da440c49a8569dc0da05cc70f33bbc93c136634e10a43cf167beefa6b6d563c065fd164564dd913e73738ca7add8d789417ae9a4b30dad8f8f44a84cfaa40907d900d6a08509a599597f42970b45b8f0e81fe55fa2c3d198c4b5a4aced3d4bcf8d3a1d8a900a5c9313479ba35f9c81df4d1ce26c2f8095e97d8aadd9fc3257f8c11747df5696b39f554d46ef2e2884c08b3198d18d899600bd6e17c2006a7c90ebb7ce35357144562756812ea611b34fc224c257dbdf4c7ae2da0b16f010070d6396e200a45d9d02e9fe5255a01a1bc5ab6f660de275b69236777b46babf49ee4ffe570a18cc23514cb0782748e7451cdc3b48b6991076fe5c0b1ce8bd367ad983a1f6589c1ff69e710f09ff549695e640e166256b41fcefb95da0b4c93e8564507bef409a371a77817728977921d343d9066ca4fef2c90b8ec5041aa3537eb6d8204bdfe6f3dc3ef8a8a8dad7a3250ac7b441944edfd7fc9ed3a1dd46b877d47b4185560185dfb19f2299e5287dec69a191e3673233fead155e0f72bc79d7b9d02e49fff1ac8dad3b3ec1f03f7b0246f720c7a98bbff6fac5bef4697b5d774ae33a2633879672cf1fd3ab5a2b930213f2a04e1f3908da71f2b56d689cf601505adaf31a00c168ca22437d0b2d238ac627aa7f8e064a68c37c3ff7cf14108b16c02c205dc8d529c0c8d800a98abe039bb1b6a36c48ca3f47e1a8a436a7b2c8a8230e1906d6caa9b5ad32600ccba9673fbf2aad99f80cabce9211a2b9268c12f6a281121b38c5e419c13c5eb21dae1465bb6442105176f0fb7616cc3f75647eea5cc7a33f918619c6c654bd86ea557568ce7b16b89bb5af6428d02da0cc4b48d4943ef6b6443c342b966039a6fb43ef525b5ef790c5a2dcebae65f1c42c5e70b5e9cf545fa8d81420a0bf877ea90ea0a25c3bd05972ce22227f668efba3c59da81e90cbdcfd36038f2013fa5ab6107395e8e0ac530d9909317a3479380d4974cabfc5f45160946be5258104d06f19ec6480a7c1fbeb0d773b0fd404cf76f27916f32fa507d0c1d33c98cd50836804455d04fa52487c5548657610f8e4ba9288553d09cca3c5194931de94a265f8842bc0f6c7a77cc56f345415a5c7d9f04caba9e881d1b0ac9ebbd60d65991bd4348ad5c1c5ace8ab4f6652b10a74ad52be02e30f4125d63873f3b79f6dcf658ad7b22fa9f71e06744fad0f50fda98b9d63ac827b97b5707b3c903fccb1bb55048f9ae941823f1ac3e62a1735de50ae63a956d9e281a3a4275a13a87ad22807c791b71f73ba67fe4640566ed4981987d61b76e2758ddca4c5784b0a98e564af3a7820f3416b95ffdf963402aecf51edc292f3f90cda3bc2e9d22dfaf7a3e49a506a9480f5b593e7f79efc69bd9b7e9f3d5e7085314e5ce9fbb6cb9a34f41a7dae370463cdd1b0dd151e98fa9008ceef9924cf5e87ccb9e85330c6817334d9bc31d85f19a459d323b5e5aeaf5fa7b62f3279b466e6667662732950bf8b79b8cdc9cbf22cc4d96025ff0a6bce205f699d5467004d4df51586edbc3ee72e71eaddfe2cc651ecd30ab4b2b9490f0f0388100fc209338727d65646649283caf9c4939c30d92a58683c2f7186a0c5cf13a4bab5a0f9fc3aa48237333874123646e6106cb2de775ba6f3006caae7a98523e1fb05c91fa907a0eed87e23b1315436013cc29dec6302fcdc6c7f0a0f346b82dec2bcd46dbe6ae0c708e8cd2b2a83801a0771abb0feacd6d0d017154e86d9dc380ab57f7fa095c1f84e035a2c0dfd4c653b986f4a87ccd1020acb2c89a220740bbfd6e141ad4928a9a14fc686479ce8dc4ea4b8b33da3318c74b045e2961e90dc24034090e2bbfb68e4f3ea17c7c667fc7480fef10fdd41551d59af851992421373e85fdf0fc8081b8a9af82329632b4996baea3878dd439ba7211e0005b6d04906eb4529840f26631da67a149c6056eecfe493a8d553be465e458a12e36e33136275670268d5ac2ee42e7d8e0fe6220ed5d180baa2c74814caceb5a3cd41ac450755fe8f968c2729592bd9f9c988ca219ec21361cb3daeb764cb2d72a83dcc13c39a3b28ef64e717ff4444ddfd2f095d5377039aa37e0e431c3932fcd1dff94fb5e054f3f07c7785fbcd8edeb30192b8f7f9eced21af4cb69257d24306003241dd3ba587f1e4ac1568db8e43451f74009cdf8fb1be4dad634ad88bbec462d353e8604dd2d417329a910844acdcd468eb6730ed061e41aae33b586a6681203fe2eed3e941c398a4cac4f71e44ae1f087db4095eda315c9363c5f91e437b6eb9b1bdd2f9d217890fbe5ab1732190430fa75a50e5116139134f574d0baeeaf448638527e68ea1e928bed290a96c317f94ba353d4135dc86411748347dfab067f8264dc4efa123d78e7c0df9245f7aa55f2ff346a7f958762324ff9b8b8999c55fdb326674dc581b1caa4200763869ac05649fe50f66b29e4771856586a55bd7acbbd823cb3dc5be98511f5f7e9d9c2963d24442b3e91435d2ba2b501caf8fc5cc7efb81588c780359ee96734c0646bc61aaa63c6fca468c34845d07fddacfba15e81daa60381ba80543f7114340a14d0676a3968fc1085bbce07ff987099714cd7050f0b0d1a33be229072dbc39f0ddc61ed529da8030a7c818203fba4ceb54079a5e2e75094f6dc19edbbde69fe399099c0d549c3b299ea0cbfaf03d66f6c83b0d8bda21614eddb9a910dda142900b2c040de9c27ad04bc174f80ac9c2419af71589e38e0cdf966edea971a940d6a0eaf4057f7154483956c600441104a9c7c5986104ec32752db36ce0c64c86917a20d9fe94c52f312551551cc00f1c013ce3f1f39220ee0b1df60045fa5f53471fc24ae50f94e76810b93175ec75cc6af1dec6fade31b1bb40513773df457ce4eccbeffb24c90400c03aa9209df2a2b8f35fc61b27eba454c6402c59122b9f151a72f393933eb065001fa71f194381c6fc30f76eb8d30f1bfe0436df769897b3a390718914aa540e54b152d9af58f55e801089ce4aea8db7317872f3df0be5a19e879ebc96cd92f740eec4b40a72577409fe3663a9c61a003e3e6538e78ebec600719a58b6dbd86f35abf833749019287d9b5679e08958ebbe2facd50a512fa22e7be6767233a115c14a14a3d4574891b9901ac5218c081ac52fc85f085b4dd78711b30b428a7ed4650c541c03cd217a93430a823e3eaa0b904f9e3c8eb1eac572f7591f50acbe29bb130a91e6df798fda187512af46dbb8aa79f276860771a6471a0083416af6ebb401d03c23e9a498625b88e95dda018bdb300be5404c41b889a36b56ba7163169c51dd2f179dd17dbda65fb24612bf08dfb06a4955c8149ce16d61173823eeaa392439a556f23c60de1f3b5e297db544018f641d902e941075bb3bac6ec119a68850ac34843b1e5429e626a0f0997327708297ccb31528f422973962835da97d83a2c74879513d307f5b465c4f3fab892edd93c40ed6911896a69bc599712991be71a7bae93ff68f688e2a2e37ba9da3405b0d74f1c3a60bf87ae2655689c61855208cfa75ab2d09ad9906034dc5194eb668ea41d317cd4d190bca783d3ab94e43a3a09e4cf6d15712bc770039b15b0296aac252ee8800d3e9a5587a7ac5e4a23bbb5cbd74ac915bf417612b004403c63e397639403885ce8eba16e25682ed05bb6b1ac2e4b5274e9b1a57c66ee7348211d9dd8e2de2098d2d9031462176c5c012e2314992084160b71c483311aeeb45f07a79c801dea548cf3d2298d85dec3da81c1ca08b382152c86bd4d43cffd0f618f8762e7f075170b47cb2b1a4f166601e30980c6b713b38eb508adec64bf2563e86539f652d73d481adfb80cece679bf738e9cd837784df8a2d9c0f1dcbb7c31fc7cda01e3e17632a908ec71e2a979c60900db2c582e1ff2202a650dec58a9bc283ae6f75f1dfab48185d1c3219763e64c7c96de4d2ab5a9f85f67028e05942d3ee99c51b22f250e40e98d7a00aeb4efbe0810ff3665072cac7f7865733bc2eafd058a4704b781880eaae8c6a74cffc887b42642d726791c56d3709f9632dd86bd81802e999317ba2409237f0be04a6881ce79cbe348c14bf7442bceac3b80a8950e0e129b5005aed7ac2867f68cd543e44ce4b920e9efb2df7ded246730249062ba43074e6841a167e14bdf0d1b61ba1f1b6900d8d8edd56ba6d28215c1e54d8f9a5c23cf16a9ca4f1bd86ee7f20c153169504aff749e56c8c28325643fd5507e85b774b0f0e4ee6cd8f884ec960144e4d3fb8fe136e0863024a"); - Crypto.HaruCrypt.Decrypt(encryptedTest); - LoggerFactory.Logger.Debug(JsonConvert.SerializeObject(encryptedTest));*/ - #if DEBUG if (Common.Common.config.VerboseLevel < Common.VerboseLevel.Debug) Common.Common.config.VerboseLevel = Common.VerboseLevel.Debug; #endif PacketFactory.LoadPacketHandlers(); + CommandFactory.LoadCommands(); + Task.Run(Server.Instance.Start); SDKServer.SDKServer.Main(args); }