Files

116 lines
6.5 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Ananta.SDK.Rpc;
using Ananta.Server.Protocol.Client4229938;
namespace Ananta.Server.Handlers.Game;
/// <summary>
/// T2 单发杂项(2026-10-02 自 7k-v0.6 捐赠端移植)。
///
/// <para>★ 这一批的共同点:捐赠端每条背后都有它自己的一套 runtime(Garm 随从账本 /
/// 骇入装置 / 简化配送 runtime / 装置武器),主线<b>没有等价物</b>。
/// 所以这里按「能不能诚实实现」分成两类,逐条在下面写清理由。</para>
///
/// <list type="number">
/// <item><b>只记账的 Notify</b>:<c>AskHackerBetray</c>、<c>SyncTrackGPS</c> ——
/// 客户端只是上报「发生了什么」,本来就没有回包。接住的收益是
/// ① 不再灌 <c>unknown-methods.log</c>;② 日志里能看见玩家真的触发了这些原生动作。
/// 行为零变化(NOTIFY 兜底本来就是接受 + 打日志)。</item>
/// <item><b>明确回绝的 Invoke</b>:<c>AskDestroyGangMember</c>、<c>AskAgentChangeWeaponByTemplateId</c>、
/// <c>AskResetTruckOrderGoods</c> —— 回 <c>error=1</c>。
/// ⛑ 为什么不沿用兜底:<c>DefaultReturnCatalog4229938</c>(478 条)里<b>没有这三个 id</b>
/// ⇒ 兜底 = <c>ReturnEmptyOkAsync</c> = <b>error=0</b> = 告诉客户端「删了 / 换了 / 重置了」,
/// 而我们<b>什么都没做</b>。与 <c>GameRouter.NpcShopTrades.cs</c> 同一条原则
/// (捐赠端原话:"must not fall back to an empty success reply, which would falsely
/// claim a purchase/sale occurred")。
/// 副作用要提前说:客户端可能弹一次失败提示 —— 这比静默假装成功更接近真相。</item>
/// </list>
///
/// <para>⛑ 回滚:把下面 5 个 <c>MethodId.*</c> 从 <c>GameRouter.cs</c> 的
/// <c>Enabled4229938MethodIds</c> 里删掉即可。INVOKE 回到兜底(error=0),
/// NOTIFY 回到 <c>DefaultUnknownNotify4229938</c>(接受 + 打日志)。</para>
/// </summary>
internal sealed partial class GameRouter
{
// ======================================================================================
// ① 纯记账的 Notify
// ======================================================================================
/// <summary>
/// <c>AskHackerBetray</c>(67145924) —— 玩家对已被骇入的单位触发「反水 / 背叛」。
///
/// <para>捐赠端是 <c>ExecuteEnemyHackAsync(session, id, betray: true)</c>,依赖它自己的
/// 骇入 runtime;主线<b>没有这套执行逻辑</b>(主线在 spawn 时下发
/// <c>AgentSyncClientInfo.HackerBetray</c> 标记,并有 <c>ReportBeHacked</c> 记账,
/// 见 <c>GameRouter.HackNpc.cs:290</c>)。所以这里按 <c>ReportBeHacked</c> 同款处理:
/// 只解析 + 打日志,不做状态变更。</para>
///
/// <para>⛑ <c>DefaultReturnCatalog4229938.cs:1542</c> 的注释也把它定性为
/// "Atmosphere-NPC 'rebel' action" ⇒ 属于氛围演出,不是核心玩法。</para>
/// </summary>
[Handler(MethodId.AskHackerBetray, HandlerPacketKind.Both)]
private async Task AskHackerBetray(Connection conn, UxRpcMessage msg)
{
// 载荷是单个 ulong targetId(属"未注册即 void"的一族,见兜底表注释)。
var ok = msg.Body.Length == 8;
conn.Log.Info($"[NPC-HACK] betray-request bytes={msg.Body.Length} "
+ (ok ? $"target={System.Buffers.Binary.BinaryPrimitives.ReadUInt64LittleEndian(msg.Body)}" : "(undecodable)"));
if (msg.IsInvoke)
await conn.ReturnEmptyOkAsync(msg);
}
/// <summary>
/// <c>SyncTrackGPS</c>(63861463) —— 客户端地图里选中「追踪」后上报,用来确认
/// 原生追踪动作<b>真的跑了</b>(捐赠端注释:"it is not a map-pin request")。
/// 只打日志,不回状态。
/// </summary>
[Handler(MethodId.SyncTrackGPS, HandlerPacketKind.Both)]
private async Task SyncTrackGps4229938(Connection conn, UxRpcMessage msg)
{
conn.Log.Info($"[MAP-TRACE] client GPS sync received bytes={msg.Body.Length}");
if (msg.IsInvoke)
await conn.ReturnEmptyOkAsync(msg);
}
// ======================================================================================
// ② 没有等价 runtime ⇒ 明确回绝,不假装成功
// ======================================================================================
/// <summary>
/// <c>AskDestroyGangMember</c>(63555197) —— 移除一个帮派随从。
/// 捐赠端走 <c>RemoveGarmCompanion4229938(ctx, args.templateId)</c>(<c>GarmGang.cs:371</c>),
/// 主线没有 Garm 随从移除通道(随从走 <c>CompanionAssist</c> / <c>FactionInvasion</c> 的
/// 生成路径,没有按 templateId 反查移除的 API)⇒ 回绝。
/// </summary>
[Handler(MethodId.AskDestroyGangMember, HandlerPacketKind.Invoke)]
private Task AskDestroyGangMember4229938(Connection conn, UxRpcMessage msg)
{
conn.Log.Info($"[T2] AskDestroyGangMember bytes={msg.Body.Length} -> rejected(error=1): no Garm companion removal channel");
return conn.ReturnEmptyAsync(msg, 1);
}
/// <summary>
/// <c>AskAgentChangeWeaponByTemplateId</c>(63182186) —— 给骇入装置 / 炮台换武器。
/// 捐赠端走 <c>GameRouter.DeviceWeapons.cs</c> 的 <c>HackerDeviceRuntime</c>
/// (装置模板 + 槽位白名单 + 装备态推送),主线<b>没有 DeviceWeapons</b> ⇒ 回绝。
/// </summary>
[Handler(MethodId.AskAgentChangeWeaponByTemplateId, HandlerPacketKind.Invoke)]
private Task AskAgentChangeWeaponByTemplateId4229938(Connection conn, UxRpcMessage msg)
{
conn.Log.Info($"[T2] AskAgentChangeWeaponByTemplateId bytes={msg.Body.Length} -> rejected(error=1): no device-weapon runtime");
return conn.ReturnEmptyAsync(msg, 1);
}
/// <summary>
/// <c>AskResetTruckOrderGoods</c>(63383400) —— 重置配送货物并重新下发目的地。
/// 捐赠端走它自己的 <c>DeliveryApps</c> runtime(<c>GameRouter.Delivery.cs:318</c>);
/// 主线配送是另一套(UberSim 系列,<c>GameRouter.cs:459-471</c> 那批 truck 接口),
/// 两条 runtime 不通用 ⇒ 回绝而不是瞎推一个目的地。
/// </summary>
[Handler(MethodId.AskResetTruckOrderGoods, HandlerPacketKind.Invoke)]
private Task AskResetTruckOrderGoods4229938(Connection conn, UxRpcMessage msg)
{
conn.Log.Info($"[T2] AskResetTruckOrderGoods bytes={msg.Body.Length} -> rejected(error=1): UberSim delivery has no order-goods reset");
return conn.ReturnEmptyAsync(msg, 1);
}
}