# Android-порт клиента Цель — тот же клиент `gmod-rs` (SDL3 + wgpu), запускаемый как APK на Android 12+ (API 31+). Отдельного «мобильного движка» нет: карта, физика, Lua и рендер общие с десктопом. ## Ассеты: полный набор или встроенный минимум Ассеты в APK не обязательны: клиент читает их из каталога `files/gmod_server/server` (см. `MainActivity`). Есть два пути. **Полный набор (универсально, но долго копировать).** `adb push` всей установки — 6,7 ГБ; после `adb uninstall` каталог `Android/data/<пакет>/files` стирается, ассеты нужно заливать заново. **Встроенный минимум (самодостаточный APK).** Команда ```bash cargo run -q -p client -- fs pack gm_construct --assets ~/gmod_server/server --out /tmp/pack ``` записывает все файлы, которые клиент реально читает (мир, модели игрока и оружия, автозагрузка Lua), и кладёт их в `/tmp/pack/garrysmod/...` вместе с картой. Замер для `gm_construct`: **335 файлов, 27,0 МБ + карта 35,0 МБ = 62,1 МБ** (в tar.gz — 31 МБ) против 6,7 ГБ установки. ```bash cp -a /tmp/pack android/assets/gmod ./android/build.sh # APK соберётся с assets/gmod внутри ``` `MainActivity` при первом запуске распаковывает `assets/gmod` в `files/gmod_server/server`, если карты там ещё нет. Итоговый APK — **38 МБ** вместо 6,3 МБ без ассетов. Каталог `android/assets/` в `.gitignore`: ассеты GMod не коммитим. ## Сборка ```bash ./android/build.sh # arm64-v8a, APK для телефона ANDROID_ABI=x86_64 ./android/build.sh # x86_64, для эмулятора ``` Скрипт использует SDK/NDK, `cargo`, `aapt2`, `d8`, `zipalign`, `apksigner` (Gradle не нужен). Результат — `target/android/gmod-rs-debug.apk` (подписан debug-ключом `android/debug.keystore`). Подробности и команды установки — в `android/README.md`. ## Крейты и target cfg - `crates/client` теперь и библиотека (`src/lib.rs`), и бинарь (`src/main.rs`). Бинарь вызывает `client::run(args)`, Android-сборка — `cargo build --lib` с `crate-type = ["cdylib", "rlib"]`. - Экспорт `SDL_main` (в `lib.rs` под `cfg(target_os = "android")`) — точка входа для штатной Java-обвязки SDL3 (`SDLActivity`). - `steamworks` подключён только для не-Android; команда `net` на Android отсутствует. - `mlua`: на десктопе LuaJIT + `vendored`, на Android — Lua 5.4 + `vendored` (LuaJIT не собирается кросс-компилятором mlua). API GMod-скриптов сохраняется. - `tracing` на Android пишет в logcat (`adb logcat -s gmod-rs`), а не в stdout. ## APK - Java-классы SDL3 (`org.libsdl.app.*`) взяты из `sdl3-src` (zlib-лицензия) и лежат в `android/app/src/main/java`. - `MainActivity` наследует `SDLActivity`, фиксирует ландшафт и передаёт нативной части аргументы `map gm_construct --assets /...`. - Нативные библиотеки пакуются как `lib/arm64-v8a/libSDL3.so` и `libmain.so` (внутри — `libclient.so` с `SDL_main`). - Ассеты не входят в APK: их кладут во внешний каталог приложения (`Android/data/org.gmodrs.client/files/gmod_server/server`), см. README. ## Управление Обрабатываются `SDL_EVENT_FINGER_*`; синтетические события мыши от касаний отключены (`SDL_TOUCH_MOUSE_EVENTS=0`): - левая половина экрана — аналоговый стик (forward/right идут в тот же `Player::update`, что WASD); - правая половина — обзор свайпом (приращение углов камеры); - кнопки `JUMP`/`DUCK` — прыжок (с защёлкой короткого тапа) и присед; - на Android движение сразу бегом (отдельной кнопки Shift нет). ## Проверка - `cargo clippy -p client --lib --target aarch64-linux-android -- -D warnings`. - Эмулятор API 35 x86_64: APK запускается, `gm_construct` грузится, кадры рисуются (SwiftShader, ~11–14 fps), стик/обзор/прыжок проверены через `adb shell input`. - Реальное arm64-устройство не проверялось (нет устройства); при отладке — `adb logcat -s gmod-rs SDL`.