104 lines
6.4 KiB
Go
104 lines
6.4 KiB
Go
package methods
|
||
|
||
//
|
||
// Cat Express / 蓝猫物流 wire contracts for client build 4229938 (internal name: UberSim).
|
||
// Why this file exists: the panels exist and look finished, but every list they render is a server
|
||
// reply — AskGetTruckJobOrders supplies the take-order list, AskGetFinishedOrderWraps
|
||
// the completed list — and none of those had a handler, so the app opened onto an empty board.
|
||
// Source of truth. The IL2CPP dump declares these types as EMPTY classes
|
||
// (ux_game_all.dump.cs:24562 ClientTruckOrderView, :34846 TruckJobOrderWrap — hard
|
||
// rule 22), so every field order below comes from the client's own writer in
|
||
// lua/LuaGen/AutoGen/RPCSerializeAuto.lua:
|
||
// ClientTruckOrderView :2523 · TruckJobOrderWrap :10473
|
||
// TruckJobOrderInfo :10433 · TruckJobOrderAccept :10428
|
||
// TruckJobOrderResult :10456 · TruckNpcInfo :10483
|
||
// TruckPosInfo :10490 · CargoInfo :1571
|
||
// DeliveryGadgetInfo :3272 · UXVector3 :11429
|
||
// ClientFinishedTruckOrderView :2273
|
||
// Field order IS the wire layout — do not reorder (UxSerializer writes by MetadataToken).
|
||
// Framing (from BowlingWireContracts.cs §0, re-derived here line by line):
|
||
// complex -> 0x00 when null, else 0xFF + fields (Base.WriteComplex)
|
||
// struct -> never any marker (Base.WriteStruct / Inline = true)
|
||
// list -> 0x00 when null, else 0xFF + Int32 count (Base.WriteList, 4 bytes FLAT)
|
||
// list7 -> 0x00 when null, else 0xFF + varint(count + 1) (Base.WriteList7Bit)
|
||
// dict7 -> same as list7, then key, value pairs
|
||
// ⛑⛑ WriteList and WriteList7Bit are NOT interchangeable and this type family mixes
|
||
// both — see the Count = UxCountEncoding.Int32 notes on each list below. Writing the
|
||
// wrong one shifts everything after it by three bytes and the client silently drops the reply.
|
||
//
|
||
// Three floats, never marked. Used for both positions and euler rotations.
|
||
//
|
||
// One drop-off fixture = Auto.WriteDeliveryGadgetInfo (RPCSerializeAuto.lua:3272). Complex.
|
||
//
|
||
//
|
||
// Pickup / delivery point = Auto.WriteTruckPosInfo (RPCSerializeAuto.lua:10490).
|
||
// ⛑ DeliveryGadgetInfoList goes through Base.WriteList (flat Int32 count), not the
|
||
// 7-bit variant — it is the one list in this family that is NOT varint-counted.
|
||
//
|
||
// Consignee identity = Auto.WriteTruckNpcInfo (RPCSerializeAuto.lua:10483).
|
||
// One physical parcel = Auto.WriteCargoInfo (RPCSerializeAuto.lua:1571).
|
||
//
|
||
// The authored body of one order = Auto.WriteTruckJobOrderInfo (RPCSerializeAuto.lua:10433).
|
||
// Everything cosmetic (cargo name, area name, disaster stars, tag icons, NPC portrait) is looked up
|
||
// client-side from CargoId / OrderType / SpecialOrderId, so the server only publishes identifiers
|
||
// and the numbers that go into payment.
|
||
//
|
||
// Set once the player takes the row = Auto.WriteTruckJobOrderAccept (:10428).
|
||
// Filled on settlement = Auto.WriteTruckJobOrderResult (:10456).
|
||
//
|
||
// One row of the take-order list = Auto.WriteTruckJobOrderWrap (RPCSerializeAuto.lua:10473).
|
||
// AcceptInfo / ResultInfo are the ONLY nullable complexes here
|
||
// (WriteComplex(..., true)), which is exactly how a row tells "takeable" from "taken".
|
||
//
|
||
//
|
||
// Reply body of AskGetTruckJobOrders(63386469) and AskRefreshTruckOrder(63071191) —
|
||
// Auto.WriteClientTruckOrderView (RPCSerializeAuto.lua:2523). The whole take-order board.
|
||
// ⛑ Reply framing: this type is declared complex (no Inline), matching every other INVOKE reply in
|
||
// this repo (Bubble / Extraction / Tuite's TuiteTimelineData). If the client logs
|
||
// deserialize failed for these two methods, flip delivery.replyFraming to "struct" in
|
||
// private-server.json — no rebuild needed.
|
||
//
|
||
//
|
||
// Reply body of AskGetFinishedOrderWraps — Auto.WriteClientFinishedTruckOrderView
|
||
// (RPCSerializeAuto.lua:2273). The three counters headline the completed-log page.
|
||
//
|
||
//
|
||
// Reply body of AskAcceptTruckJobOrder(63110537) — the callback is
|
||
// (errorId, TruckJobOrderWrap, ulong npcInstanceId), so this is the two-part tuple the RPC
|
||
// layer unpacks: complex row first, raw u64 second (no marker on a primitive).
|
||
// ⛑⛑ Inline, not complex. 2026-09-25 修正:这曾写成 [UxContract],于是顶层多出
|
||
// 一个 0xFF。多值回包的顶层是没有标记的 —— RPCDeserializeAuto.lua:10160 直接
|
||
// ReadComplex(286) 再 ReadUInt64,标记由每个值自己发。多出来的那一字节会让
|
||
// 客户端把 OrderWrap 的标记当成 OrderInfo 的标记、把 OrderInfo 的标记当成 StartPos 的标记,
|
||
// 整包左移一字节 ⇒ 回调拿到的是一坨垃圾(现象正是"点了接单没反应")。
|
||
// 对照:单值回包(ClientTruckOrderView / TruckJobOrderWrap)顶层要那个 0xFF,
|
||
// 因为客户端第一个读的就是 ReadComplex。
|
||
//
|
||
//
|
||
// Reply body of AskQueryTruckPosInfo(63763434) — RPCDeserializeAuto.lua:12187 reads
|
||
// ReadList7Bit(Auto.Reader[641]) twice, so again no top-level marker: Inline.
|
||
// The client only looks at [1] of each list (DeliveryTaskManager.lua:1870), so one
|
||
// entry per queried id in the same order as the request is all that is required.
|
||
//
|
||
//
|
||
// Push body of SyncAcceptTruckJobOrder(64910164) — RPCDeserializeAuto.lua:4732:
|
||
// (u32 id, complex TruckJobOrderWrap, u64 deliveryAgentId, u64 deliveryGadgetId), no top marker.
|
||
// ⛑ This — not the accept reply — is what actually moves the UI: the reply callback at
|
||
// DeliveryHomepagePanelStore.lua:809 inspects errorId and nothing else, and the
|
||
// store only clears its own canInteract latch in
|
||
// OnAcceptTruckJobOrder, which is bound to
|
||
// ON_ACCEPT_TRUCK_JOB_ORDER — the message GameToClientImpl.SyncAcceptTruckJobOrder
|
||
// (:1761) raises. So without this push the board stays frozen after a tap that the server logged
|
||
// as accepted.
|
||
//
|
||
//
|
||
// Inline twin of ClientTruckOrderView — identical fields, no leading marker.
|
||
// ⛑ Why a copy instead of a base class: UxSerializer serialises every public field including
|
||
// inherited ones and orders them by MetadataToken, so sharing one declaration would quietly make
|
||
// both framings emit the same bytes. The duplication is the cheap part; a mismatched reply
|
||
// framing costs a rebuild round-trip per guess.
|
||
// Selected at runtime by gameplay.deliveryReplyFraming ("complex" | "struct"). Nothing else
|
||
// consults it — a wrong guess shows up as the client dropping the callback, never as an exception.
|
||
//
|
||
// Inline twin of ClientFinishedTruckOrderView for the same reason.
|