package methods // // NPC shop contracts for build 4229938, copied field-for-field from the client's own wire schema // (RPCDeserializeAuto.lua midToReader) rather than from the IL2CPP dump: the dump declares // NpcShopCommodityView and NpcShopRefreshState as empty classes, so it cannot be // used as the source of truth here. // The chain the client runs when the player presses F on a shop clerk: // OpenNpcShop(shopId) -> AskNpcShop(63563263) (server answers err only) // -> SyncFullCommodityInfos(64769566) (server pushes the shelf) // ShopManager.lua keeps the pushed rows in shopCommodityDataDict[shopId] and, when the // dictionary has no entry at all, aborts with "获取不到服务端的商品数据" — that is exactly the // empty-panel symptom. Everything else displayed (name, icon, quality, description) comes from // tables the client already has locally, so the server only has to name what is on the shelf. // Field order is the wire layout and must not be reordered: UxSerializer writes public fields in // declaration order, and the client's Reader[366] reads them in this same order. // // // One row of SyncFullCommodityInfos = Auto.Reader[366], the element of the shelf list. // Read back by the client as Base.ReadComplex(r, Auto.Reader[366]), so — unlike the // enclosing message — this one is not inline and does carry the 0xFF/0x00 presence byte. // // // SyncFullCommodityInfos(64769566): (uint shopId, List<NpcShopCommodityInfo> infos). // The client reader starts straight at reader.ReadUInt32 with no ReadComplex wrapper, so // this message is inline: no presence byte of its own, exactly like SyncDynamicGoChange. //