Add proxy/VPN/telegram launchd and emergency runbooks; reorganize apps docs; document JA3 CrossOver runbook and Wine troubleshooting; add GOG/HoMM game scripts, disk cleanup guides, and gitea push-via-proxy helper. Ignore temp/. Co-authored-by: Cursor <cursoragent@cursor.com>
204 lines
5.2 KiB
Bash
Executable File
204 lines
5.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# JA3: multipart GOG → innoextract в bottle (без Wine-Inno). Экономия диска: .bin удаляются по ходу.
|
|
set -euo pipefail
|
|
GOG_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
# shellcheck source=config.sh
|
|
source "${GOG_DIR}/config.sh"
|
|
|
|
JA3_GAMES_DIR="${JA3_GAMES_DIR:-${HOME}/Games}"
|
|
JA3_PREFIX='setup_jagged_alliance_3_1.5.2_(80730)'
|
|
JA3_EXE="${JA3_GAMES_DIR}/${JA3_PREFIX}.exe"
|
|
JA3_TARGET="${BOTTLE_DIR}/drive_c/GOG Games/Jagged Alliance 3"
|
|
MARKER="${BOTTLE_DIR}/.ja3_installed"
|
|
LOG="/tmp/ja3-innoextract-${BOTTLE_NAME}.log"
|
|
JA3_MIN_FREE_MB="${JA3_MIN_FREE_MB:-800}"
|
|
JA3_KEEP_BINS="${JA3_KEEP_BINS:-0}"
|
|
|
|
gog_disk_free_mb() {
|
|
local kb
|
|
kb="$(gog_disk_free_kb)"
|
|
echo $((kb / 1024))
|
|
}
|
|
|
|
gog_disk_watch() {
|
|
local min_mb="$1"
|
|
local free
|
|
free="$(gog_disk_free_mb)"
|
|
if [[ "${free}" -lt "${min_mb}" ]]; then
|
|
echo "❌ Мало места на диске: ${free} MB свободно (нужно ≥${min_mb} MB)" >&2
|
|
df -h "$(gog_data_volume_path)" | awk 'NR==2' >&2
|
|
return 1
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
gog_ja3_safe_cleanup() {
|
|
local freed=0
|
|
local d f
|
|
|
|
for d in \
|
|
"${GAMES_CACHE_DIR}/gog-galaxy-extract-gog-bottle" \
|
|
"${GAMES_CACHE_DIR}/ja3-extract-test" \
|
|
"${GAMES_CACHE_DIR}/ja3-innoextract-staging"; do
|
|
if [[ -d "${d}" ]]; then
|
|
local sz
|
|
sz="$(du -sk "${d}" | awk '{print $1}')"
|
|
rm -rf "${d}"
|
|
freed=$((freed + sz))
|
|
echo " удалён cache: ${d}"
|
|
fi
|
|
done
|
|
|
|
if [[ -f "${GAMES_CACHE_DIR}/setup_galaxy.exe" ]] \
|
|
&& [[ -f "${BOTTLE_DIR}/drive_c/Program Files (x86)/GOG Galaxy/GalaxyClient.exe" ]]; then
|
|
f="${GAMES_CACHE_DIR}/setup_galaxy.exe"
|
|
sz="$(du -sk "${f}" | awk '{print $1}')"
|
|
rm -f "${f}"
|
|
freed=$((freed + sz))
|
|
echo " удалён setup_galaxy.exe (Galaxy уже в bottle)"
|
|
fi
|
|
|
|
if [[ "${freed}" -gt 0 ]]; then
|
|
echo "Освобождено ~$((freed / 1024)) MB (cache)"
|
|
fi
|
|
}
|
|
|
|
ja3_bin_path() {
|
|
echo "${JA3_GAMES_DIR}/${JA3_PREFIX}-$1.bin"
|
|
}
|
|
|
|
ja3_delete_bin() {
|
|
local n="$1"
|
|
local p
|
|
p="$(ja3_bin_path "${n}")"
|
|
if [[ -f "${p}" ]]; then
|
|
rm -f "${p}"
|
|
echo " 🗑 удалён $(basename "${p}") (~$(du -sh "${p}" 2>/dev/null | cut -f1 || echo '?'))"
|
|
gog_disk_watch "${JA3_MIN_FREE_MB}" || true
|
|
fi
|
|
}
|
|
|
|
ja3_delete_all_bins() {
|
|
local n
|
|
for n in 1 2 3 4; do
|
|
ja3_delete_bin "${n}" || true
|
|
done
|
|
if [[ -f "${JA3_EXE}" && "${JA3_KEEP_BINS}" != "1" ]]; then
|
|
rm -f "${JA3_EXE}"
|
|
echo " 🗑 удалён $(basename "${JA3_EXE}")"
|
|
fi
|
|
}
|
|
|
|
ja3_watch_bins() {
|
|
local line opened=0
|
|
while IFS= read -r line; do
|
|
printf '%s\n' "${line}"
|
|
case "${line}" in
|
|
*"Opening \"${JA3_PREFIX}-2.bin\""*)
|
|
ja3_delete_bin 1
|
|
opened=2
|
|
;;
|
|
*"Opening \"${JA3_PREFIX}-3.bin\""*)
|
|
ja3_delete_bin 2
|
|
opened=3
|
|
;;
|
|
*"Opening \"${JA3_PREFIX}-4.bin\""*)
|
|
ja3_delete_bin 3
|
|
opened=4
|
|
;;
|
|
esac
|
|
gog_disk_watch "${JA3_MIN_FREE_MB}" || return 1
|
|
done
|
|
if [[ "${opened}" -ge 4 ]]; then
|
|
ja3_delete_bin 4 || true
|
|
fi
|
|
}
|
|
|
|
verify() {
|
|
local n
|
|
[[ -f "${JA3_EXE}" ]] || {
|
|
echo "❌ Нет: ${JA3_EXE}"
|
|
return 1
|
|
}
|
|
for n in 1 2 3 4; do
|
|
[[ -f "$(ja3_bin_path "${n}")" ]] || {
|
|
echo "❌ Нет: $(ja3_bin_path "${n}")"
|
|
return 1
|
|
}
|
|
done
|
|
command -v innoextract >/dev/null 2>&1 || {
|
|
echo "❌ brew install innoextract"
|
|
return 1
|
|
}
|
|
}
|
|
|
|
main() {
|
|
verify || exit 1
|
|
gog_wine_check
|
|
|
|
if [[ -f "${JA3_TARGET}/JA3.exe" ]]; then
|
|
echo "JA3 уже установлен: ${JA3_TARGET}/JA3.exe"
|
|
exit 0
|
|
fi
|
|
|
|
bash "${GOG_DIR}/emergency-stop.sh" || true
|
|
|
|
echo "=== Очистка cache (без трогания архивов игры) ==="
|
|
gog_ja3_safe_cleanup
|
|
|
|
gog_disk_watch "${JA3_MIN_FREE_MB}" || {
|
|
echo "❌ Перед установкой нужно ≥$((JA3_MIN_FREE_MB / 1024)) GB свободно."
|
|
exit 1
|
|
}
|
|
|
|
echo ""
|
|
echo "Свободно на Data: $(gog_disk_free_mb) MB"
|
|
echo "Распаковка JA3 → ${JA3_TARGET}"
|
|
echo "Лог: ${LOG}"
|
|
echo "(архивы .bin удаляются по мере чтения innoextract)"
|
|
echo ""
|
|
|
|
rm -rf "${JA3_TARGET}"
|
|
mkdir -p "${JA3_TARGET}"
|
|
: >"${LOG}"
|
|
|
|
cd "${JA3_GAMES_DIR}"
|
|
set +e
|
|
innoextract -e -m -d "${JA3_TARGET}" "$(basename "${JA3_EXE}")" 2>&1 \
|
|
| tee "${LOG}" | ja3_watch_bins
|
|
local rc=${PIPESTATUS[0]}
|
|
set -e
|
|
|
|
if [[ "${rc}" -ne 0 ]]; then
|
|
echo ""
|
|
echo "❌ innoextract exit ${rc}"
|
|
tail -15 "${LOG}" 2>/dev/null || true
|
|
df -h "$(gog_data_volume_path)" | awk 'NR==2'
|
|
if [[ "${JA3_CLEANUP_PARTIAL:-1}" == "1" ]]; then
|
|
echo "Удаляю незавершённую распаковку в bottle…"
|
|
rm -rf "${JA3_TARGET}"
|
|
fi
|
|
exit 1
|
|
fi
|
|
|
|
if [[ -f "${JA3_TARGET}/JA3.exe" ]]; then
|
|
bash "${GOG_DIR}/finish-ja3-layout.sh"
|
|
date -u +"%Y-%m-%dT%H:%M:%SZ" >"${MARKER}"
|
|
if [[ "${JA3_KEEP_BINS}" != "1" ]]; then
|
|
echo ""
|
|
echo "Удаляю GOG-архивы (~15 GB)…"
|
|
ja3_delete_all_bins
|
|
fi
|
|
echo ""
|
|
echo "OK: JA3 установлен."
|
|
echo " Свободно: $(gog_disk_free_mb) MB"
|
|
echo " Запуск: bash ${GOG_DIR}/run-ja3.sh"
|
|
else
|
|
echo "❌ JA3.exe не найден"
|
|
find "${JA3_TARGET}" -maxdepth 2 -iname 'JA3.exe' 2>/dev/null | head -5
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
main "$@"
|