From 5de3551ef37f37b5002d9ce32835ed5d0814018a Mon Sep 17 00:00:00 2001 From: Kei-Luna Date: Tue, 26 May 2026 07:47:49 +0900 Subject: [PATCH] DLCLogic_CheckOpenAct --- Common/Data/Excel/DlcActivityExcel.cs | 21 ++++ Common/Data/GameData.cs | 1 + .../Activity/DLCLogic_CheckOpenAct.cs | 112 ++++++++++++++++++ 3 files changed, 134 insertions(+) create mode 100644 Common/Data/Excel/DlcActivityExcel.cs create mode 100644 GameServer/Server/CallGS/Handlers/Activity/DLCLogic_CheckOpenAct.cs diff --git a/Common/Data/Excel/DlcActivityExcel.cs b/Common/Data/Excel/DlcActivityExcel.cs new file mode 100644 index 0000000..8250cf4 --- /dev/null +++ b/Common/Data/Excel/DlcActivityExcel.cs @@ -0,0 +1,21 @@ +using Newtonsoft.Json; + +namespace MikuSB.Data.Excel; + +[ResourceEntity("dlc/dlc_activities.json")] +public class DlcActivityExcel : ExcelResource +{ + [JsonProperty("ID")] public uint Id { get; set; } + [JsonProperty("StartTime")] public string StartTime { get; set; } = ""; + [JsonProperty("EndTime")] public string EndTime { get; set; } = ""; + [JsonProperty("EnterStartTime")] public string EnterStartTime { get; set; } = ""; + [JsonProperty("CloseEndTime")] public string CloseEndTime { get; set; } = ""; + [JsonProperty("Condition")] public string Condition { get; set; } = ""; + + public override uint GetId() => Id; + + public override void Loaded() + { + GameData.DlcActivityData[Id] = this; + } +} diff --git a/Common/Data/GameData.cs b/Common/Data/GameData.cs index 0f6ea08..52f6c93 100644 --- a/Common/Data/GameData.cs +++ b/Common/Data/GameData.cs @@ -59,6 +59,7 @@ public static class GameData public static Dictionary FishingFoodData { get; private set; } = []; public static Dictionary VirCaptureTowerData { get; private set; } = []; public static Dictionary DreamCardActivityData { get; private set; } = []; + public static Dictionary DlcActivityData { get; private set; } = []; } public static class GameResourceTemplateId diff --git a/GameServer/Server/CallGS/Handlers/Activity/DLCLogic_CheckOpenAct.cs b/GameServer/Server/CallGS/Handlers/Activity/DLCLogic_CheckOpenAct.cs new file mode 100644 index 0000000..0e59d46 --- /dev/null +++ b/GameServer/Server/CallGS/Handlers/Activity/DLCLogic_CheckOpenAct.cs @@ -0,0 +1,112 @@ +using MikuSB.Data; +using MikuSB.Data.Excel; +using MikuSB.Database.Player; +using MikuSB.GameServer.Game.Player; +using MikuSB.Proto; +using System.Globalization; +using System.Text.Json.Nodes; + +namespace MikuSB.GameServer.Server.CallGS.Handlers.Activity; + +[CallGSApi("DLCLogic_CheckOpenAct")] +public class DLCLogic_CheckOpenAct : ICallGSHandler +{ + private const uint GroupId = 15; + private const uint ActIdSid = 1; + + public async Task Handle(Connection connection, string param, ushort seqNo) + { + var now = DateTime.Now; + var act = ResolveCurrent(GameData.DlcActivityData.Values, now); + if (act == null) + { + await CallGSRouter.SendScript(connection, "DLCLogic_CheckOpenAct", "{\"bOpen\":false}"); + return; + } + + var player = connection.Player!; + var sync = new NtfSyncPlayer(); + SetAttr(player, ActIdSid, act.Id, sync); + + var response = new JsonObject + { + ["bOpen"] = true, + ["nId"] = act.Id, + ["nStartTime"] = ToUnixSeconds(ParseConfigTime(act.EnterStartTime)), + ["nEndTime"] = ToUnixSeconds(ParseConfigTime(act.CloseEndTime)) + }; + + await CallGSRouter.SendScript(connection, "DLCLogic_CheckOpenAct", response.ToJsonString(), sync); + } + + private static DlcActivityExcel? ResolveCurrent(IEnumerable configs, DateTime now) + { + var parsed = configs + .Select(x => new + { + Config = x, + Start = ParseConfigTime(x.EnterStartTime), + End = ParseConfigTime(x.CloseEndTime) + }) + .Where(x => x.Start.HasValue && x.End.HasValue) + .OrderBy(x => x.Start) + .ToList(); + + var current = parsed.FirstOrDefault(x => x.Start <= now && now < x.End); + if (current != null) + return current.Config; + + var latestStarted = parsed.LastOrDefault(x => x.Start <= now && x.End > x.Start); + return latestStarted?.Config; + } + + private static DateTime? ParseConfigTime(string? raw) + { + if (string.IsNullOrWhiteSpace(raw)) + return null; + + var normalized = raw.Trim().Trim('[', ']'); + if (normalized.Length != 12) + return null; + + return DateTime.TryParseExact( + normalized, + "yyyyMMddHHmm", + CultureInfo.InvariantCulture, + DateTimeStyles.None, + out var value) + ? value + : null; + } + + private static long ToUnixSeconds(DateTime? value) + { + return value.HasValue ? new DateTimeOffset(value.Value).ToUnixTimeSeconds() : 0L; + } + + private static void SetAttr(PlayerInstance player, uint sid, uint value, NtfSyncPlayer sync) + { + var attr = GetOrCreateAttr(player, sid); + if (attr.Val != value) + { + attr.Val = value; + sync.Custom[player.ToPackedAttrKey(GroupId, sid)] = value; + sync.Custom[player.ToShiftedAttrKey(GroupId, sid)] = value; + } + } + + private static PlayerAttr GetOrCreateAttr(PlayerInstance player, uint sid) + { + var attr = player.Data.Attrs.FirstOrDefault(x => x.Gid == GroupId && x.Sid == sid); + if (attr != null) + return attr; + + attr = new PlayerAttr + { + Gid = GroupId, + Sid = sid + }; + player.Data.Attrs.Add(attr); + return attr; + } +}