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
Ananta-ps/internal/gameserver/routers/game_router_mini_game_stall.go
T

112 lines
7.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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"`
}