package routers import ( "context" "sync" ) var _ = sync.Mutex{} var _ = context.Background // // Interactive props: Gadget placement and DynamicGo activation. // Two different systems, both previously untouched by this server: // Gadget — the game's placed interactive prop (chairs, benches, arcade cabinets, // computers, drill shelves). The client owns the prefabs; the server only says *which prefab and // where* via SyncGadgetAdd(68843189) and the client loads and spawns it. We have the full prefab // list (2935 pathIds) from the world dump, so this is the one channel where the server can put a // brand-new interactive object into the world without any scene data of its own. // DynamicGo — scene-authored props that the client already has (doors, shutters, kiosks). // Their ids live inside the client's scene resources, which is why the server has never been able // to enumerate them. The client tells us what it activated through AskActiveDynamicGo(67339530), // so the reachable half is: accept the report, remember it, and echo it back as // SyncDynamicGoChange(68106491) so the state survives a relog instead of resetting. // // // Client invoke: AskActiveDynamicGo(67339530) — "I activated/deactivated prop id N". // The wire payload is 6 bytes and reads as int32 + bool + byte, which pins // DynamicGoChangeReason to a single byte even though the dump types it as an int enum. The // two sightings in unknown-methods.log are both reason 5 (Shop) on the same id with // active 0 then 1 — a shop purchase toggling a prop, not a player pressing a switch. // func GameRouter_Gadget_OnActiveDynamicGo(ctx context.Context, conn any, msg any) any { // Router implementation for GameRouter_Gadget_OnActiveDynamicGo var zero any; return zero } // // Builds the mandatory part of GadgetEntityInfo and books the instance in // WorldEntryState.SpawnedGadgets. Shared by the single and batch channels. // func GameRouter_Gadget_BuildGadgetEntityInfo(ctx context.Context, session *GameSession, state any, pathId int32, x float32, y float32, z float32, facing float32, uniqueId uint64, iScale int32, spoonParams []any, houseFurniture bool) any { // Router implementation for GameRouter_Gadget_BuildGadgetEntityInfo var zero any; return zero } // // Per-prefab spoon parameters (PackedGadgetInfo.spoonSpecialList). Most props ship it // null — a frida dump of 161 live instances found only the SpoonSlot doors and // MiniGameMachine_Bee carrying anything (markId 31511937 = "True", which is what arms the // mini-game). Explicit params win; otherwise we look the prefab up in // world.content.gadgetSpoonParams.byPathId. Null came a full stop before this existed, // so nothing else can regress by adding it. // func GameRouter_Gadget_BuildSpoonSpecialList(ctx context.Context, session *GameSession, pathId int32, explicitParams []any) []any { // Router implementation for GameRouter_Gadget_BuildSpoonSpecialList return nil } // // Places a whole batch with SyncGadgetAddList(68925813) — one push, N entities. This is the // channel AnantaGymLoader.exe drives by injection; it exists here so the server can try it // without the loader (see GadgetSendChannel.AddList). // func GameRouter_Gadget_SpawnGadgetListAsync(ctx context.Context, session *GameSession, state any, specs []any, iScale int32, houseFurniture bool) any { // Router implementation for GameRouter_Gadget_SpawnGadgetListAsync var zero any; return zero } // // Places one Gadget prefab into the world in front of the player and returns its instance id. // Only the mandatory part of GadgetEntityInfo is filled: instance id, transform, and the // packed placement (pathId + same transform + a fresh uniqueId). Every authored sub-module — // doors, drill shelves, lifts, occupants — is left null, which the client reads as "this prop // has none". ForceLod0 keeps a freshly spawned prop from being culled to a billboard. // // // Non-zero = reuse that instance id instead of minting one. Gym equipment passes the real blob // uid captured from the client, so the entity the server places is the same instance the client // would have built itself (its prefab lookup and any blob-side state key off that uid). // func GameRouter_Gadget_SpawnGadgetAsync(ctx context.Context, session *GameSession, state any, pathId int32, x float32, y float32, z float32, facing float32, channel any, uniqueId uint64, iScale int32) any { // Router implementation for GameRouter_Gadget_SpawnGadgetAsync var zero any; return zero } // Removes every Gadget this panel placed, or just one when an id is given. // // 只撤某一种物件(按 pathId)。**这是撤离探针残留的正确姿势** —— 全清会把健身房器材 / // PropRestock / 摊位补给一起抹掉,而它们各自管线有自己的 Sent 记录,不一定会立刻补回来。 // (2026-10-03 随赛车移植:赛车门「过点即撤」要按 pathId 批量撤。) // // // ★ 只撤这一批 id(比 更细)。 // 赛车门一局 52 个门**同一个 pathId**,按 pathId 撤会把还没跑到的一起撤掉, // 所以「过点即撤」必须用它。 // func GameRouter_Gadget_RemoveGadgetsAsync(ctx context.Context, session *GameSession, state any, onlyId any, pathIdFilter int32, onlyIds []any) any { // Router implementation for GameRouter_Gadget_RemoveGadgetsAsync var zero any; return zero } // // Which S2C channel places the prop. SyncGadgetAdd(68843189) is the direct create call and was // proven to reach the client; SyncGadgetAOIAddAndRemove(68169646) is the world-streaming call // the client uses for props that come and go with the AOI. Both are offered because which one // the client honours for a prop that no grid ever streamed is still unknown. // type GadgetSendChannel int32 const ( GadgetSendChannel_Add GadgetSendChannel = 0 GadgetSendChannel_Aoi GadgetSendChannel = 1 GadgetSendChannel_Both GadgetSendChannel = 2 // // SyncGadgetAddList(68925813) — the channel AnantaGymLoader.exe calls. Same payload as // Add but batched in one push. Worth trying when Add builds the entity (name, position, // interact point all correct) yet the prefab never appears: the two client handlers are // different methods (0x12787ED0 vs 0x1276CF20) and may not share the resource path. // GadgetSendChannel_AddList GadgetSendChannel = 3 ) // One prop the caller wants placed. Used by the batch channel. type GadgetSpawnSpec struct { PathId int32 `json:"pathId"` X float32 `json:"x"` Y float32 `json:"y"` Z float32 `json:"z"` Yaw float32 `json:"yaw"` UniqueId uint64 `json:"uniqueId"` Name string `json:"name"` }