Paradoxes can play(It is still in the experimental stage and contains many bugs.)

This commit is contained in:
Kei-Luna
2026-04-27 13:13:41 +09:00
parent b6ed4bc089
commit 6f5c19976c
4 changed files with 149 additions and 0 deletions

View File

@@ -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}}}");
}
}

View File

@@ -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<uint, uint> 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<SelectDiffParam>(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; }
}

View File

@@ -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", "{}");
}
}

View File

@@ -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<SelectTalentParam>(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; }
}