This repository has been archived on 2026-10-31. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files

119 lines
4.9 KiB
C#
Raw Permalink Normal View History

using System.Buffers.Binary;
using Ananta.SDK.Rpc;
using Ananta.Server.Protocol.Client4229938;
using GameMethods = Ananta.Server.RpcTypes.Client4229938.Methods.Game;
using SceneMethods = Ananta.Server.RpcTypes.Client4229938.Methods.GameScene;
namespace Ananta.Server.Handlers.Game;
/// <summary>
/// 迷雾 / 探索 POI / Aether 氛围层 —— <c>SyncEnterFogMapPoiId</c>(63491307)、
/// <c>GmUnlockAllFogMap</c>(65914419)、<c>GmSetAmbianceEnabled</c>(69166506)、
/// <c>GmGetAmbianceEnabled</c>(69384152)。
///
/// 移植自捐赠端 DremkaPS(2026-09-24)。
///
/// ★★ 这一组是<b>抓包筛出来的</b>,不是照单全收。捐赠端比本服多的 handler 一共有 66 个,
/// 拿 16.5 万行 <c>unknown-methods.log</c> 逐个数下来,<b>只有 6 个真的被客户端发过</b>:
/// <c>SyncEnterFogMapPoiId</c> 49 次(活跃到 09-23)、<c>GmUnlockAllFogMap</c> 5 次、
/// <c>ForceSubmitTask</c> 5 次、<c>GmSwitchSpiritHere</c> 3 次、<c>GmSubmitEvent</c> 2 次、
/// <c>GmGetAmbianceEnabled</c> 2 次。剩下 <b>60 个零次</b>,注册它们只是增加维护面 —— 已剔除。
///
/// 剔除的三条(虽然日志里出现过):
/// · <c>ForceSubmitTask</c> / <c>GmSubmitEvent</c> —— 任务族。本服
/// <c>GameRouter.Tasks.cs</c> 已经四次证明任务面板在 4229938 下渲染不出来
/// (<c>TaskPublishEnabled = false</c>),捐赠端自己也只拿它们记账,搬过来是死代码。
/// · <c>GmSwitchSpiritHere</c> —— 切角色。本服已有 <c>AskSwitchSpirit</c> 这条正规路径,
/// GM 版只是控制台的快捷方式,09-16 之后再没被用过。
///
/// ⛑ <c>GmGetAmbianceEnabled</c> 是 <b>0 字节的 INVOKE</b>:客户端在 await 一个返回值。
/// 不接它,控制台按下去会一直卡到超时(规则 94)。这里回一个 bool。
/// </summary>
internal sealed partial class GameRouter
{
[Handler(MethodId.SyncEnterFogMapPoiId, HandlerPacketKind.Notify)]
private Task EnterFogMapPoiId(Connection conn, UxRpcMessage msg)
{
var poiId = msg.TryGetArgs<GameMethods.SyncEnterFogMapPoiId4229938>(out var args) && args is not null
? args.PoiId
: (msg.Body.Length >= 4 ? BinaryPrimitives.ReadUInt32LittleEndian(msg.Body) : 0u);
if (poiId == 0)
{
conn.Log.Warn($"[FOG] enter-poi without an id bytes={msg.Body.Length}");
return Task.CompletedTask;
}
var state = GetWorldState(msg.Context);
bool fresh;
int total;
lock (state.SyncRoot)
{
fresh = state.FogMapPoiIds.Add(poiId);
total = state.FogMapPoiIds.Count;
}
// 同一个 POI 玩家会反复踏入(抓包里 49 条几乎全是 id=11),所以只在新增时记 Info。
if (fresh)
conn.Log.Info($"[FOG] enter-poi id={poiId} total={total}");
return Task.CompletedTask;
}
[Handler(MethodId.GmUnlockAllFogMap, HandlerPacketKind.Invoke)]
private async Task GmUnlockAllFogMap(Connection conn, UxRpcMessage msg)
{
var unlock = msg.TryGetArgs<GameMethods.GmUnlockAllFogMap4229938>(out var args) && args is not null
? args.Unlock
: (msg.Body.Length > 0 && msg.Body[0] != 0);
var state = GetWorldState(msg.Context);
lock (state.SyncRoot)
state.FogMapAllUnlocked = unlock;
conn.Log.Info($"[FOG] gm-unlock-all unlock={unlock} poi={state.FogMapPoiIds.Count} "
+ $"raid={state.ActiveRaidId} (recorded: pushing SyncSceneFogMapAllUnlock needs the current sceneId, not wired yet)");
await conn.ReturnEmptyOkAsync(msg);
}
[Handler(MethodId.GmSetAmbianceEnabled, HandlerPacketKind.Invoke)]
private async Task GmSetAmbianceEnabled(Connection conn, UxRpcMessage msg)
{
bool enabled;
int type = 0;
if (msg.TryGetArgs<SceneMethods.GmSetAmbianceEnabled>(out var args) && args is not null)
{
enabled = args.Enabled;
type = args.Type;
}
else
{
enabled = msg.Body.Length > 0 && msg.Body[0] != 0;
}
var state = GetWorldState(msg.Context);
lock (state.SyncRoot)
{
state.AmbianceEnabled = enabled;
state.AmbianceType = type;
}
conn.Log.Info($"[GM] ambiance set enabled={enabled} type={type}");
await conn.ReturnEmptyOkAsync(msg);
}
/// <summary>
/// 0 字节 INVOKE —— 必须回一个 bool,否则客户端这次调用会 await 到超时。
/// </summary>
[Handler(MethodId.GmGetAmbianceEnabled, HandlerPacketKind.Invoke)]
private Task GmGetAmbianceEnabled(Connection conn, UxRpcMessage msg)
{
var state = GetWorldState(msg.Context);
bool enabled;
lock (state.SyncRoot)
enabled = state.AmbianceEnabled;
conn.Log.Info($"[GM] ambiance query -> {enabled}");
return conn.ReturnAsync(msg, enabled);
}
}