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

124 lines
6.2 KiB
Go
Raw Permalink Normal View History

package routers
import (
"context"
"sync"
)
var _ = sync.Mutex{}
var _ = context.Background
//
// T2-32 路人骇入(Seymour 骇入路人的手机看信息)—— 2026-09-24 接入。
// 整条链路客户端早就写好了,服务端只缺两样东西(取证见
// modules/黑客大停电与广告牌坐标.md §7.8):
// 1. 从来没推过 SyncUnitHackableState(68941159) ⇒ C# 的 HackManager.hackUnitTarget
// 永远是 nil ⇒ GadgetManager.RefreshHackInteract 不会把路人装进
// HackInteractList ⇒ 路人身上根本没有骇入按钮;
// 2. 三个 C2S(AskHackingNpc 67070057 / AskHackingNpcPress 67747341 /
// ReportBeHacked 67093669)没进白名单 ⇒ 就算玩家按了也是静默落兜底,
// 而前两个是 Invoke,不 ack 会让客户端 await 卡死。
// 两者完全自洽:logs/unknown-methods.log 里 AskHackingNpc 命中 0 次。
// ⛑️ 本文件不实现"看信息"的内容:面板(HackerInfoPanelStore.lua:267 /
// HintInfosHudStore.lua:2132)读的是客户端手里的 NPC 数据,服务端只负责放行。
//
//
// 把一个 NPC 标记为可骇 / 取消标记。
// 与载具那套(SyncVehicleHackableState + SyncVehicleBrokenCollision)对齐:
// 只在状态翻转时发,重复发同一个值没有意义(C# 侧就是个集合/标志位)。
//
func GameRouter_HackNpc_PublishNpcHackableAsync(ctx context.Context, session *GameSession, unitId uint64, hackable bool, token context.Context) any {
// Router implementation for GameRouter_HackNpc_PublishNpcHackableAsync
var zero any; return zero
}
//
// NPC 出场时调一次。 gate:Gameplay.HackNpc.MarkSpawnedNpcs。
// 放在 SendCivilianAsync / SendAmbientCrowdPedAsync 的尾部 ——
// 必须先有单位(StaticNpcAddData / CrowdAdd + ManagedLogicAgent),
// C# 才能在 SceneDataMgr.GetUnit(unitId) 里找到它。
//
func GameRouter_HackNpc_MarkNpcHackableOnSpawnAsync(ctx context.Context, session *GameSession, unitId uint64, channel any, token context.Context, skipPhone bool) any {
// Router implementation for GameRouter_HackNpc_MarkNpcHackableOnSpawnAsync
var zero any; return zero
}
//
// ⭐ 给 NPC 发一部手机并让他正在玩/正在打 —— 骇入面板下面那排按钮就是从这儿来的。
// 证据链(2026-09-24,用户回报"骇入路人后只能看名字,不像汽车/售货机有选项"):
// 1. HackerInfoPanelStore.lua:119(反编译,比较符极性反转)路人分支走
// self.textIds = HackManager:GetUnitHackBtns(data.unit),
// btnNum = min(#textIds,3) ⇒ 列表为空就是"只剩标题(名字)";
// 2. GetUnitHackBtns 遍历六个 NpcHackSkill,逐个问 CanUse(unit, tracker, debug);
// 3. PhoneUsageSkillBase.CanUseInternal 看的是
// BelongingBelongingUsageConfig.HackType,全三条非 0 的 usage 都要求持有手机
// BelongingSceneItem = 80003481;
// 4. 我们下发的 crowd 行人没有任何 belongings,而 static NPC 用的是 POI 的 usage
// (18/86/93/237/238/241 —— HackType 全 0)⇒ 一条都对不上 ⇒ 零按钮。
// 与 GameRouter.Civilians.cs / GameRouter.DonorNpc.cs 给 NPC 递道具的路径完全同包同结构,
// 只是把"POI 决定拿什么"换成"一律给手机"。
//
func GameRouter_HackNpc_PublishNpcPhoneAsync(ctx context.Context, session *GameSession, unitId uint64, channel any, token context.Context) any {
// Router implementation for GameRouter_HackNpc_PublishNpcPhoneAsync
var zero any; return zero
}
//
// 敌人版本的手持道具 —— 与 PublishNpcPhoneAsync 同一套 wire
// (SyncAgentBelongings → SyncAgentUseBelongingChanged),只是配置源换成
// gameplay.combat.enemies,调敌人手里的东西时不会动到全城路人。
// 为什么单独一份:两者的生命周期完全不同。路人的手机要在每次 SendCivilianAsync
// / crowd ped 出场时按 MaxPhonedNpcs 计数限量推;敌人是 GM 面板一次性指令,
// 数量本来就很少,再套那层保险丝只会让第 N 个敌人之后突然不带东西,很难解释。
// ⛑ 调用时机必须在单位已经在客户端落地之后(SyncManagedLogicAgent +
// SyncRaidBattleUnitAgent 都已发出),否则 SceneDataMgr.GetUnit(uid)
// 查不到这个单位,两个包都会被静默丢掉。
//
func GameRouter_HackNpc_PublishEnemyPropAsync(ctx context.Context, session *GameSession, unitId uint64, templateId uint32, token context.Context) any {
// Router implementation for GameRouter_HackNpc_PublishEnemyPropAsync
var zero any; return zero
}
//
// AskHackingNpc(67070057) — 玩家点下了路人骇入按钮。
// ⛑️ 必须 HandlerPacketKind.Both:客户端走的是 Invoke
// (ClientToGameSceneDelegate.lua:489),但按 AskControlAgent 那次的教训,
// 同族 RPC 会有 NOTIFY 变体,只注册 Invoke 就是静默丢包。
// 返回体是空 reader ⇒ ReturnEmptyOkAsync(对 NOTIFY 是 no-op)。
//
func GameRouter_HackNpc_OnAskHackingNpc(ctx context.Context, conn any, msg any) any {
// Router implementation for GameRouter_HackNpc_OnAskHackingNpc
var zero any; return zero
}
//
// AskHackingNpcPress(67747341) — 长按骇入的那一下(GadgetManager.lua:1851)。
// 同样是 Invoke + 空 reader。
//
func GameRouter_HackNpc_OnAskHackingNpcPress(ctx context.Context, conn any, msg any) any {
// Router implementation for GameRouter_HackNpc_OnAskHackingNpcPress
var zero any; return zero
}
//
// ReportBeHacked(67093669) — NOTIFY,客户端告知"这些单位被骇了"。
// 纯记账:没有 ack,也没有需要回推的包(面板内容在客户端)。
//
func GameRouter_HackNpc_OnReportBeHacked(ctx context.Context, conn any, msg any) any {
// Router implementation for GameRouter_HackNpc_OnReportBeHacked
var zero any; return zero
}
//
// NPC 的来路。手机要不要发,两条通道的政策不同(HackNpcSettings 里各有一个开关):
// crowd 行人本来一件 belongings 都没有,static NPC 则由 POI 决定拿什么在做什么。
//
type HackNpcChannel int32
const (
// crowd 行人(SendAmbientCrowdPedAsync,SyncAetherAICrowdAdd)。
HackNpcChannel_Crowd HackNpcChannel = iota
// 服务端自己生成的 static NPC(SendCivilianAsync,SyncAetherAIStaticNpcAddData)。
HackNpcChannel_Static
)