After building the APK, android/build.sh now picks the attached device (ANDROID_SERIAL for several),
installs the APK (reinstalling on a signature mismatch), syncs the zh client into files/Client and, with
--launch, wakes the phone and starts the app. Without a device it only builds.
push-client.sh is now incremental (android/sync_client.py): the device keeps files/Client/.mt_sync
(size, mtime, path of what the last sync wrote), so later syncs send only new and changed files as one
tar streamed through `adb shell -T run-as` (no copy in /data/local/tmp) and delete the ones gone
locally. Only game resources are synced; settings and logs the app writes there are kept. --locale zh
rebuilds build/zh-locale/Client first when its inputs changed. android/adb_env.sh picks adb and falls
back to server port 5038 when :5037 cannot bind.
Verified against a fake adb device: first sync (1.4 GB, byte-identical), no-op resync, changed files,
deletions, locale switch, --full, the install/launch path and the no-device path.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
branding/icon/icon.svg (a cracked Metin stone with glowing runes, inside a studded gold ring, in front of
a blood moon over ink mountains) is the single source; build_icons.sh renders it with headless Chrome and
writes the committed outputs: Android legacy + adaptive mipmaps (wired into the manifest), the macOS
AppIcon.icns and the iOS AppIcon.appiconset. scripts/package_mac_app.sh wraps mt_native_render into a
local Metin2.app using that icon.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>