State machine (cold start, first launch)
In 1.0.364,
CheckResVersion clears the cached server IP, port, and connection type on every cold start, so StartConnect never finds a cached server and the GSL (Gate Server List) call always runs (static-analysis-only). The cached ip/port/zone short-cut from state 6 to state 9 still exists, but only a mid-session reconnect, such as following a serverInfo redirect, takes it. See Identity, login & session for what the GSL call does with the stored tokens.
Check-version endpoint
table_env is table_online and server carries the cached zone (static-analysis-only). goclient sends both empty, and the server answers anyway (confirmed live).
Host list (requests go out to every host in parallel and the first success wins; on total failure the client retries the same list once). About 5% of devices are A/B-bucketed to the ea- hosts by GrayUtils.GetPercentageFromMd5: MD5(deviceId) read as a little-endian uint64, mod 100 + 1 <= 5.
goclient tries the three online hosts one after another, not in parallel.
Whichever host answers becomes the base URL for every subsequent call in this bootstrap (getserverlist.php, getnotice.php, probe.php); there is no separate “gate server” discovery step.
A response counts as valid when it has a non-empty code (which the client treats as an error), or when updateType is in 0..3 and hotUpdateMsg is non-empty. The 1.0.364 parser (CheckResVersionState) reads these fields:
That’s every field the parser handles. A live response carries fewer: the iOS check-version response for 1.0.344 (786), fetched on 2026-10-04, held only
client_config, downloadurl, firstLaunchForceUpdateMsg, hotUpdateMsg, lwfile2, resMsg, updateType, and warmup.
updateType meanings (1.0.364 C#):
The
Login response can carry updateType too; with 2, the client enters its app-update state instead of waiting for init. On 2026-10-04 the iOS 1.0.344 app got updateType=3 from both check-version and Login, with the Login response naming new_version 1.0.350 (observed live). goclient now logs a warning when check-version returns updateType=2, since Logins claiming that build are likely to start failing too.
resVersion
Login’s resVersion is GetResVersion() in the 1.0.364 C# (static-analysis-only):
GameRes and DllRes versions from hotUpdateMsg, the first | field of lwfile2, and the first , field of table_version and locale.
Only the {GameRes}.{DllRes}_{lwfile2 version}F prefix can be derived from a live response. The real iOS app sent 2159.1505_821F_39516.23570 on 2026-10-04, and that day’s check-version response returned GameRes 2159, DllRes 1505, and lwfile2 version 821, matching the prefix. It carried no table_version or locale field, and neither 39516 nor 23570 appears anywhere in it. The tail’s source is unknown (local state or another endpoint), and its mapping to table_version and locale is static-analysis-only. goclient sends "0", which the server has accepted for months.
Hot-update transport & patch format
Three independently-versioned payloads, compared via the fields above and patched separately:- Asset bundles (incl. C#
.mdlassemblies): standard UnityAssetBundle, tracked by thedllresmanifest. - Lua bundle: one flat
LWLFfile, not wrapped in an AssetBundle at all. - Data tables: the plain-ZIP
table_*.dataarchive.
Key/nonce are derived once from hardcoded dummy constants via two self-referential ChaCha8 passes (reproduced independently in Python and confirmed reproducible):
CDN
NetworkURLConfig.GetDownloadURL, LWLuaFileUtil):
<app id> is the bundle identifier: com.fun.lastwar.gp for Android, com.lastwar.ios for iOS. The .bz2 is plain bzip2, not ChaCha-wrapped; if a download ever is wrapped (PRB), the client unwraps it first. On disk, the client re-encrypts the bundle as LWLF file version 2, which never affects the CDN payload. Old versions stay hosted: every version probed between 780 and 826 returned HTTP 200 on 2026-10-04.
Lua bundle versions seen on 2026-10-04:
At the command-catalog level, both live bundles match the 1.0.364 APK. Their differences are debug-only UI modules, a removed diagnostic, and a handful of changed chunks outside
Net/. Every request schema goclient uses is identical across all four versions, see Command reference.