package routers import ( "context" "sync" ) var _ = sync.Mutex{} var _ = context.Background // // Doors as gadgets — T2-11, ported from the donor's proven rounds 16C-16I. // Doors are PLAIN GADGETS carrying a DoorModuleSyncInfo module ("USER MODEL ADOPTED: // DOORS ARE GADGETS", HANDOFF-2026-09-18 round 16I-7). The client reports crossings with // AskPlayerEnterOrLeaveDoor(63525373) = (ulong gadgetId, bool isEnter), dump.cs:1893406. // ⛔ WIRE KIND: the client sends this as a NOTIFY, not an invoke — packets log shows // "C2S NOTIFY AskPlayerEnterOrLeaveDoor [0x03C951FD] body=9b". Registered Invoke-only it never // matched and every frame fell to DefaultUnknownNotify4229938, so nothing was ever logged. // Registration is Both and only invokes get a reply (a notify has no callback). // There is NO dedicated door RPC: a census of all 2754 UXRPCMethodArgs classes in the client // found zero door-proximity args classes (round 16C). The state travels inside // GadgetEntityInfo.DoorModuleInfo and arrives through SyncGadgetRefresh(68765074), which the // client applies in OnSyncDoorInfo. The chain is BaseDoorProxy.TriggerEnter -> // DoorMgr.SyncDoorProximityState -> DoorModuleSyncInfo{LockState, ProximityState, // ProximityStartTime, ClientInfos}. // ⚠ Two door classes, do not confuse them (donor round 16I-10): // · venue / high-layer doors whose approach makes the client's own bundled // sector_high_indoor_<id>_0 binary fail to deserialize — no server fix exists; // · ordinary gadget doors, which this file drives. The gym (Hypercore) and Sonic Boom doors // were in the SECOND class and opened live in round 16H. // // AskPlayerEnterOrLeaveDoor(63525373) — u64 gadgetId + u8 isEnter. // ⛔ NOTIFY on the wire, never invoke — see the class note for the evidence. func GameRouter_Door_OnAskPlayerEnterOrLeaveDoor(ctx context.Context, conn any, msg any) any { // Router implementation for GameRouter_Door_OnAskPlayerEnterOrLeaveDoor var zero any; return zero } // ---- the official channel ------------------------------------------------------------- // Three dedicated door S2Cs exist and the client really implements them (GameSceneToClient // overrides at RVA 0x127D4500 / 0x127D4690 / 0x127D4840 — a stub would be 0x9148360). The // donor's round 16C census missed them because bare-scalar methods own no args class. // Semantics are the client's own enums: DoorLockState{Unlocked=0, Locked=1}, // DoorProximityState{NoPlayer=0, HasPlayer=1}. // Announce "somebody is at this door": unlock, HasPlayer, and swing the leaf. func GameRouter_Door_PushDoorOpen(ctx context.Context, session *GameSession, gadgetId uint64) any { // Router implementation for GameRouter_Door_PushDoorOpen var zero any; return zero } // Announce "nobody is here any more" — the leaf slides back to 0 degrees. func GameRouter_Door_PushDoorShut(ctx context.Context, session *GameSession, gadgetId uint64) any { // Router implementation for GameRouter_Door_PushDoorShut var zero any; return zero } func GameRouter_Door_Push(ctx context.Context, session *GameSession, methodId uint32, args any, what string) any { // Router implementation for GameRouter_Door_Push var zero any; return zero } // // Legacy path: restate the door through SyncGadgetRefresh(68765074) with DoorModuleSyncInfo. // Body size is the acceptance proof: donor round 16H measured 8 presses -> 8x 130b refreshes // -> ZERO `deserialize failed methodId=68765074`, and the gym / Sonic Boom doors opened. // ⛑️ Round 16I-4/5 then proved the 130b shape is what made the leaf VANISH on approach: // an empty ClientInfos means "no leaf record", so the panel hides the leaf when the module // is applied. Carrying one OpenAngle takes the body to 135b (donor's byte-exact size) and // gives the panel something to swing. Every other collection stays EMPTY rather than null, // which is what makes the arithmetic land on those numbers. // Placement is frozen per gadget on first push (see DoorPlacementsOf): Pack carries a real // position the client applies to the entity, so re-sending a different/player-tracked // position drags the door around (or to zero) instead of leaving it where it belongs. // func GameRouter_Door_PushDoorProximity(ctx context.Context, session *GameSession, gadgetId uint64, proximityState byte, openAngle float32) any { // Router implementation for GameRouter_Door_PushDoorProximity var zero any; return zero } func GameRouter_Door_DoorPlacementsOf(ctx context.Context, session *GameSession) map[string]any { // Router implementation for GameRouter_Door_DoorPlacementsOf return nil } // ---- auto-close ---------------------------------------------------------------------- // Donor round 16I-4/5: the client emits ENTER far more often than LEAVE (one session logged // 3 ENTER / 0 LEAVE), and it never restates the module by itself, so a door opened by the // server stayed open forever / vanished on leave. Cancel the pending timer on any new event // for the same door so only the last one survives. func GameRouter_Door_DoorTimersOf(ctx context.Context, session *GameSession) map[string]any { // Router implementation for GameRouter_Door_DoorTimersOf return nil } func GameRouter_Door_ArmDoorAutoClose(ctx context.Context, session *GameSession, gadgetId uint64) any { // Router implementation for GameRouter_Door_ArmDoorAutoClose var zero any; return zero } func GameRouter_Door_CancelDoorAutoClose(ctx context.Context, session *GameSession, gadgetId uint64) any { // Router implementation for GameRouter_Door_CancelDoorAutoClose var zero any; return zero } func GameRouter_Door_CacheGarageDoor(ctx context.Context, session *GameSession, gadgetId uint64) any { // Router implementation for GameRouter_Door_CacheGarageDoor var zero any; return zero } // 出库时把本会话记住的车库门推开。没有缓存(玩家没走过门)就只记一条日志。 func GameRouter_Door_OpenCachedGarageDoor(ctx context.Context, conn any) any { // Router implementation for GameRouter_Door_OpenCachedGarageDoor var zero any; return zero } // // Where this session last said a door stands. GadgetEntityInfo.Pack is authoritative on the // client side, so once we have declared a placement we must keep declaring the same one: // a drifting value makes the leaf jump to the player instead of sitting in its frame. // type DoorPlacement struct { X float32 `json:"x"` Y float32 `json:"y"` Z float32 `json:"z"` Facing float32 `json:"facing"` }