package routers import ( "context" "sync" ) var _ = sync.Mutex{} var _ = context.Background // // 搜打撤(ExtractionShooter,本季「不要抬头!」)的服务端实现。 // 移植自捐赠端 handoff AI_HANDOFF不要抬头2.md(第二版),只取第一轮范围: // ① 进图 / 退图 ② 容器搜索与刷物 ③ 背包搬运 / 丢弃 / 锁定 / 排序 / 拆分 / 扩容 / 入仓 // 不做武器实体化(轮盘 Tab 切枪)—— 那要 SyncSpiritWeaponDetail 整表,是第二轮。 // 三条先读再加代码: // - ⛑️ [Handler] ≠ 已注册:不写进 GameRouter.cs 的 // Enabled4229938MethodIds 就是空注册 —— 请求不报错,只有一行 // unimplemented ... typed-default void 0b,且 unknown-methods.log 里反而没有。 // - ⛑️ 请求-应答型 RPC 必须回等价结构:midToReturnMessageReader[mid] 有 reader 的 // (典型是 SearchContainer/67410186,要求 ReadComplex(Reader[530])),回 EmptyOk 就是用 nil // 覆盖客户端本地那份数据 —— 容器曾经就这么坏掉。 // - ⛑️ 容器 carrying 的实例 id 是客户端给的(8 字节),服务端按它确定性选容器形体; // 所以同一实例在这一局里怎么搜都一致,换局才会重洗。 // // ---------------------------------------------------------------- helpers func GameRouter_Extraction_ExtractionCfg(ctx context.Context, ) any { // Router implementation for GameRouter_Extraction_ExtractionCfg var zero any; return zero } // 这个 raid 是不是搜打撤图。表里没有 raid↔图外键 ⇒ 用配置里的 raid 名单。 func GameRouter_Extraction_IsExtractionRaid(ctx context.Context, raidId uint32) bool { // Router implementation for GameRouter_Extraction_IsExtractionRaid return true } func GameRouter_Extraction_ExtractionStateOf(ctx context.Context, session *GameSession) any { // Router implementation for GameRouter_Extraction_ExtractionStateOf var zero any; return zero } // // 首次用到时建包。为了避免 登录 flush 前就把包柜塞满,这里只做一次。 // func GameRouter_Extraction_EnsureExtractionSeeded(ctx context.Context, session *GameSession) any { // Router implementation for GameRouter_Extraction_EnsureExtractionSeeded var zero any; return zero } func GameRouter_Extraction_NowSeconds(ctx context.Context, ) uint32 { // Router implementation for GameRouter_Extraction_NowSeconds return 0 } // ---------------------------------------------------------------- wire builders // ClearBag 逐件 SetItemInfo 的整包重推 —— 只改了一格也要整包,客户端没有单删。 func GameRouter_Extraction_PushBagAsync(ctx context.Context, session *GameSession, bag any, phase string) any { // Router implementation for GameRouter_Extraction_PushBagAsync var zero any; return zero } func GameRouter_Extraction_PushBagCapacityAsync(ctx context.Context, session *GameSession, bag any, phase string) any { // Router implementation for GameRouter_Extraction_PushBagCapacityAsync var zero any; return zero } // =============================================================== handlers // // 搜索容器(67410186,Invoke)。 // ⛑ 这条必须回真正的包体:midToReturnMessageReader[67410186] 要求 // ReadComplex(Reader[530]),回 EmptyOk 会拿 nil 覆盖客户端本地那份 ContainerInfo。 // 回完之后再补一条 SyncExtractionShooterContainerInfo(68820459) 走推送路径, // 两条同源同一个 BuildContainerInfo。 // func GameRouter_Extraction_OnAskExtractionShooterSearchContainer(ctx context.Context, conn any, msg any) any { // Router implementation for GameRouter_Extraction_OnAskExtractionShooterSearchContainer var zero any; return zero } // // 容器读条的收尾:seconds 秒后把这个 pid 的时间戳翻成过去,再推同一份容器数据。 // ⛑️ seconds 必须 > 0(取整箱最长 SearchTime)—— 传 0 会立刻揭晓,读条动画播不出来。 // 这是一次性的延时推,不是循环,但仍然要过 GameRouter.IsBackgroundPushPaused 门控 // (硬规则 37):等这几秒里客户端可能已经挂起,那时推等于往不消费的 TCP 里灌包。 // func GameRouter_Extraction_RevealContainerAfterAsync(ctx context.Context, session *GameSession, owner any, instanceId uint64, pid uint64, seconds int32, phase string) any { // Router implementation for GameRouter_Extraction_RevealContainerAfterAsync var zero any; return zero } func GameRouter_Extraction_AnswerEmptyContainerAsync(ctx context.Context, conn any, msg any, instanceId uint64) any { // Router implementation for GameRouter_Extraction_AnswerEmptyContainerAsync var zero any; return zero } // // 结束搜索(67701506)。客户端读条走完自己发的收尾。 // ⛑️ 不能只 ack:这一条是「时间戳该翻回过去了」的信号,服务端必须真的 // ExtractionShooterRuntime4229938.TryRevealContainer 再补推一帧, // 否则客户端手上那份还是未来时间戳 ⇒ 物品不显示。 // (旧实现在这里写的是「服务端无状态可清」,是错的 —— 状态就是那个时间戳。) // func GameRouter_Extraction_OnAskExtractionShooterEndSearchContainer(ctx context.Context, conn any, msg any) any { // Router implementation for GameRouter_Extraction_OnAskExtractionShooterEndSearchContainer var zero any; return zero } // // 六合一搬运(63749738,25B):装备 / 卸下 / 放入安全箱 / 携带 / 放回仓库 / 旋转 // 全走这一条,区别只是 destBag。修一条等于修全部。 // func GameRouter_Extraction_OnAskExtractionShooterShiftItem(ctx context.Context, conn any, msg any) any { // Router implementation for GameRouter_Extraction_OnAskExtractionShooterShiftItem var zero any; return zero } func GameRouter_Extraction_OnAskExtractionShooterRemoveItem(ctx context.Context, conn any, msg any) any { // Router implementation for GameRouter_Extraction_OnAskExtractionShooterRemoveItem var zero any; return zero } func GameRouter_Extraction_OnAskExtractionShooterLockItem(ctx context.Context, conn any, msg any) any { // Router implementation for GameRouter_Extraction_OnAskExtractionShooterLockItem var zero any; return zero } func GameRouter_Extraction_OnAskExtractionShooterSortBag(ctx context.Context, conn any, msg any) any { // Router implementation for GameRouter_Extraction_OnAskExtractionShooterSortBag var zero any; return zero } func GameRouter_Extraction_OnAskExtractionShooterSplitItem(ctx context.Context, conn any, msg any) any { // Router implementation for GameRouter_Extraction_OnAskExtractionShooterSplitItem var zero any; return zero } // // 扩容(63115121,4B)。唯一的扩容入口 —— 客户端没有"直接换包"请求。 // Type=1 给目标包加一行 ⇒ 要回 ChangeBagCapacity;Type=2 解锁新仓库。 // func GameRouter_Extraction_OnAskExtractionShooterBagExpansion(ctx context.Context, conn any, msg any) any { // Router implementation for GameRouter_Extraction_OnAskExtractionShooterBagExpansion var zero any; return zero } func GameRouter_Extraction_OnAskExtractionShooterTransferAllToStash(ctx context.Context, conn any, msg any) any { // Router implementation for GameRouter_Extraction_OnAskExtractionShooterTransferAllToStash var zero any; return zero } // 全包整理(63009939,list7bit<u32>)。逐包重排后各自整包重推。 func GameRouter_Extraction_OnAskExtractionShooterSortBags(ctx context.Context, conn any, msg any) any { // Router implementation for GameRouter_Extraction_OnAskExtractionShooterSortBags var zero any; return zero } // 容器 ↔ 背包 / 槽位的六条搬运。 // // ⛑️ 第一版这里的字段全是「按最可能的布局猜」的,实机一跑全错(捐赠端 §14.8/§14.10 用 C2S // 抓包纠正):非槽位那两条是 (container, fromX, fromY, destBag/srcBag, toX, toY, isRotated), // 槽位那两条是 (container…, slotBag, slotIndex) / (srcBag, slotIndex, container…)。 // 猜错的后果不是报错,而是 TryGetArgs 静默返回 false ⇒ 处理器什么也不做("点了没反应")。 // ⇒ 现在一律走 §8.14 的 ExtractionRequests 契约,并且解析失败要打出来(见 TryArgs)。 func GameRouter_Extraction_OnAskExtractionShooterShiftContainerItemToBag(ctx context.Context, conn any, msg any) any { // Router implementation for GameRouter_Extraction_OnAskExtractionShooterShiftContainerItemToBag var zero any; return zero } func GameRouter_Extraction_OnAskExtractionShooterShiftContainerItemToSlot(ctx context.Context, conn any, msg any) any { // Router implementation for GameRouter_Extraction_OnAskExtractionShooterShiftContainerItemToSlot var zero any; return zero } func GameRouter_Extraction_OnAskExtractionShooterBagItemToContainer(ctx context.Context, conn any, msg any) any { // Router implementation for GameRouter_Extraction_OnAskExtractionShooterBagItemToContainer var zero any; return zero } func GameRouter_Extraction_OnAskExtractionShooterSlotItemToContainer(ctx context.Context, conn any, msg any) any { // Router implementation for GameRouter_Extraction_OnAskExtractionShooterSlotItemToContainer var zero any; return zero } func GameRouter_Extraction_RunTakeAsync(ctx context.Context, conn any, msg any, container uint64, fromX uint32, fromY uint32, destBag uint32, toX uint32, toY uint32, isRotated bool, phase string) any { // Router implementation for GameRouter_Extraction_RunTakeAsync var zero any; return zero } func GameRouter_Extraction_RunPutAsync(ctx context.Context, conn any, msg any, srcBag uint32, fromX uint32, fromY uint32, container uint64, toX uint32, toY uint32, isRotated bool, phase string) any { // Router implementation for GameRouter_Extraction_RunPutAsync var zero any; return zero } func GameRouter_Extraction_RunMoveAsync(ctx context.Context, conn any, msg any, container uint64, fromX uint32, fromY uint32, toX uint32, toY uint32, isRotated bool, phase string) any { // Router implementation for GameRouter_Extraction_RunMoveAsync var zero any; return zero } // // TryGetArgs 的替代品 —— 它把异常 catch 掉并返回 false(见 UxRpcMessage), // 是搜打撤最大的 bug 隐身衣:契约字段数 / 顺序 / Inline 写错的表现全都是 // 「处理器静默什么都不做」,日志里连一个字都没有(§14.8 三连故障的真根因)。 // 这里失败时把契约名 + 字节数 + 原始 hex 全部打出来,拿 packets-latest.log // 里的 C2S INVOKE 对照一眼就知道差几个字段。 // func GameRouter_Extraction_TryArgs(ctx context.Context, conn any, msg any, req any) bool { // Router implementation for GameRouter_Extraction_TryArgs return true } func GameRouter_Extraction_PushContainerAsync(ctx context.Context, session *GameSession, owner any, instanceId uint64, phase string) any { // Router implementation for GameRouter_Extraction_PushContainerAsync var zero any; return zero } // 容器内挪位 / 原地旋转(67007990)—— 现在真的挪。 func GameRouter_Extraction_OnAskExtractionShooterShiftContainerItem(ctx context.Context, conn any, msg any) any { // Router implementation for GameRouter_Extraction_OnAskExtractionShooterShiftContainerItem var zero any; return zero } // 容器内删除(67825663)—— 现在真的删。 func GameRouter_Extraction_OnAskExtractionShooterRemoveContainerItem(ctx context.Context, conn any, msg any) any { // Router implementation for GameRouter_Extraction_OnAskExtractionShooterRemoveContainerItem var zero any; return zero } // 容器内堆叠拆分(67597775,25B):u32 bag + u64 container + u32 x/y + u32 count + bool。 func GameRouter_Extraction_OnAskExtractionShooterRaidSplitItem(ctx context.Context, conn any, msg any) any { // Router implementation for GameRouter_Extraction_OnAskExtractionShooterRaidSplitItem var zero any; return zero } // ------------------------------------------------------------- enter / exit // // 退出(67504722)。 // ⛑ 等待房 / 主城的点也会发这条请求 ⇒ 必须先用 IsExtractionRaid 守卫, // 否则玩家在主城点个按钮就被扔回主城。 // func GameRouter_Extraction_OnAskQuitExtractionShooter(ctx context.Context, conn any, msg any) any { // Router implementation for GameRouter_Extraction_OnAskQuitExtractionShooter var zero any; return zero } // // 退图:结算 → 清局 → 扔回主城。 // func GameRouter_Extraction_ExitExtractionAsync(ctx context.Context, session *GameSession, state any) any { // Router implementation for GameRouter_Extraction_ExitExtractionAsync var zero any; return zero } // // 进图后补齐玩法侧的包结构:SyncPlayerEnterExtractionShooter(64811826) 空体 + // 各包真实容量。 // 空体是必须的 —— 它是客户端把 UI 从标题切到背包 UI 的信号之一;缺它会出现 // "进得去、但整个 HUD 不认自己在副本里"。 // func GameRouter_Extraction_PushExtractionEnterAsync(ctx context.Context, session *GameSession, state any) any { // Router implementation for GameRouter_Extraction_PushExtractionEnterAsync var zero any; return zero } // ---------------------------------------------------------------- utilities // // 轮盘 bag 被改动之后的收尾:把「物品存储」的变动同步成「实体化武器」的变动。 // 搜打撤里这两套是分开的 —— 往轮盘里挪进一把枪只改了 bag,Tab 切枪读的是 // gWeaponManager.CurrWeaponSlots,不补这一步 Tab 永远只在拳头和角色自带那把之间转。 // 传进来一串包 id 就行,只有真的碰到轮盘(99952004)才会动手 —— 其余包零开销。 // func GameRouter_Extraction_SyncWheelAfterBagChangeAsync(ctx context.Context, session *GameSession, phase string, touchedBags []any) any { // Router implementation for GameRouter_Extraction_SyncWheelAfterBagChangeAsync var zero any; return zero } // list7bit<u32> 解包。7bit 计数带 +1 偏置 ⇒ 读出来的数要减一。 func GameRouter_Extraction_ReadU32List7Bit(ctx context.Context, body []byte) []any { // Router implementation for GameRouter_Extraction_ReadU32List7Bit return nil } func GameRouter_Extraction_ReadVarInt(ctx context.Context, body []byte, pos int32) int32 { // Router implementation for GameRouter_Extraction_ReadVarInt return 0 }