From 116ea108f9bd026da366b26750d48363e1bc5c1f Mon Sep 17 00:00:00 2001 From: capyb2222 Date: Tue, 8 Sep 2026 17:22:28 -0700 Subject: [PATCH] upd(readme): add a note --- README.md | 4 ++- .../Handlers/LoginHandlers.cs | 2 ++ .../Handlers/MissionHandlers.cs | 30 ++++++++++++++-- .../Handlers/TutorialHandlers.cs | 34 ++++++++++++++++--- 4 files changed, 63 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index fddbe19..f9c9c13 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ -# CapySR +# CapySR - WIP +This server is a Work In Progress and might face multiple rewrites and changes. + A Honkai: Star Rail server reimplementation rewritten in C#. Current version: `CNBETAWin4.5.53` diff --git a/src/CapySR.GameServer/Handlers/LoginHandlers.cs b/src/CapySR.GameServer/Handlers/LoginHandlers.cs index 7f1f921..f819236 100644 --- a/src/CapySR.GameServer/Handlers/LoginHandlers.cs +++ b/src/CapySR.GameServer/Handlers/LoginHandlers.cs @@ -60,6 +60,8 @@ public static class LoginHandlers IsGenderSet = true, Gender = (uint)session.Player.Gender, CurDay = 1, + // PlayerModule dereferences this one without checking + PlayerSettingInfo = new PlayerSettingInfo(), }); public static Task OnHeartBeat(PlayerSession session, PlayerHeartBeatCsReq request) => diff --git a/src/CapySR.GameServer/Handlers/MissionHandlers.cs b/src/CapySR.GameServer/Handlers/MissionHandlers.cs index bc18700..c4413a3 100644 --- a/src/CapySR.GameServer/Handlers/MissionHandlers.cs +++ b/src/CapySR.GameServer/Handlers/MissionHandlers.cs @@ -29,6 +29,16 @@ public static class MissionHandlers response.CurversionFinishedMainMissionIdList.Add(id); } + // same story as GetMainMissionCustomValue: the ids asked about need a row each + foreach (var id in request.MainMissionIdList) + { + response.MainMissionMcvList.Add(new MainMissionCustomValue + { + MainMissionId = id, + CustomValueList = new ONHKODAFEMH(), + }); + } + session.Logger.LogInformation( "missions: {Sub} sub finished, {Main} main finished", response.SubMissionStatusList.Count, response.FinishedMainMissionIdList.Count); @@ -36,8 +46,24 @@ public static class MissionHandlers return session.SendAsync(response); } - public static Task OnGetMainMissionCustomValue(PlayerSession session, GetMainMissionCustomValueCsReq request) => - session.SendAsync(new GetMainMissionCustomValueScRsp { Retcode = 0 }); + // an entry has to come back for every id asked about. the client indexes the result by + // mission id while it activates the map's hoyo groups, and a miss throws inside + // AdventureModule.EnterMap - the map never finishes entering and the load screen stays up. + public static Task OnGetMainMissionCustomValue(PlayerSession session, GetMainMissionCustomValueCsReq request) + { + var response = new GetMainMissionCustomValueScRsp { Retcode = 0 }; + + foreach (var id in request.MainMissionIdList) + { + response.MainMissionList.Add(new MainMission + { + Id = id, + Status = MissionStatus.MissionFinish, + }); + } + + return session.SendAsync(response); + } // report every tutorial already finished. an empty list makes the client try to unlock // them one at a time, forever, and it never leaves the loading screen. diff --git a/src/CapySR.GameServer/Handlers/TutorialHandlers.cs b/src/CapySR.GameServer/Handlers/TutorialHandlers.cs index bea1799..5e8e01b 100644 --- a/src/CapySR.GameServer/Handlers/TutorialHandlers.cs +++ b/src/CapySR.GameServer/Handlers/TutorialHandlers.cs @@ -7,17 +7,43 @@ namespace CapySR.GameServer.Handlers; [Handlers] public static class TutorialHandlers { + // the client reads rsp.Tutorial / rsp.TutorialGuide without a nil check, so leaving + // them unset throws in TutorialModule.lua and the load never gets past the loading + // screen. echo the id back and call it finished, like the rest of the tutorial state. public static Task OnUnlockTutorial(PlayerSession session, UnlockTutorialCsReq request) => - session.SendAsync(new UnlockTutorialScRsp { Retcode = 0 }); + session.SendAsync(new UnlockTutorialScRsp + { + Retcode = 0, + Tutorial = Tutorial(request.HPIMDINCCNN), + }); public static Task OnFinishTutorial(PlayerSession session, FinishTutorialCsReq request) => - session.SendAsync(new FinishTutorialScRsp { Retcode = 0 }); + session.SendAsync(new FinishTutorialScRsp + { + Retcode = 0, + Tutorial = Tutorial(request.TutorialId), + }); public static Task OnUnlockTutorialGuide(PlayerSession session, UnlockTutorialGuideCsReq request) => - session.SendAsync(new UnlockTutorialGuideScRsp { Retcode = 0 }); + session.SendAsync(new UnlockTutorialGuideScRsp + { + Retcode = 0, + TutorialGuide = Guide(request.GroupId, request.Type), + }); public static Task OnFinishTutorialGuide(PlayerSession session, FinishTutorialGuideCsReq request) => - session.SendAsync(new FinishTutorialGuideScRsp { Retcode = 0 }); + session.SendAsync(new FinishTutorialGuideScRsp + { + Retcode = 0, + Reward = new ItemList(), + TutorialGuide = Guide(request.GroupId, request.Type), + }); + + private static Tutorial Tutorial(uint id) => + new() { Id = id, Status = TutorialStatus.TutorialFinish }; + + private static TutorialGuide Guide(uint groupId, TutorialGuideType type) => + new() { Id = groupId, Type = type, Status = TutorialStatus.TutorialFinish }; public static Task OnSetClientPaused(PlayerSession session, SetClientPausedCsReq request) => session.SendAsync(new SetClientPausedScRsp { Retcode = 0, Paused = request.Paused });