diff --git a/AscNet.GameServer/Commands/CoatingCommand.cs b/AscNet.GameServer/Commands/CoatingCommand.cs new file mode 100644 index 00000000..099caf14 --- /dev/null +++ b/AscNet.GameServer/Commands/CoatingCommand.cs @@ -0,0 +1,63 @@ +using AscNet.Common.MsgPack; +using AscNet.Common.Util; +using AscNet.GameServer.Handlers; +using AscNet.Table.V2.share.fashion; + +namespace AscNet.GameServer.Commands +{ + [CommandName("coating")] + internal class CoatingCommand : Command + { + public CoatingCommand(Session session, string[] args, bool validate = true) : base(session, args, validate) { } + + public override string Help => "Command to unlock all coatings of characters."; + + [Argument(0, @"^unlock$", "The operation selected (unlock)")] + string Op { get; set; } = string.Empty; + + [Argument(1, @"^[0-9]+$|^all$", "The target character, value is character id or 'all' for all owned character")] + string Target { get; set; } = string.Empty; + + public override void Execute() + { + int characterId = Miscs.ParseIntOr(Target); + + switch (Op) + { + case "unlock": + if (Target == "all") + { + List newFashions = new(); + foreach (var fashion in TableReaderV2.Parse().Where(x => session.character.Characters.Any(y => y.Id == x.CharacterId))) + { + if (session.character.Fashions.Any(x => x.Id == fashion.Id)) + continue; + + newFashions.Add(new() { Id = fashion.Id }); + } + + session.SendPush(new FashionSyncNotify() { FashionList = newFashions }); + session.character.Fashions.AddRange(newFashions); + } + else + { + List newFashions = new(); + foreach (var fashion in TableReaderV2.Parse().Where(x => x.CharacterId == characterId)) + { + if (session.character.Fashions.Any(x => x.Id == fashion.Id)) + continue; + + newFashions.Add(new() { Id = fashion.Id }); + } + + session.SendPush(new FashionSyncNotify() { FashionList = newFashions }); + session.character.Fashions.AddRange(newFashions); + } + + break; + default: + throw new InvalidOperationException("Invalid operation!"); + } + } + } +} diff --git a/AscNet.GameServer/Handlers/FashionModule.cs b/AscNet.GameServer/Handlers/FashionModule.cs new file mode 100644 index 00000000..0a60b78d --- /dev/null +++ b/AscNet.GameServer/Handlers/FashionModule.cs @@ -0,0 +1,44 @@ +using AscNet.Common.MsgPack; +using AscNet.Common.Util; +using AscNet.Table.V2.share.fashion; +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 FashionUseRequest + { + public uint FashionId { get; set; } + } + + [MessagePackObject(true)] + public class FashionUseResponse + { + public int Code { 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 FashionModule + { + [RequestPacketHandler("FashionUseRequest")] + public static void HandleFashionUseRequestHandler(Session session, Packet.Request packet) + { + FashionUseRequest req = packet.Deserialize(); + var character = session.character.Characters.Find(x => x.Id == TableReaderV2.Parse().Find(x => x.Id == req.FashionId)?.CharacterId); + + if (character is not null) + { + character.FashionId = req.FashionId; + + NotifyCharacterDataList notifyCharacterData = new(); + notifyCharacterData.CharacterDataList.Add(character); + session.SendPush(notifyCharacterData); + } + + session.SendResponse(new FashionUseResponse(), packet.Id); + } + } +} diff --git a/AscNet/Program.cs b/AscNet/Program.cs index 205e8986..8e12ac15 100644 --- a/AscNet/Program.cs +++ b/AscNet/Program.cs @@ -2,7 +2,6 @@ using AscNet.GameServer.Handlers; using AscNet.GameServer.Commands; using AscNet.Logging; -using Newtonsoft.Json; namespace AscNet {