116 lines
6.5 KiB
C#
116 lines
6.5 KiB
C#
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);
|
||
}
|
||
}
|