From 85df98c0ae6ebc5f780f4c89d23034058cf72210 Mon Sep 17 00:00:00 2001 From: Kei-Luna Date: Wed, 20 May 2026 09:50:28 +0900 Subject: [PATCH] Added functionality to Rogue3D --- .../Rogue3D/Rogue3D_EnterSeasonLevel.cs | 71 +++++++++++++++++++ .../Rogue3D/Rogue3D_SelectSeasonTalent.cs | 47 ++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 GameServer/Server/CallGS/Handlers/Rogue3D/Rogue3D_EnterSeasonLevel.cs create mode 100644 GameServer/Server/CallGS/Handlers/Rogue3D/Rogue3D_SelectSeasonTalent.cs diff --git a/GameServer/Server/CallGS/Handlers/Rogue3D/Rogue3D_EnterSeasonLevel.cs b/GameServer/Server/CallGS/Handlers/Rogue3D/Rogue3D_EnterSeasonLevel.cs new file mode 100644 index 0000000..bac30d9 --- /dev/null +++ b/GameServer/Server/CallGS/Handlers/Rogue3D/Rogue3D_EnterSeasonLevel.cs @@ -0,0 +1,71 @@ +using MikuSB.Data; +using MikuSB.Database.Player; +using MikuSB.GameServer.Game.Player; +using MikuSB.Proto; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace MikuSB.GameServer.Server.CallGS.Handlers.Rogue3D; + +// Enters the Rogue3D season level. Returns a random seed used by the client for map generation. +// Persists SeasonGameplayId (sid=1006) and SeasonEnterFlag (sid=1008) as player attributes (GroupId=124). +// param: {"nDiffId", "nTeamID", "tbTeam", "tbBuffList", "tbLog"} +// Response: {"nSeed": int} on success, {"sErr": "key"} on failure +[CallGSApi("Rogue3D_EnterSeasonLevel")] +public class Rogue3D_EnterSeasonLevel : ICallGSHandler +{ + private const uint GroupId = 124; + private const uint SeasonGameplayIdSid = 1006; + private const uint SeasonEnterFlagSid = 1008; + private static readonly Random Random = new(); + + public async Task Handle(Connection connection, string param, ushort seqNo) + { + var req = JsonSerializer.Deserialize(param); + if (req == null) + { + await CallGSRouter.SendScript(connection, "Rogue3D_EnterSeasonLevel", "{\"nSeed\":0}"); + return; + } + + if (!GameData.Rogue3DDifficultData.TryGetValue(req.DiffId, out var cfg) || cfg.GameplayGroup.Count == 0) + { + await CallGSRouter.SendScript(connection, "Rogue3D_EnterSeasonLevel", "{\"sErr\":\"rogue3.massage_gameProcessError\"}"); + return; + } + + var player = connection.Player!; + var sync = new NtfSyncPlayer(); + + SetAttr(player, SeasonGameplayIdSid, cfg.GameplayGroup[0], sync); + SetAttr(player, SeasonEnterFlagSid, 1, sync); + + var seed = Random.Next(1, 1_000_000_000); + await CallGSRouter.SendScript(connection, "Rogue3D_EnterSeasonLevel", $"{{\"nSeed\":{seed}}}", sync); + } + + private static void SetAttr(PlayerInstance player, uint sid, uint val, NtfSyncPlayer sync) + { + var attr = player.Data.Attrs.FirstOrDefault(x => x.Gid == GroupId && x.Sid == sid); + if (attr == null) + { + attr = new PlayerAttr { Gid = GroupId, Sid = sid }; + player.Data.Attrs.Add(attr); + } + + if (attr.Val == val) + { + return; + } + + attr.Val = val; + sync.Custom[player.ToPackedAttrKey(GroupId, sid)] = val; + sync.Custom[player.ToShiftedAttrKey(GroupId, sid)] = val; + } +} + +internal sealed class EnterSeasonLevelParam +{ + [JsonPropertyName("nDiffId")] + public uint DiffId { get; set; } +} diff --git a/GameServer/Server/CallGS/Handlers/Rogue3D/Rogue3D_SelectSeasonTalent.cs b/GameServer/Server/CallGS/Handlers/Rogue3D/Rogue3D_SelectSeasonTalent.cs new file mode 100644 index 0000000..26be649 --- /dev/null +++ b/GameServer/Server/CallGS/Handlers/Rogue3D/Rogue3D_SelectSeasonTalent.cs @@ -0,0 +1,47 @@ +using MikuSB.Database.Player; +using MikuSB.Proto; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace MikuSB.GameServer.Server.CallGS.Handlers.Rogue3D; + +// Selects the Rogue3D season talent and persists it as player attribute (GroupId=124, TalentId=1007). +// param: {"nTalentId": int} +// Response: {} on success, {"sErr": "key"} on failure +[CallGSApi("Rogue3D_SelectSeasonTalent")] +public class Rogue3D_SelectSeasonTalent : ICallGSHandler +{ + private const uint GroupId = 124; + private const uint SeasonTalentIdSid = 1007; + + public async Task Handle(Connection connection, string param, ushort seqNo) + { + var req = JsonSerializer.Deserialize(param); + if (req == null) + { + await CallGSRouter.SendScript(connection, "Rogue3D_SelectSeasonTalent", "{}"); + return; + } + + var player = connection.Player!; + var attr = player.Data.Attrs.FirstOrDefault(x => x.Gid == GroupId && x.Sid == SeasonTalentIdSid); + if (attr == null) + { + attr = new PlayerAttr { Gid = GroupId, Sid = SeasonTalentIdSid }; + player.Data.Attrs.Add(attr); + } + attr.Val = req.TalentId; + + var sync = new NtfSyncPlayer(); + sync.Custom[player.ToPackedAttrKey(GroupId, SeasonTalentIdSid)] = attr.Val; + sync.Custom[player.ToShiftedAttrKey(GroupId, SeasonTalentIdSid)] = attr.Val; + + await CallGSRouter.SendScript(connection, "Rogue3D_SelectSeasonTalent", "{}", sync); + } +} + +internal sealed class SelectSeasonTalentParam +{ + [JsonPropertyName("nTalentId")] + public uint TalentId { get; set; } +}