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

160 lines
8.4 KiB
Go
Raw Permalink Normal View History

package routers
import (
"context"
"sync"
)
var _ = sync.Mutex{}
var _ = context.Background
//
// World props WITHOUT the AnantaGadgetLoader exe — the server-side half of what that tool does
// by frida injection.
// The loader calls GadgetMgr.SyncGadgetGridAOIAddByIndex(cx, cz, exceptIds, sectorIds,
// gridIndex) inside the client process; the props themselves come from the client's own
// GadgetBlob, so nothing has to be authored server-side. The wire equivalent is
// SyncGadgetGridAOIDecrease(68956797) — the only grid-AOI method id that exists, and it
// carries both directions (add cells in addGridInfo, remove in removeGridInfo).
// ⛔ CORRECTED 2026-09-27 (user live-tested; the previous wording here was wrong twice):
// · The old line said "Donor server proved this end to end (HANDOFF round 12)". NO donor
// ever said that. HANDOFF-2026-09-19.md:2598 "ROUND 12 VERDICT" is OUR OWN round,
// user-tested 2026-09-20. The HANDOFF docs mix donor material with our own round log —
// round 12/13/15D/15F/15G/15H/16E/16I are all ours (they carry "user-tested" / "TEST NOW").
// · "appeared AND stayed interactive" is also wrong as written. Appearing and being
// interactable are TWO INDEPENDENT things on this channel:
// - 68956797 only materializes props out of the client's own GadgetBlob, and only for
// cells+sectors we actually push => only a PART of the world ever appears.
// - interactability is decided SOLELY by how the server answers the Ask* device RPCs
// (see GameRouter.SceneDevices.cs: an Ask* INVOKE is only a REQUEST; the client's
// device-state manager waits for the server to echo the transition before it runs any
// presentation). No reply shape => no interaction, injector or not.
// HANDOFF-2026-09-18.md:341 (ROUND 15H) pinned the ONE session where vending + outfits +
// signs + elevators ALL worked at once — Sep 20 01:32 (packets-20260920-012232.log) — and
// that session's wire was an 8-byte struct {int CheckIndex; uint Error}, silent, ALL
// devices. Cross-era census (user-verified): 012232 = 8b struct silent -> all families OK;
// 021225 = 6b blob silent -> vending STUCK (retry storm); r13-15F = 10b + echoes ->
// vending OK but menu prompts DISARM.
// · So "no injection needed" means "no frida injector needed to MATERIALIZE", NOT
// "the server can sit idle and still get interactions".
// Two rules the loader's author established and we keep:
// · sector pairing matters — one message carries ONE sector list, so cells are grouped
// by identical sector list (sectorIdList=[0] is outdoor only; interior furniture lives
// in hashed sectors from GadgetCells.json);
// · never spam — a cell is pushed once and re-pushed only on a cell crossing or the
// periodic refresh. The loader's own note warns that hammering the grid channel kills it.
//
//
// ★ donor《content-streaming-implementation》§3 的窗口差分(2026-10-01 落地)。
// prevLoaded = 客户端当前持有的格子;window = 本轮要展示的正方形窗口。
// <code>
// added = window − prevLoaded // 新格子 → 见到才加载
// keep = prevLoaded 里仍落在卸载边界内(Chebyshev ≤ unloadRadius)的那些(保留环)
// removed = prevLoaded − keep // 真·出界 → 显式下发卸载
// next = window ∪ keep // 成为新的 prevLoaded
// </code>
// ⛑ retainVisitedCells=false ⇒ 没有保留环,出窗口即卸载(等价于 unload = radius)。
// ⛑ 窗口与卸载边界都用 Chebyshev(正方形),与 §2 的 (2r+1)² 定义一致,别改用曼哈顿。
//
func GameRouter_GadgetGrid_ComputeGridWindowDiff(ctx context.Context, prevLoaded []any, window []any, cx int32, cz int32, unloadRadius int32, retainVisited bool, added []any, removed []any, next []any) any {
// Router implementation for GameRouter_GadgetGrid_ComputeGridWindowDiff
var zero any; return zero
}
//
// ★ donor《content-streaming-implementation》§1 —— 传送 / 远跳时两个窗口根本不相交
// ⇒ 必须 Init 全 re-seed(清空声明过的格子),不能只补差集。
// 2026-10-01 起用它解决「owner.Sent 只增不减」这一条:以前每次远跳都会留下一份
// 玩家已经离开的格子,永远不会消失,把卸载这件事全推给客户端自己去猜。
// ⛑ 判据 = 格子 Chebyshev 距离 &gt; unloadRadius(窗口不相交,donor §3 原文)。
//
func GameRouter_GadgetGrid_IsFarGridJump(ctx context.Context, fromX int32, fromZ int32, toX int32, toZ int32, unloadRadius int32) bool {
// Router implementation for GameRouter_GadgetGrid_IsFarGridJump
return true
}
func GameRouter_GadgetGrid_GadgetGridStateOf(ctx context.Context, session *GameSession) any {
// Router implementation for GameRouter_GadgetGrid_GadgetGridStateOf
var zero any; return zero
}
// World-ready hook: start the grid stream. Idempotent; no-op when disabled.
func GameRouter_GadgetGrid_EnsureGadgetGrid(ctx context.Context, session *GameSession) any {
// Router implementation for GameRouter_GadgetGrid_EnsureGadgetGrid
var zero any; return zero
}
// Disconnect / scene switch: stop the loop. Props already out stay out.
func GameRouter_GadgetGrid_StopGadgetGrid(ctx context.Context, session *GameSession) any {
// Router implementation for GameRouter_GadgetGrid_StopGadgetGrid
var zero any; return zero
}
// Cells handed to the client so far. Panel/debug display only.
func GameRouter_GadgetGrid_GadgetGridSentCount(ctx context.Context, session *GameSession) int32 {
// Router implementation for GameRouter_GadgetGrid_GadgetGridSentCount
return 0
}
func GameRouter_GadgetGrid_RunGadgetGridLoopAsync(ctx context.Context, session *GameSession, owner any, token context.Context) any {
// Router implementation for GameRouter_GadgetGrid_RunGadgetGridLoopAsync
var zero any; return zero
}
func GameRouter_GadgetGrid_TickGadgetGridAsync(ctx context.Context, session *GameSession, owner any) any {
// Router implementation for GameRouter_GadgetGrid_TickGadgetGridAsync
var zero any; return zero
}
//
// Push every not-yet-sent cell around (cx,cz), grouped by sector list, one message per group.
// Returns how many cells went out.
// ★ 2026-10-01 重写为 donor《content-streaming-implementation》§3 的 add/keep/remove 三元组:
// 以前只算 added(差额补发),removeGridInfo 恒为空 ⇒ 走过的格子永远被声明、
// 客户端永不卸载(这正是 2026-09-27 §10.9.3 内存项第 3 条)。现在走出
// unloadRadiusCells 边界的格子会被显式下发卸载。
//
func GameRouter_GadgetGrid_PushGadgetGridAsync(ctx context.Context, session *GameSession, owner any, cx int32, cz int32, reason byte, fullResend bool) int32 {
// Router implementation for GameRouter_GadgetGrid_PushGadgetGridAsync
return 0
}
//
// ★ donor《content-streaming-implementation》§4 —— 显式的「请卸载这批格子」。
// 单独一条 68956797:addGridInfo 空表、removeGridInfo 装出界的格子。
// ⛑ BuildingId 必须写 int32(值 0)—— donor §6 第 2 条:漏写会让整条 payload 错位。
// ⛑ sector 仍然要带:一条报文一个 sector 列表,和加载侧同律分组。
//
func GameRouter_GadgetGrid_PushGadgetGridRemovalAsync(ctx context.Context, session *GameSession, removed []any, cx int32, cz int32, reason byte) any {
// Router implementation for GameRouter_GadgetGrid_PushGadgetGridRemovalAsync
var zero any; return zero
}
type GadgetGridSessionState struct {
SyncRoot any `json:"syncRoot"`
Cts *context.CancelFunc `json:"cts"`
Loop *any `json:"loop"`
// Cells already handed to the client. A cell is re-sent only on refresh.
Sent []any `json:"sent"`
LastCellX int32 `json:"lastCellX"`
LastCellZ int32 `json:"lastCellZ"`
HasCell bool `json:"hasCell"`
LoadedSent bool `json:"loadedSent"`
//
// Scene AOI switch (68418115) already pushed for this session. Research lever only —
// gated by SceneAoiSwitchEnabled, which defaults to false.
//
SceneAoiSwitchSent bool `json:"sceneAoiSwitchSent"`
LastPushMs int64 `json:"lastPushMs"`
ReadyAtMs int64 `json:"readyAtMs"`
Pushes int32 `json:"pushes"`
CellsSent int32 `json:"cellsSent"`
// 首次成功整窗推送的时刻(Environment.TickCount64)。入世界守卫的计时基准。
FirstPushMs int64 `json:"firstPushMs"`
//
// ★ 2026-10-04「入世界守卫」是否已经做过。每会话只做一次;
// 远跳 reseed(ReseedOnFarJump)已经替我们清过窗时也算完成,避免重复砸卸载报文。
//
SettleDone bool `json:"settleDone"`
}