package methods // ============================================================================ // Task (quest) contracts for build 4229938. // // Why this file exists: the task panel reads its list from ONE dedicated S2C, // SyncPlayerAllTask(64260853). It does not read the login payload at all — // PlayerClientInfoAchievement.UnlockedQuestList is consumed only by the // favourites / ambient-event code (verified by grepping the client Lua), so // filling 4342 quest ids there leaves the panel empty. That was tried and it // changed nothing in-game. // // Every shape below is transcribed from the client's OWN reader table // (Drmk.Proxy/proxy/lua/RPCDeserializeAuto.lua), which is authoritative for the // wire order. Reader indices are noted per type so a future change can be // re-verified instead of guessed. Indices are build-specific — an earlier draft of // this file quoted 334/335/503/1567 from a different client build and produced a // stream that desynced the reader: // // midToReader[64260853] -> taskInfos, submitTaskList, // currentTask, eventPanelInfo, // loginGameServer (5 args, not 7) // Auto.Reader[334] TaskViewData TaskId, CounterValues, Counters, // State(byte), ActiveFunctionValue, // ActiveFunctionIds, RecoverResource, // SpoonViewInfo // Auto.Reader[1567] TaskViewCounter Index, Value, ConfigValue, Parent, Child // Auto.Reader[1164] IntList Value (Int32 count!) // Auto.Reader[503] TaskSpoonViewInfo (unused while null) // Auto.Reader[335] TaskEventPanelInfo EventsInfo, SubmitEventList, // SubmitReplayEventList, EventViewInfoList // <-- FOUR fields on 4229938 // Auto.Reader[1563] EventInfo (unused while EventsInfo is empty) // Auto.Reader[1043] EventViewInfo (unused while EventViewInfoList is empty) // Auto.Reader[438] TaskStateData State(byte), Reason(byte), FailTextId, // CanSkip // // Reader indices are build-specific and MUST be re-read from // Drmk.Proxy/proxy/lua/RPCDeserializeAuto.lua (or lua.zip) rather than copied from // another branch. An earlier draft of this file quoted 293/294 from a different // client build: 293 is a colouring-slot struct and 294 has three fields, so that // draft dropped SubmitReplayEventList and desynced everything after eventPanelInfo. // // Framing, from lua/LX6/Service/RPCDeserializeBase.lua: ReadList7Bit/ReadDict7Bit read // one byte and return nil only when it is 0x00, then read a biased 7-bit count; // ReadComplex does the same and emits NO inner object marker. UxSerializer therefore // writes 0xFF as the "present" marker (any non-zero byte works) followed by UxWriter.Int7. // // Enums are 1 byte on the wire (Reader[334].State = ReadByte), so every enum below is // declared `: byte`. UxSerializer writes Enum.GetUnderlyingType, so a plain `enum` // (int) would emit four bytes and shift every following field. // // TaskState comes from the IL2CPP dump (enum UX.Game.TaskState, TypeDefIndex // 32201): NotAccept=0, Accepted=1, Submited=3, Aborted=4. Note there is no 2. // ============================================================================ // UX.Game.TaskState — one byte on the wire (Reader[334].State is ReadByte). type TaskState4229938 byte const ( TaskState4229938_NotAccept TaskState4229938 = 0 TaskState4229938_Accepted TaskState4229938 = 1 TaskState4229938_Submited TaskState4229938 = 3 TaskState4229938_Aborted TaskState4229938 = 4 ) // Auto.Reader[1567] — a task counter node. `Child` is the same type, so the // recursive field references this class. // Auto.Reader[503] — which spoon/raid this task is authored in. // Auto.Reader[1164] — value list behind PlayerTaskInfo.ActiveFunctionIds. // Uses an Int32 count, not a 7-bit one. // Auto.Reader[334] — one row of the task panel. // Auto.Reader[1563] — an ambient/story event row. // FinishedChoiceLs is the Int32-counted list. // Auto.Reader[1043] — event view metadata. // Auto.Reader[335] — bundled event state carried alongside the task list. // Exactly FOUR fields on 4229938. SubmitReplayEventList is easy to lose because some // client builds omit it; dropping it here pushes EventViewInfoList into // loginGameServer and strands a trailing byte, which desyncs the whole packet. // // SyncPlayerAllTask(64260853) — the ONLY thing that populates the task panel. // Wire shape (midToReader[64260853], export option LuaAndCSharp, so both the Lua // impl and the native side see it): // taskInfos List<PlayerTaskInfo> (7-bit count, complex items) // submitTaskList List<uint> (7-bit count) // currentTask uint // eventPanelInfo EventPanelInfo (complex) // loginGameServer bool // Flat argument list, so this wrapper is Inline: a 0xFF marker before taskInfos // would be read as the list's own framing and corrupt the count. // // // SyncPlayerAllTaskDebug(64423039) — the CSharpOnly twin of SyncPlayerAllTask, and the ONLY // way to get task rows into the native task manager. // Why this exists: SyncPlayerAllTask(64260853) is LuaAndCSharp and the client ships a Lua impl // (GameToClientImpl.SyncPlayerAllTask). Per the dispatcher rule, a LuaAndCSharp method with an // impl reports handled=true and native never sees the packet — and that impl only reads // `currentTask`, it never touches `taskInfos`. So the list we publish there is discarded. // This one is CSharpOnly with no Lua impl, so native reads it. Field order straight from the // IL2CPP dump (UXRPCMethodArgs64423039): taskInfos / submitTaskList / submitEventList / // versionControlInfo. TaskViewData (dump TypeDefIndex 32303) has exactly the eight fields of // PlayerTaskInfo4229938, so that DTO is reused as-is. // // UX.Game.ChangeSingleTaskReason — one byte on the wire (Reader[438].Reason). // From the IL2CPP dump, TypeDefIndex 32311. type ChangeSingleTaskReason4229938 byte const ( ChangeSingleTaskReason4229938_Accept ChangeSingleTaskReason4229938 = 0 ChangeSingleTaskReason4229938_TaskCounterAdd ChangeSingleTaskReason4229938 = 1 ChangeSingleTaskReason4229938_TaskCounterDesChange ChangeSingleTaskReason4229938 = 2 ChangeSingleTaskReason4229938_GpsChange ChangeSingleTaskReason4229938 = 3 ChangeSingleTaskReason4229938_Submit ChangeSingleTaskReason4229938 = 4 ChangeSingleTaskReason4229938_Abort ChangeSingleTaskReason4229938 = 5 ChangeSingleTaskReason4229938_Fail ChangeSingleTaskReason4229938 = 6 ChangeSingleTaskReason4229938_ClearSubmit ChangeSingleTaskReason4229938 = 7 ) // Auto.Reader[438] / UX.Game.TaskStateData (TypeDefIndex 32305) — why a single task // changed. Note the dump declares these enums as `int`, but the generated client reader reads // bytes, so both are declared `: byte` here. // // SyncTaskTitleGuideUnlock(64841491) — unlocks one task title (a panel tab / chapter group). // Wire shape from the IL2CPP dump (UXRPCMethodArgs64841491): `ushort taskTitleId`, // `bool unlock`. The client's Lua impl calls // gMapSystem.taskUtils:SetTaskTitleGuide(taskTitleId, unlocked), so this is what reveals // the story/side/chapter tabs. Ids come from TaskTitleConfig.json (21 rows on this build: // 1,2,3,4,5,6,7,8,9,10,11,12,13,15,16,19,21,23,24,25,99). // taskTitleId is a ushort — writing it as uint would shift `unlock` out of position. // // // SyncPlayerSingleTask(64917604) — per-task incremental channel, and CSharpOnly with no Lua // impl, so native's task manager reads it. This is the channel the real server uses when a // task changes state after login. // Wire shape from the dump (UXRPCMethodArgs64917604): `uint taskId`, `TaskViewData taskInfo`, // `TaskSpoonViewInfo spoonViewInfo`, `TaskStateData stateData`. Flat argument list, so this // wrapper is Inline; each of the three class arguments carries its own Complex marker. // // // SyncCurrentTask(64450155) — S2C「把这条任务设为当前追踪任务」(GPS 布点)。 // 2026-10-03 随赛车移植:赛车接受任务时必须回这一条,否则客户端不知道该追踪哪条。 // 线格式取自客户端 reader:`byte type, uint taskId, uint eventId, bool firstTime, byte reason` // —— flat argument list,Inline。 // Type 0 = CurrentTaskType.Primary;Reason 2 = ChangeCurrentTaskReason.Client。 //