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

111 lines
7.4 KiB
Go
Raw Permalink Normal View History

package routers
import (
"context"
"sync"
)
var _ = sync.Mutex{}
var _ = context.Background
//
// 龙栖村(新祈村)庙会摊位「布景」—— 服务端主动把摊位机关摆到官方世界坐标上。
// ★ 用户的原话:「现在能像别人服务那样把龙栖村所有的摊位布景都一起刷出来吗」
// ── 与对照包的关系(第 89 轮已核实,别再多花时间)────────────────────────────
// 对照包 `DRMK-PS_08.05_Lyco-v0.2.1` 里**没有任何摊位摆位代码**:
// grep SyncGadgetAdd|GadgetEntityInfo|MiniGameStall 只命中它自己的
// GameRouter.cs / GameRouter.SceneDeviceState.cs / MethodId.cs。
// 它只做了**打气球一个**小游戏的完整链路,其余摊位(套圈/刮刮乐/五子棋…)
// 连 wire 契约都没有(它的 Drmk.RpcTypes/Methods/Game/ 只有 BalloonZone + RacingZone)。
// ⇒ 「像别人那样把摊位刷出来」这件事,**我方是走在前面的一方**,不是补课。
// 对照包它自己也只有一句「入口空 ACK」,摊位本体照样看不见。
// ── 为什么必须服务端摆(与健身房器材 / 派对家具 / 补货物件完全同因)────────────
// 这批摊位机关(Gadget_DaQiQiu 912387408 / Gadget_RingToss 1937674505 /
// ScratchGame 165071345 / Gadget_WuZiQi 2066229997 …)的真身分两半:
// ① 客户端 Spoon 图里有一个 GADGET 节点(StartBalloonNode / StartRingTossNode …)
// ② 关卡块(vfc_1479 / vfc_859)里有一份**官方世界摆位**
// 而它**不在**客户端会自己实例化的清单里 —— grid-AOI 下发(68956797)**不驱动**
// LX6.Item.GadgetBlob.OnAoiAddBlobCfgByGridIndex ⇒ 一件都不会自己出现。
// 唯一可行路径 = 服务端拿 pathId + 官方坐标显式走 SyncGadgetAdd。
// ── 数据来源(别再搞混两套 id 空间)────────────────────────────────────────
// pathId = ClientData/4229938/Configs/GadgetCatalog.json(2935 条,服务端用)
// ⛔ 不是客户端 GadgetConfig.json 的 1367 条(另一套;
// 同一件 Gadget_DaQiQiu 在那边是 79304020,在服务端 catalog 是 912387408)
// 世界坐标 = Configs/MiniGameStalls.json(解自关卡块,工具
// gym_tools/_r87_minigame_gadget.py,记录结构 = 命中点-28 起头,
// +0/+4/+8 = f32 x/y/z,+16 = yaw,+28 = pathId)
// ── 判据(回答「是不是要按 F 才开始摆」)──────────────────────────────────
// **不是。** 摆位是「玩家走进锚点半径」触发的常驻世界装点,一次会话每片区只摆一次。
// 与玩家有没有交互、摊位开没开、Lua 有没有跑到那里**都无关** —— 这是纯服务端行为。
// 反过来说:**看得见摊位 ≠ 摊位能玩**。能玩要各自的小游戏入口 RPC
// (打气球 EnterBalloonZone 已实现;套圈 EnterRingTossZone 67108425 见下)。
// ⛔ PackedGadgetInfo.iScale 必须是 **0**(100 ⇒ transform scale (0,0,1) 零尺寸空壳,
// 看得见实体、看不见模型)。与气球的 DestructibleInfo.IScale = 1000 是
// **同名不同尺度的两个字段**(铁律 39;本条在 R89 上真踩过一次,别再来)。
// Rollback: world.content.miniGameStalls.enabled = false(config 热重载,不需重编译)。
//
func GameRouter_MiniGameStall_MiniGameStallStateOf(ctx context.Context, session *GameSession) any {
// Router implementation for GameRouter_MiniGameStall_MiniGameStallStateOf
var zero any; return zero
}
// 重连 / 切场景:忘掉已摆记录,下次进图重摆(客户端那边实例已随会话消失)。
func GameRouter_MiniGameStall_ResetMiniGameStall(ctx context.Context, session *GameSession) any {
// Router implementation for GameRouter_MiniGameStall_ResetMiniGameStall
var zero any; return zero
}
//
// 由网格 AOI tick 调用(它已经知道玩家位置)。把玩家走进的每个摊位片区的机关摆一次。
//
func GameRouter_MiniGameStall_TickMiniGameStallAsync(ctx context.Context, session *GameSession, state any, px float32, pz float32) any {
// Router implementation for GameRouter_MiniGameStall_TickMiniGameStallAsync
var zero any; return zero
}
//
// ★★★ 玩家走近刮刮乐桌 ⇒ 推一条 SyncStartScratchGameZone(68649573),把面板叫出来。
// ── 为什么必须服务端「主动」推 ────────────────────────────────────────
// 客户端**不发** AskStartScratchGame:它在 2349 个 Lua 文件里 0 命中,
// 9 份 packets-*.log 里也 0 命中(服务端 handler 已登记白名单、从未被调用过)。
// 而刮刮乐面板的**唯一**入口是服务端推 SyncStartScratchGameZone:
// GameSceneToClientImpl.lua:1131 → gScratchGameManager:Show(gadgetUid, subType, result)
// ScratchGameManager.lua:7:result == nil ⇒ return;否则
// GetEntitySearchByInstanceId(gadgetUid) → RegisterWaitLoad →
// Find("ItemViewNode/UIPose") → CheckShow(SCRATCHCARD_PANEL, …)。
// ⇒ 服务端不推,「通用交互提示」永远只是提示、没有选项。
// 详细 wire 见 GameRouter.MiniGameEntry.PushScratchStartAsync。
// ── 迟滞(别在边界上连推)────────────────────────────────────────────
// 进圈(dist ≤ ScratchOfferRadius)推**一次**;出圈超过 ScratchRearmRadius
// 才复位,允许再进来再推。玩家一直站在圈里 ⇒ 只推一条。
// ── 前提 ─────────────────────────────────────────────────────────
// 桌子的 gadgetUid 必须是**服务端自己 mint 的那个**([GADGET] add id=…)——
// 配表里 UniqueId = 0,所以只有 SpawnGadgetAsync 的返回值可信。
// 没摆到(uid==0)或走 AddList 批量通道(那条路目前不回收 id)⇒ 直接返回,什么都不做。
// Rollback: world.content.miniGameStalls.scratchAutoOpen = false(配置热重载,不用重编译)。
//
func GameRouter_MiniGameStall_MaybeOfferScratchAsync(ctx context.Context, session *GameSession, owner any, px float32, pz float32) any {
// Router implementation for GameRouter_MiniGameStall_MaybeOfferScratchAsync
var zero any; return zero
}
type MiniGameStallSessionState struct {
SyncRoot any `json:"syncRoot"`
// 摊位片区本轮已摆过的名字。一次会话每片区一次,和健身房 / 营地一样。
Placed []string `json:"placed"`
PlacedCount int32 `json:"placedCount"`
// 空表只抱怨一次,不每 tick 刷屏。
WarnedEmpty bool `json:"warnedEmpty"`
// 只记一次「跳过了几件」的明细,避免每片区重复。
SkipLogged []int32 `json:"skipLogged"`
// ── ★ 刮刮乐「走近自动叫面板」的状态 ──────────────────────────────
// 服务端自己 mint 出来的 ScratchGame 桌 instanceId(`[GADGET] add id=…`)。
ScratchGadgetUid uint64 `json:"scratchGadgetUid"`
ScratchX float32 `json:"scratchX"`
ScratchZ float32 `json:"scratchZ"`
// 上一刻玩家是否在圈内(迟滞用)。
ScratchNear bool `json:"scratchNear"`
// 本轮是否已推过(进圈只推一次)。
ScratchOffered bool `json:"scratchOffered"`
}