package methods // // C2S AskSetMobileSkinPart(63575641) — "wear this wallpaper / decoration / pendant". // Wire shape is three bare UInt32 with no complex header, read from the client's own serializer // (lua/LuaGen/AutoGen/ClientToGameDelegate.lua:4362 // SerializerHelper.AskSetMobileSkinPart_Serializer(writer, wallpaper, decoration, pendant)). // Bare primitives ⇒ this contract must be Inline; a 0xFF marker would shift every field. // // // S2C SyncSpiritMobileSkinPartInfo(64208597) — the ONLY packet that actually changes the phone // wallpaper the player sees. // lua/LX6/Service/GameToClientImpl.lua:1968 // GameToClientImpl.SyncSpiritMobileSkinPartInfo = function(spiritId, mobileSkinInfo, availableSkinParts) // spiritViewData.SpiritInfo.MobileSkinInfo = mobileSkinInfo -- the worn suit // ... // gMessageManager:SendMessage(ON_SYNC_SPIRIT_SKIN_PART_INFO_CHANGE) // The client never applies the choice locally: it waits for this packet, then // MainPhonePanelStore.OnSpiritSkinPartChange re-reads MainPhoneUtils.GetCurrentSpiritSkinInfo(). // Without it the panel closes, the wallpaper reverts to the login-payload value, and the player // sees "applied successfully" with no visible change. // Wire shape from the client's own reader (RPCDeserializeAuto.lua midToReader[64208597]): // spiritId UInt32 FightSpiritConfig id, i.e. SpiritInfo.TemplateId // (SpiritManager.spiritViewDatas is keyed by TemplateId) // mobileSkinInfo complex Auto.Reader[323] 3x UInt32 (Wallpaper/Decoration/Pendant) // availableSkinParts List7Bit<UInt32> // WARNING: never send a zero-length availableSkinParts. The client does // if availableSkinParts then gPlayerManager.infoSpirit.bindData.AvailableSkinParts = availableSkinParts end // and an empty Lua table is still truthy, so an empty list WIPES the phone's skin list. // A null field writes a single 0x00, which the client reads as "no list" and skips the assign — // that is the safe way to leave the list untouched. //