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

128 lines
6.4 KiB
Go

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"`
}