From db70b5068e48568ad89df5bb1a4ba544a00d10a3 Mon Sep 17 00:00:00 2001 From: Mikhail Date: Mon, 15 Jul 2024 14:05:30 -0400 Subject: [PATCH] implement tactic academy --- .../Msgs/Outpost/ClearTacticAcademyLesson.cs | 44 +++++++++++++++++++ .../Msgs/Outpost/GetTacticAcademyData.cs | 25 +++++++++++ nksrv/Protos/outpost.proto | 22 ++++++++++ nksrv/StaticInfo/JsonStaticData.cs | 10 ++++- nksrv/StaticInfo/StaticDataParser.cs | 30 +++++++++++++ nksrv/Utils/JsonDb.cs | 1 + 6 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 nksrv/LobbyServer/Msgs/Outpost/ClearTacticAcademyLesson.cs create mode 100644 nksrv/LobbyServer/Msgs/Outpost/GetTacticAcademyData.cs create mode 100644 nksrv/Protos/outpost.proto diff --git a/nksrv/LobbyServer/Msgs/Outpost/ClearTacticAcademyLesson.cs b/nksrv/LobbyServer/Msgs/Outpost/ClearTacticAcademyLesson.cs new file mode 100644 index 0000000..a245c2e --- /dev/null +++ b/nksrv/LobbyServer/Msgs/Outpost/ClearTacticAcademyLesson.cs @@ -0,0 +1,44 @@ +using nksrv.Net; +using nksrv.StaticInfo; +using nksrv.Utils; +using Swan.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace nksrv.LobbyServer.Msgs.Outpost +{ + [PacketPath("/outpost/tactic/clearlesson")] + public class ClearTacticAcademyLesson : LobbyMsgHandler + { + protected override async Task HandleAsync() + { + var req = await ReadData(); + var user = GetUser(); + + var response = new TacticAcademyClearLessonResponse(); + response.LessonId = req.LessonId; + + var x = StaticDataParser.Instance.GetTacticAcademyLesson(req.LessonId); + + if (user.CanSubtractCurrency(x.CurrencyId, x.CurrencyValue)) + { + user.SubtractCurrency(x.CurrencyId, x.CurrencyValue); + + user.CompletedTacticAcademyLessons.Add(req.LessonId); + + foreach (var currency in user.Currency) + { + response.RemainingCurrency.Add(new NetUserCurrencyData() { Type = (int)currency.Key, Value = currency.Value }); + } + } + else + { + Logger.Error($"User {user.PlayerName} tried to clear lesson {req.LessonId} without enough currency"); + } + await WriteDataAsync(response); + } + } +} diff --git a/nksrv/LobbyServer/Msgs/Outpost/GetTacticAcademyData.cs b/nksrv/LobbyServer/Msgs/Outpost/GetTacticAcademyData.cs new file mode 100644 index 0000000..610b454 --- /dev/null +++ b/nksrv/LobbyServer/Msgs/Outpost/GetTacticAcademyData.cs @@ -0,0 +1,25 @@ +using nksrv.Net; +using nksrv.Utils; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace nksrv.LobbyServer.Msgs.Outpost +{ + [PacketPath("/outpost/tactic/get")] + public class GetTacticAcademyData : LobbyMsgHandler + { + protected override async Task HandleAsync() + { + var req = await ReadData(); + var user = GetUser(); + + var response = new GetTacticAcademyDataResponse(); + response.CompletedLessons.AddRange(user.CompletedTacticAcademyLessons); + + await WriteDataAsync(response); + } + } +} diff --git a/nksrv/Protos/outpost.proto b/nksrv/Protos/outpost.proto new file mode 100644 index 0000000..367ec7f --- /dev/null +++ b/nksrv/Protos/outpost.proto @@ -0,0 +1,22 @@ +syntax = "proto3"; + +option csharp_namespace = "nksrv.Net"; + +import "google/protobuf/timestamp.proto"; +import "google/protobuf/Duration.proto"; +import "Protos/allmsgs.proto"; + +// Get Tactic Academy data +message GetTacticAcademyDataRequest {} +message GetTacticAcademyDataResponse { + repeated int32 CompletedLessons = 2; +} + +// Clear Tactic Academy lesson +message TacticAcademyClearLessonRequest { + int32 LessonId = 2; +} +message TacticAcademyClearLessonResponse { + int32 LessonId = 2; + repeated NetUserCurrencyData RemainingCurrency = 4; +} \ No newline at end of file diff --git a/nksrv/StaticInfo/JsonStaticData.cs b/nksrv/StaticInfo/JsonStaticData.cs index 17c6085..ed02434 100644 --- a/nksrv/StaticInfo/JsonStaticData.cs +++ b/nksrv/StaticInfo/JsonStaticData.cs @@ -67,7 +67,7 @@ namespace nksrv.StaticInfo /// /// can be CharacterLevel or SynchroLevel /// - public string type = ""; + public string type = ""; /// /// amount of credits required /// @@ -81,4 +81,12 @@ namespace nksrv.StaticInfo /// public int character_exp2 = 0; } + + public class TacticAcademyLessonRecord + { + public CurrencyType CurrencyId; + public int CurrencyValue; + public int Id; + public int GroupId; + } } diff --git a/nksrv/StaticInfo/StaticDataParser.cs b/nksrv/StaticInfo/StaticDataParser.cs index 2355ec6..01c6aba 100644 --- a/nksrv/StaticInfo/StaticDataParser.cs +++ b/nksrv/StaticInfo/StaticDataParser.cs @@ -13,6 +13,7 @@ using Newtonsoft.Json.Linq; using Swan.Parsers; using Newtonsoft.Json; using System.Drawing; +using Google.Protobuf.WellKnownTypes; namespace nksrv.StaticInfo { @@ -56,6 +57,7 @@ namespace nksrv.StaticInfo private JArray tutorialTable; private JArray itemEquipTable; private Dictionary LevelData = []; + private Dictionary TacticAcademyLessons = []; public byte[] Sha256Hash; public int Size; @@ -256,6 +258,29 @@ namespace nksrv.StaticInfo else Logger.Warn("failed to read character level table entry"); } + + var tacticLessonTable = await LoadZip("TacticAcademyFunctionTable.json"); + + foreach (JToken item in tacticLessonTable) + { + var idRaw = item["id"]; + var groupidRaw = item["group_id"]; + var currencyIdRaw = item["currency_id"]; + var currencyValueRaw = item["currency_value"]; + + if (idRaw == null) throw new InvalidDataException(); + if (groupidRaw == null) throw new InvalidDataException(); + if (currencyIdRaw == null) throw new InvalidDataException(); + if (currencyValueRaw == null) throw new InvalidDataException(); + + var id = idRaw.ToObject(); + var currencyId = currencyIdRaw.ToObject(); + var currencyValue = currencyValueRaw.ToObject(); + var groupid = groupidRaw.ToObject(); + + var fullId = int.Parse(groupid.ToString() + id.ToString()); + TacticAcademyLessons.Add(id, new TacticAcademyLessonRecord() { CurrencyId = (CurrencyType)currencyId, CurrencyValue = currencyValue, GroupId = groupid, Id = id }); + } } public MainQuestCompletionData? GetMainQuestForStageClearCondition(int stage) @@ -481,5 +506,10 @@ namespace nksrv.StaticInfo { return LevelData; } + + public TacticAcademyLessonRecord GetTacticAcademyLesson(int lessonId) + { + return TacticAcademyLessons[lessonId]; + } } } diff --git a/nksrv/Utils/JsonDb.cs b/nksrv/Utils/JsonDb.cs index eb1d2a0..52f3b4a 100644 --- a/nksrv/Utils/JsonDb.cs +++ b/nksrv/Utils/JsonDb.cs @@ -109,6 +109,7 @@ namespace nksrv.Utils public NetOutpostBattleLevel OutpostBattleLevel = new() { Level = 1 }; public int GachaTutorialPlayCount = 0; + public List CompletedTacticAcademyLessons = []; // Event data public Dictionary EventInfo = new();