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
Ananta-ps/internal/gameserver/routers/game_router_bowling_pin_gadget.go
T

74 lines
5.3 KiB
Go
Raw Normal View History

package routers
import (
"context"
"sync"
)
var _ = sync.Mutex{}
var _ = context.Background
//
// ★ 诊断实验(2026-09-24 深夜):把 10 个球瓶改走**健身房器材那条路**推。
// 起因(客户端日志给出的硬证据):
// [error] ,scene item,910000000015, hold not found,
// BowlingGameManager.lua:670 in 'getItemsFromIdList'
// BowlingGameManager.lua:680 in 'InitSceneItems'
// ⇒ 客户端确实收到了我们推的 id(910000000001..15,见 BowlingZoneInfo 的两个 id 列表),
// 但 `SceneItemMgr.Instance:GetSceneItemHold(id)` 查不到 hold,
// 于是 `sceneItemPinList` 为空 → `Rent(101)` 报 "pool[101] is nil" →
// `BowlingPinSetter.CreatePin` 直接 return → 官方那套带模型的球瓶根本没被建出来。
// 我们走的 `DestructibleInfo` 只造出「物理 + 音效」的实体,不产生 hold、不产生渲染。
// 而本项目里**唯一被实测证明能生成"看得见"的物体**的通道是 gadget:
// `GameRouter.GymEquipment.cs` → GadgetEntityInfo(Pack.PathId 直接给资源 id)
// → `GadgetGridAOIIncrease` → `SyncGadgetAOIAddAndRemove`(68169646)
// 健身房器材就是这么生成出来的,肉眼可见。
// 所以本实验:同样用 gadget AOI 把东西推到球瓶位置,看客户端认不认。
// 配置(config/bowling_wire.json):
// "pinAsGadget": 1 打开本实验(0 = 关)
// "gadgetProbePathId": N 对照组的 pathId,默认 79300636 = MiniGameMachine_Bowling
// (GadgetConfig 里保龄球机器,写 0 = 不放对照组)
// 一次测试能读出三件事:
// ① 对照机器的 gadget 现身了?→ 说明「服务端推 gadget + AOI 通道」在球馆里也成立
// ② 10 个球瓶位置现出物体了?→ 说明客户端能把 `pinPathId` 当资源 id 解析出来 ⇒ 收工
// ③ 都不现 → gadget 通道认不得场景物 id,得转客户端侧(frida)方案
// ⚠ 本实验**不动**原来的 DestructibleInfo 推送(物理/计分/音效照旧),
// 只是在同一位置上再叠一层"看得见"的 gadget。两者互不干扰。
// ★★ 2026-09-24 A 方案移植说明(本文件与 PrivateServer修改 版的差异)
// 本仓库(DRMK-PS_09_HyNB-v1.7)里,机关那一族类型在 `...Methods.GameScene` 命名空间下,
// 且 `GadgetEntityInfo.Position/Facing` 的类型是 `Auto.UXVector3`:
// GadgetEntityInfo → Methods.GameScene(本仓库,下方用 SceneMethods. 限定)
// PackedGadgetInfo → Methods.GameScene(= 我们那边的 GadgetPackInfo,**字段顺序前 13 项完全一致**,
// 本仓库末位多出 extractionItemContainerId / isStatic 两个字段,
// 默认 0 即可,与 v1.7 自己的机关推送同形)
// 字段名对照(我们 → 本仓库):Jnc/Jnb/Jna → posX/posY/posZ;EulerX/Y/Z → eulerX/eulerY/eulerZ;
// IScale → iScale;UniqueId → uniqueId;PathId → pathId。
// ⚠ iScale 保持 100:这是**机关族**的正确取值(本仓库 PackedGadgetInfo.iScale 的注释写明
// "Uniform scale in percent (100 = authored size)",且 GameRouter.Gadget.cs / GymEquipment.cs
// 的默认参数就是 100)。我们那条「iScale 必须写 0」的教训针对的是**另一个**结构
// `SceneItemPlaceInfoData +0x3C`,两者不要混。
// ★★★ 第二处、也是**唯一改变语义**的一处:68169646 的顶层 args 换成本仓库既有的
// `SceneMethods.SyncGadgetAOIAddAndRemoveArgs4229938`(6 字段),不再用我们那边的
// `GymGadgetContracts.GadgetGridAOIIncrease`(7 字段)。理由是**证据打架时选宿主仓**:
// (a) 我们那边的 7 字段版本,来源是 Drmk.Proxy 的 proxy/rpc_schema.json 读端 schema
// `433`(已实测抽取,字段 = addInfos / indexList / addUniqueIds / removeIds /
// activeIds / inactiveIds / reason(ReadByte)),但本项目自己的
// `Drmk.RpcTypes\Client4229938\BowlingWireContracts.cs:271-276` 的注释把同一个
// DTO 判为 "uncalled rpc_schema-era gym DTO"(把 Destructible 与 Gadget 两族混用)。
// (b) 本仓库对 68169646 的既有写法就是 6 字段(GameRouter.Gadget.cs:257、Blackout.cs:335),
// 且 GameRouter.Gadget.cs:33-38 自述这条通道 "which one the client honours … is still
// unknown" —— 也就是说**本仓也从未验证过它**。
// (c) 本文件是**诊断旁路**,默认关闭(`_pinAsGadget = 0`),不参与保龄球主功能。
// 保龄球能不能玩,取决于服务端推球瓶实体(GameRouter.GameGround.cs + 本仓
// BowlingWireContracts.cs 的 DestructibleGridAOIIncrease,schema 396)**以及客户端
// BF1 补丁(AnantaBowlingLoader.exe)**,与本文件无关。
// ⇒ 结论:既然两种形状都未在本仓验证过,就**不引入第三种形状、不搬入被判可疑的 DTO**,
// 直接用宿主仓既有类型,保持本仓内部完全同形。若日后要试 7 字段形状,请回
// `PrivateServer修改\Drmk.Server\Drmk.RpcTypes\Client4229938\GymGadgetContracts.cs`
// 整体搬入,本文件只需把 payload 类型与字段名换回大驼峰即可。
//
func GameRouter_BowlingPinGadget_PushBowlingPinGadgetsAsync(ctx context.Context, conn any, session any, playerPos Vec3) any {
// Router implementation for GameRouter_BowlingPinGadget_PushBowlingPinGadgetsAsync
var zero any; return zero
}