diff --git a/.gitattributes b/.gitattributes index 130805e..327bbd8 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,3 +1,3 @@ # Auto detect text files and perform LF normalization * text=auto -* text eol=lf +cert.sh text eol=lf diff --git a/ProtobufViewUtil/Program.cs b/ProtobufViewUtil/Program.cs index cbdde1b..80de512 100644 --- a/ProtobufViewUtil/Program.cs +++ b/ProtobufViewUtil/Program.cs @@ -10,8 +10,8 @@ namespace ProtobufViewUtil { Console.WriteLine("Hello, World!"); - ResGetStageData s = new ResGetStageData(); - var inn = File.ReadAllBytes(@"C:\Users\Misha\Downloads\getstageinfo2"); + ResGetMainQuestData s = new ResGetMainQuestData(); + var inn = File.ReadAllBytes(@"C:\Users\Misha\Downloads\getmainquestdata-stage01complete"); s.MergeFrom(inn); Console.WriteLine(s.ToString()); var outt = s.ToByteArray(); diff --git a/nksrv/LobbyServer/Msgs/Campaign/GetCampaignField.cs b/nksrv/LobbyServer/Msgs/Campaign/GetCampaignField.cs index 6251678..2e200a4 100644 --- a/nksrv/LobbyServer/Msgs/Campaign/GetCampaignField.cs +++ b/nksrv/LobbyServer/Msgs/Campaign/GetCampaignField.cs @@ -1,5 +1,6 @@ using nksrv.LobbyServer.Msgs.Stage; using nksrv.Utils; +using Swan.Logging; using System; using System.Collections.Generic; using System.Linq; @@ -19,7 +20,7 @@ namespace nksrv.LobbyServer.Msgs.Campaign Console.WriteLine("Map ID: " + req.MapId); var response = new ResGetCampaignFieldData(); - response.Field = GetStage.CreateFieldInfo(user, 0); // TODO dont hardcode chapter + response.Field = GetStage.CreateFieldInfo(user, GetChapterFromMapId(req.MapId)); // todo save this data response.Team = new NetUserTeamData() { LastContentsTeamNumber = 1, Type = 1 }; @@ -40,5 +41,19 @@ namespace nksrv.LobbyServer.Msgs.Campaign WriteData(response); } + + public static int GetChapterFromMapId(string mapId) + { + switch(mapId) + { + case "fcbg_cityforest_000": + return 0; + case "fcbg_cityforest_003": + return 1; + default: + Logger.Warn("TODO: I don't know what chapter mapid " + mapId + " is"); + return 101; + } + } } } diff --git a/nksrv/LobbyServer/Msgs/Character/GetSynchrodevice.cs b/nksrv/LobbyServer/Msgs/Character/GetSynchrodevice.cs new file mode 100644 index 0000000..f396764 --- /dev/null +++ b/nksrv/LobbyServer/Msgs/Character/GetSynchrodevice.cs @@ -0,0 +1,29 @@ +using nksrv.Utils; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace nksrv.LobbyServer.Msgs.Character +{ + [PacketPath("/character/synchrodevice/get")] + public class GetSynchrodevice : LobbyMsgHandler + { + protected override async Task HandleAsync() + { + var req = await ReadData(); + + var response = new ReqGetSynchroData(); + response.Synchro = new NetUserSynchroData(); + response.Synchro.SynchroLv = 1; + response.Synchro.Slots.Add(new NetSynchroSlot() { Slot = 1 }); + response.Synchro.Slots.Add(new NetSynchroSlot() { Slot = 2 }); + response.Synchro.Slots.Add(new NetSynchroSlot() { Slot = 3 }); + response.Synchro.Slots.Add(new NetSynchroSlot() { Slot = 4 }); + response.Synchro.Slots.Add(new NetSynchroSlot() { Slot = 5 }); + // TODO: Validate response from real server and pull info from user info + WriteData(response); + } + } +} diff --git a/nksrv/LobbyServer/Msgs/Inventory/GetInventoryData.cs b/nksrv/LobbyServer/Msgs/Inventory/GetInventoryData.cs new file mode 100644 index 0000000..5081aaf --- /dev/null +++ b/nksrv/LobbyServer/Msgs/Inventory/GetInventoryData.cs @@ -0,0 +1,24 @@ +using nksrv.Utils; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace nksrv.LobbyServer.Msgs.Inventory +{ + [PacketPath("/inventory/get")] + public class GetInventoryData : LobbyMsgHandler + { + protected override async Task HandleAsync() + { + var req = ReadData(); + + var response = new ResGetInventoryData(); + + // TODO implement + + WriteData(response); + } + } +} diff --git a/nksrv/LobbyServer/Msgs/Outpost/MemorialGetMemoryList.cs b/nksrv/LobbyServer/Msgs/Outpost/MemorialGetMemoryList.cs new file mode 100644 index 0000000..f08f3a3 --- /dev/null +++ b/nksrv/LobbyServer/Msgs/Outpost/MemorialGetMemoryList.cs @@ -0,0 +1,17 @@ +using nksrv.Utils; + +namespace nksrv.LobbyServer.Msgs.Outpost +{ + [PacketPath("/outpost/memorial/getmemorylist")] + public class MemorialGetMemoryList : LobbyMsgHandler + { + protected override async Task HandleAsync() + { + var req = await ReadData(); + + var response = new ResGetMemoryList(); + // TODO + WriteData(response); + } + } +} diff --git a/nksrv/LobbyServer/Msgs/Shop/InApp/GetProductListInApp.cs b/nksrv/LobbyServer/Msgs/Shop/InApp/GetProductListInApp.cs new file mode 100644 index 0000000..66425b5 --- /dev/null +++ b/nksrv/LobbyServer/Msgs/Shop/InApp/GetProductListInApp.cs @@ -0,0 +1,23 @@ +using nksrv.Utils; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace nksrv.LobbyServer.Msgs.Shop.InApp +{ + [PacketPath("/inappshop/getdata")] + public class GetProductList : LobbyMsgHandler + { + protected override async Task HandleAsync() + { + var x = await ReadData(); + + var response = new ResGetInAppShopData(); + // TODO + + WriteData(response); + } + } +} diff --git a/nksrv/LobbyServer/Msgs/Tower/GetTowerData.cs b/nksrv/LobbyServer/Msgs/Tower/GetTowerData.cs new file mode 100644 index 0000000..a9db463 --- /dev/null +++ b/nksrv/LobbyServer/Msgs/Tower/GetTowerData.cs @@ -0,0 +1,22 @@ +using nksrv.Utils; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace nksrv.LobbyServer.Msgs.Tower +{ + [PacketPath("/tower/gettowerdata")] + public class GetTowerData : LobbyMsgHandler + { + protected override async Task HandleAsync() + { + var req = await ReadData(); + + var response = new ResGetTowerData(); + // TODO + WriteData(response); + } + } +} diff --git a/nksrv/Protos/allmsgs.proto b/nksrv/Protos/allmsgs.proto index 96f6902..852e5b4 100644 --- a/nksrv/Protos/allmsgs.proto +++ b/nksrv/Protos/allmsgs.proto @@ -1144,3 +1144,75 @@ message ReqGetCharacterCostumeData {} message ResGetCharacterCostumeData { repeated int32 costumeIds = 2; } + +message ReqGetInventoryData {} +message ResGetInventoryData { + repeated NetUserItemData items = 2; + repeated NetUserHarmonyCubeData harmonyCubes = 3; + NetEquipmentAwakening awakenings = 4; + repeated int64 runAwakeningIsnList = 5; + repeated NetUserRedeemData userRedeems = 6; +} + +message NetInAppShopData { + int32 id = 1; + int64 startDate = 2; + int64 endDate = 3; +} +message NetInAppShopBuyData { + int32 productType = 1; + int32 shopTid = 2; + int32 buyCount = 3; + int32 listTid = 4; +} + +message ReqGetInAppShopData {} +message ResGetInAppShopData { + repeated NetInAppShopData inAppShopDataList = 1; + repeated NetInAppShopBuyData buyDataList = 2; +} + +message NetSchedule { + oneof ScheduleKindOneof { + int32 OnlyOnceFieldNumber = 1; + int32 DayOfWeekFieldNumber = 2; + int32 PeriodicFieldNumber = 4; + int32 AllTimeFieldNumber = 5; + } +} + +message NetTowerData { + int32 type = 1; + int32 floor = 2; + int32 remainCount = 3; + repeated NetSchedule schedules = 4; +} +message ReqGetTowerData { + +} +message ResGetTowerData { + repeated NetTowerData data = 2; +} + +message ReqGetMemoryList {} +message ResGetMemoryList { + repeated int32 memoryList = 2; + repeated int32 rewardableSeriesList = 3; +} + +message NetSynchroSlot { + int32 slot = 1; + int64 csn = 2; + int64 availableRegisterAt = 3; +} +message NetUserSynchroData { + int32 synchroLv = 1; + int32 synchroMaxLv = 2; + bool isChanged = 3; + repeated NetUserCharacterData standardCharacters = 4; + repeated NetSynchroSlot Slots = 5; +} + +message ReqGetSynchroData { + NetUserSynchroData synchro = 2; +} \ No newline at end of file diff --git a/nksrv/Utils/PacketDecryption.cs b/nksrv/Utils/PacketDecryption.cs index 65914f8..ef48f5f 100644 --- a/nksrv/Utils/PacketDecryption.cs +++ b/nksrv/Utils/PacketDecryption.cs @@ -3,6 +3,7 @@ using Microsoft.AspNetCore.DataProtection.KeyManagement; using nksrv.LobbyServer; using Sodium; using System; +using System.Buffers.Binary; using System.Collections.Generic; using System.IO.Compression; using System.Linq; @@ -64,20 +65,10 @@ namespace nksrv.Utils // File.WriteAllBytes("fullPkt-decr", ms.ToArray()); var unkVal1 = ms.ReadByte(); - var pktLen = ms.ReadByte() & 0x1f; + var unkVal2 = ms.ReadByte(); + var sequenceNumber = ReadCborInteger(ms); - var seqNumB = ms.ReadByte(); - var seqNum = seqNumB; - if (seqNumB >= 24) - { - var b = ms.ReadByte(); - - seqNum = BitConverter.ToUInt16(new byte[] { (byte)b, (byte)seqNumB }, 0); - - // todo support uint32 - } - var startPos = (int)ms.Position; //Console.WriteLine("seg #: " + seqNum + ",actual:" + bytes.Length + "cntlen:" + ctx.Request.ContentLength64); @@ -103,6 +94,69 @@ namespace nksrv.Utils return new PacketDecryptResponse() { Contents = buffer.ToArray() }; } + public static ulong ReadCborInteger(Stream stream) + { + // Read the initial byte + int initialByte = stream.ReadByte(); + if (initialByte == -1) + { + throw new EndOfStreamException("Stream ended unexpectedly"); + } + + // Major type is the first 3 bits of the initial byte + int majorType = (initialByte >> 5) & 0x07; + // Additional info is the last 5 bits of the initial byte + int additionalInfo = initialByte & 0x1F; + + if (majorType != 0) + { + //throw new InvalidDataException("Not a valid CBOR unsigned integer"); + } + + ulong value; + if (additionalInfo < 24) + { + value = (ulong)additionalInfo; + } + else if (additionalInfo == 24) + { + value = (ulong)stream.ReadByte(); + } + else if (additionalInfo == 25) + { + Span buffer = stackalloc byte[2]; + if (stream.Read(buffer) != 2) + { + throw new EndOfStreamException("Stream ended unexpectedly"); + } + value = BinaryPrimitives.ReadUInt16BigEndian(buffer); + } + else if (additionalInfo == 26) + { + Span buffer = stackalloc byte[4]; + if (stream.Read(buffer) != 4) + { + throw new EndOfStreamException("Stream ended unexpectedly"); + } + value = BinaryPrimitives.ReadUInt32BigEndian(buffer); + } + else if (additionalInfo == 27) + { + Span buffer = stackalloc byte[8]; + if (stream.Read(buffer) != 8) + { + throw new EndOfStreamException("Stream ended unexpectedly"); + } + value = BinaryPrimitives.ReadUInt64BigEndian(buffer); + } + else + { + throw new InvalidDataException("Invalid additional info for CBOR unsigned integer"); + } + + return value; + } + public static byte[] EncryptData(byte[] message, string authToken) { var key = LobbyHandler.GetInfo(authToken);