diff --git a/GameServer/Server/CallGS/Handlers/Rogue3D/Rogue3D_EnterLevel.cs b/GameServer/Server/CallGS/Handlers/Rogue3D/Rogue3D_EnterLevel.cs new file mode 100644 index 0000000..6111351 --- /dev/null +++ b/GameServer/Server/CallGS/Handlers/Rogue3D/Rogue3D_EnterLevel.cs @@ -0,0 +1,16 @@ +namespace MikuSB.GameServer.Server.CallGS.Handlers.Rogue3D; + +// Enters the Rogue3D level. Returns a random seed used by the client for map generation. +// param: {"nDiffId", "nTeamID", "tbTeam", "tbBuffList", "tbLog"} +// Response: {"nSeed": int} +[CallGSApi("Rogue3D_EnterLevel")] +public class Rogue3D_EnterLevel : ICallGSHandler +{ + private static readonly Random Random = new(); + + public async Task Handle(Connection connection, string param, ushort seqNo) + { + var seed = Random.Next(1, 1_000_000_000); + await CallGSRouter.SendScript(connection, "Rogue3D_EnterLevel", $"{{\"nSeed\":{seed}}}"); + } +} diff --git a/GameServer/Server/CallGS/Handlers/Rogue3D/Rogue3D_SelectDiff.cs b/GameServer/Server/CallGS/Handlers/Rogue3D/Rogue3D_SelectDiff.cs new file mode 100644 index 0000000..ac133c3 --- /dev/null +++ b/GameServer/Server/CallGS/Handlers/Rogue3D/Rogue3D_SelectDiff.cs @@ -0,0 +1,73 @@ +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; + +// Selects the Rogue3D difficulty. +// Persists CurDiff (sid=5) and GameplayId (sid=6) as player attributes (GroupId=124). +// param: {"nDiffId": int} +// Response: {} on success, {"sErr": "key"} on failure +[CallGSApi("Rogue3D_SelectDiff")] +public class Rogue3D_SelectDiff : ICallGSHandler +{ + private const uint GroupId = 124; + private const uint CurDiffSid = 5; + private const uint GameplayIdSid = 6; + + // First gameplay group per difficulty (from server_01_difficult.txt, GameplayGroup column) + private static readonly Dictionary DiffToGameplayGroup = new() + { + { 1, 100 }, + { 2, 200 }, + { 3, 300 }, + { 4, 400 }, + { 100, 811 }, + }; + + public async Task Handle(Connection connection, string param, ushort seqNo) + { + var req = JsonSerializer.Deserialize(param); + if (req == null) + { + await CallGSRouter.SendScript(connection, "Rogue3D_SelectDiff", "{}"); + return; + } + + if (!DiffToGameplayGroup.TryGetValue(req.DiffId, out var gameplayGroup)) + { + await CallGSRouter.SendScript(connection, "Rogue3D_SelectDiff", "{\"sErr\":\"rogue3.massage_gameProcessError\"}"); + return; + } + + var player = connection.Player!; + var sync = new NtfSyncPlayer(); + + SetAttr(player, CurDiffSid, req.DiffId, sync); + SetAttr(player, GameplayIdSid, gameplayGroup, sync); + + await CallGSRouter.SendScript(connection, "Rogue3D_SelectDiff", "{}", 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); + } + attr.Val = val; + sync.Custom[player.ToPackedAttrKey(GroupId, sid)] = val; + sync.Custom[player.ToShiftedAttrKey(GroupId, sid)] = val; + } +} + +internal sealed class SelectDiffParam +{ + [JsonPropertyName("nDiffId")] + public uint DiffId { get; set; } +} diff --git a/GameServer/Server/CallGS/Handlers/Rogue3D/Rogue3D_SelectMode.cs b/GameServer/Server/CallGS/Handlers/Rogue3D/Rogue3D_SelectMode.cs new file mode 100644 index 0000000..508dc52 --- /dev/null +++ b/GameServer/Server/CallGS/Handlers/Rogue3D/Rogue3D_SelectMode.cs @@ -0,0 +1,13 @@ +namespace MikuSB.GameServer.Server.CallGS.Handlers.Rogue3D; + +// Selects the Rogue3D game mode (nModeID: 1=infinity, 2=normal, 3=season). +// param: {"nModeID": int} +// Response: {} on success, {"sErr": "key"} on failure +[CallGSApi("Rogue3D_SelectMode")] +public class Rogue3D_SelectMode : ICallGSHandler +{ + public async Task Handle(Connection connection, string param, ushort seqNo) + { + await CallGSRouter.SendScript(connection, "Rogue3D_SelectMode", "{}"); + } +} diff --git a/GameServer/Server/CallGS/Handlers/Rogue3D/Rogue3D_SelectTalent.cs b/GameServer/Server/CallGS/Handlers/Rogue3D/Rogue3D_SelectTalent.cs new file mode 100644 index 0000000..2e8f84d --- /dev/null +++ b/GameServer/Server/CallGS/Handlers/Rogue3D/Rogue3D_SelectTalent.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 talent and persists it as player attribute (GroupId=124, TalentId=7). +// param: {"nTalentId": int} +// Response: {} on success, {"sErr": "key"} on failure +[CallGSApi("Rogue3D_SelectTalent")] +public class Rogue3D_SelectTalent : ICallGSHandler +{ + private const uint GroupId = 124; + private const uint TalentIdSid = 7; + + public async Task Handle(Connection connection, string param, ushort seqNo) + { + var req = JsonSerializer.Deserialize(param); + if (req == null) + { + await CallGSRouter.SendScript(connection, "Rogue3D_SelectTalent", "{}"); + return; + } + + var player = connection.Player!; + var attr = player.Data.Attrs.FirstOrDefault(x => x.Gid == GroupId && x.Sid == TalentIdSid); + if (attr == null) + { + attr = new PlayerAttr { Gid = GroupId, Sid = TalentIdSid }; + player.Data.Attrs.Add(attr); + } + attr.Val = req.TalentId; + + var sync = new NtfSyncPlayer(); + sync.Custom[player.ToPackedAttrKey(GroupId, TalentIdSid)] = attr.Val; + sync.Custom[player.ToShiftedAttrKey(GroupId, TalentIdSid)] = attr.Val; + + await CallGSRouter.SendScript(connection, "Rogue3D_SelectTalent", "{}", sync); + } +} + +internal sealed class SelectTalentParam +{ + [JsonPropertyName("nTalentId")] + public uint TalentId { get; set; } +}