Expand local_machine docs and automation for connectivity, games, and ops.

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>
This commit is contained in:
ahauimix
2026-06-01 08:12:19 +03:00
parent a39ef89125
commit 1938b7c743
135 changed files with 9933 additions and 388 deletions

238
scripts/games/gog/config.sh Executable file
View File

@@ -0,0 +1,238 @@
# GOG-only Wine/Whisky — без Steam, HoMM, export_wine_env_steam.
GOG_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
GAMES_DIR="$(cd "${GOG_DIR}/.." && pwd)"
GAMES_CACHE_DIR="${GAMES_DIR}/cache"
_env_file="${GOG_DIR}/bottle.env"
if [[ -f "${_env_file}" ]]; then
# shellcheck source=/dev/null
source "${_env_file}"
elif [[ -n "${GOG_BOTTLE_ID:-}" ]]; then
BOTTLE_ID="${GOG_BOTTLE_ID}"
BOTTLE_NAME="${GOG_BOTTLE_NAME:-GOG-Install}"
else
echo "❌ Нет bottle для GOG."
echo " 1) Whisky → New Bottle (Windows 10 64-bit), имя GOG-Install"
echo " 2) bash ${GOG_DIR}/list-bottles.sh"
echo " 3) bash ${GOG_DIR}/use-bottle.sh <UUID>"
echo ""
echo " Не используйте bottle HoMM-OldenEra — там Steam, дампы и winedbg."
exit 1
fi
unset _env_file
_FRANKE="${HOME}/Library/Containers/com.franke.Whisky/Bottles/${BOTTLE_ID}"
_ISAAC="${HOME}/Library/Containers/com.isaacmarovitz.Whisky/Bottles/${BOTTLE_ID}"
if [[ -d "${_FRANKE}/drive_c" ]]; then
BOTTLE_DIR="${_FRANKE}"
WHISKY_LIBS="${HOME}/Library/Application Support/com.franke.Whisky"
elif [[ -d "${_ISAAC}/drive_c" ]]; then
BOTTLE_DIR="${_ISAAC}"
WHISKY_LIBS="${HOME}/Library/Application Support/com.isaacmarovitz.Whisky"
else
echo "❌ Bottle не найден: ${BOTTLE_NAME} (${BOTTLE_ID})"
echo " Проверьте UUID: bash ${GOG_DIR}/list-bottles.sh"
exit 1
fi
unset _FRANKE _ISAAC
WINE64="${WHISKY_LIBS}/Libraries/Wine/bin/wine64"
WINE_LIB="${WHISKY_LIBS}/Libraries/Wine/lib"
WINEPATH_BIN="${WHISKY_LIBS}/Libraries/Wine/bin/winepath"
gog_data_volume_path() {
if [[ -d /System/Volumes/Data ]]; then
echo /System/Volumes/Data
else
echo "${HOME}"
fi
}
gog_disk_free_kb() {
df -k "$(gog_data_volume_path)" | awk 'NR==2 {print $4}'
}
gog_disk_guard() {
local min_gb="${1:-5}"
local min_kb free_kb
min_kb=$((min_gb * 1024 * 1024))
free_kb="$(gog_disk_free_kb)"
if [[ "${free_kb}" -lt "${min_kb}" ]]; then
echo "❌ Мало места (<${min_gb} GB на Data)."
return 1
fi
return 0
}
gog_swap_used_mb() {
local used
used="$(sysctl vm.swapusage 2>/dev/null | sed -n 's/.*used = \([0-9.]*\)M.*/\1/p')"
[[ -n "${used}" ]] || return 1
printf '%.0f' "${used}"
}
gog_swap_guard() {
local max_mb="${1:-400}"
local used
used="$(gog_swap_used_mb)" || return 0
if awk -v u="${used}" -v m="${max_mb}" 'BEGIN{exit !(u>=m)}'; then
echo "❌ Swap уже ~${used}MB (лимит ${max_mb}MB) — запуск GOG/Wine запрещён."
echo " bash ${GOG_DIR}/emergency-stop.sh"
echo " затем перезагрузка Mac (swap macOS отдаёт медленно)"
return 1
fi
return 0
}
# JA3/CrossOver: жёсткий стоп только если swap высокий И Wine/JA3 ещё живы.
# «Залипший» swap после закрытия (macOS не отдал) — предупреждение, запуск разрешён.
gog_wine_or_ja3_active() {
pgrep -f 'JA3\.exe|wineserver|wine64-preloader|winedbg|wine64\.exe|CrossOver.*wine' >/dev/null 2>&1
}
gog_swap_guard_ja3_launch() {
local soft_mb="${1:-1200}"
local hard_mb="${2:-4096}"
local used
used="$(gog_swap_used_mb)" || return 0
if [[ "${JA3_IGNORE_SWAP:-0}" == "1" ]]; then
echo "⚠️ JA3_IGNORE_SWAP=1 — swap ~${used}MB"
return 0
fi
if gog_wine_or_ja3_active; then
if awk -v u="${used}" -v m="${soft_mb}" 'BEGIN{exit !(u>=m)}'; then
echo "❌ Swap ~${used}MB и Wine/JA3 ещё работают (лимит ${soft_mb}MB)."
echo " bash ${GOG_DIR}/reset-ja3-crossover.sh или bash ${GOG_DIR}/emergency-stop.sh"
echo " затем reboot Mac. Или: JA3_IGNORE_SWAP=1 bash …/run-ja3-crossover.sh"
return 1
fi
return 0
fi
if awk -v u="${used}" -v m="${hard_mb}" 'BEGIN{exit !(u>=m)}'; then
echo "❌ Swap ~${used}MB (лимит ${hard_mb}MB) — reboot Mac."
echo " Или: JA3_IGNORE_SWAP=1 bash …/run-ja3-crossover.sh"
return 1
fi
if awk -v u="${used}" -v m="${soft_mb}" 'BEGIN{exit !(u>=m)}'; then
echo "⚠️ Swap ~${used}MB — залип после прошлых сессий (Wine не запущен). Запуск JA3…"
echo " (reboot снизит swap; JA3_IGNORE_SWAP=1 — принудительный игнор)"
fi
return 0
}
# Виртуальный стол Wine — окно CEF часто «есть в логах», но не видно на macOS без /desktop.
GOG_VDESKTOP="${GOG_VDESKTOP:-1280x800}"
# 0 = прямой GalaxyClient (рекомендуется; vdesktop — в Whisky Metadata или launch-galaxy-ui.sh).
GOG_USE_WINEVDESKTOP="${GOG_USE_WINEVDESKTOP:-0}"
# GOG_LAUNCH_FG=1 — exec в текущем терминале (лучше для видимости окна, блокирует shell).
GOG_LAUNCH_FG="${GOG_LAUNCH_FG:-0}"
# GOG_CEF_PROFILE=steam — добавить -cef-in-process-gpu (A/B если login пустой).
# /deelevated — обязательно в Wine (иначе DeelevateStrategy + exit -31, см. WineHQ #41584).
GOG_GALAXY_BASE_ARGS="${GOG_GALAXY_BASE_ARGS:-/runWithoutUpdating /deelevated}"
GOG_GALAXY_CEF_ARGS="${GOG_GALAXY_CEF_ARGS:--allosarches -cef-force-32bit -no-cef-sandbox -cef-disable-gpu}"
gog_galaxy_cef_args_array() {
local -a a=(${GOG_GALAXY_BASE_ARGS} ${GOG_GALAXY_CEF_ARGS})
if [[ "${GOG_CEF_PROFILE:-}" == "steam" ]]; then
a+=(-cef-in-process-gpu)
fi
printf '%s\n' "${a[@]}"
}
export_wine_env_gog() {
export WINEPREFIX="${BOTTLE_DIR}"
export WINEMSYNC=1
unset WINEESYNC 2>/dev/null || true
local _wine_ext="${WHISKY_LIBS}/Libraries/Wine/lib/external"
if [[ -d "${_wine_ext}/D3DMetal.framework" ]]; then
export DYLD_FRAMEWORK_PATH="${_wine_ext}:${DYLD_FRAMEWORK_PATH:-}"
export DYLD_LIBRARY_PATH="${_wine_ext}:${WINE_LIB}:${DYLD_LIBRARY_PATH:-}"
else
export DYLD_LIBRARY_PATH="${WINE_LIB}:${DYLD_LIBRARY_PATH:-}"
fi
unset _wine_ext
export WINEDLLOVERRIDES="gdiplus=n,b"
unset DXVK_ASYNC DXVK_HUD 2>/dev/null || true
export WINEDEBUG=-all
export MVK_CONFIG_LOG_LEVEL=0
}
ja3_gptk_available() {
[[ -d "${WHISKY_LIBS}/Libraries/Wine/lib/external/D3DMetal.framework" ]] && return 0
[[ -f "${WHISKY_LIBS}/Libraries/.gptk_installed" ]] && return 0
[[ -d "${WHISKY_LIBS}/D3DMetal" ]] && return 0
[[ -d "${WHISKY_LIBS}/GPTK" ]] && return 0
return 1
}
ja3_bottle_uses_d3dmetal() {
local meta="${BOTTLE_DIR}/Metadata.plist"
[[ -f "${meta}" ]] || return 1
plutil -extract graphicsConfig.backend raw -o - "${meta}" 2>/dev/null | grep -q d3dMetal
}
ja3_dxmt_installed() {
[[ -f "${BOTTLE_DIR}/.ja3_dxmt_installed" ]]
}
# JA3 = D3D12 (Porting Kit / GPTK). Без GPTK — best-effort D3D11+DXVK (d3d12=d).
export_wine_env_ja3() {
export_wine_env_gog
if ja3_gptk_available || ja3_bottle_uses_d3dmetal; then
export WINED3DMETAL=1
unset DXVK_ASYNC DXVK_HUD DXVK_CONFIG_FILE 2>/dev/null || true
# builtin d3d12/dxgi + libd3dshared.so; без n,b на GPTK PE
export WINEDLLOVERRIDES="libxess,xess,dxcompiler,dxil,nvngx_dlss,XeFX,XeFX_Loader=d;gdiplus=n,b"
return 0
fi
if ja3_dxmt_installed; then
# DXMT builtin: не ставить dxgi/d3d11=n,b (ломает загрузку, c000007b).
export WINEDLLOVERRIDES="d3d12=d;libxess,xess,dxcompiler,dxil,nvngx_dlss,XeFX,XeFX_Loader=d;gdiplus=n,b"
else
export WINEDLLOVERRIDES="d3d11,d3d10core=n,b;d3d12=d;libxess,xess,dxcompiler,dxil,nvngx_dlss,XeFX,XeFX_Loader=d;gdiplus=n,b"
fi
unset DXVK_ASYNC DXVK_HUD DXVK_CONFIG_FILE 2>/dev/null || true
export SDL_VIDEO_MAC_FULLSCREEN_SPACES="${SDL_VIDEO_MAC_FULLSCREEN_SPACES:-0}"
export MVK_CONFIG_RESUME_LOST_DEVICE=1
}
export_wine_env_ja3_d3dmetal() {
export_wine_env_gog
export WINED3DMETAL=1
export WINEDLLOVERRIDES="libxess,xess,dxcompiler,dxil,nvngx_dlss,XeFX,XeFX_Loader=d;gdiplus=n,b"
unset DXVK_ASYNC DXVK_HUD 2>/dev/null || true
}
gog_steam_client_in_bottle() {
local f
[[ -d "${BOTTLE_DIR}/drive_c/Program Files (x86)/Steam" ]] && return 0
[[ -f "${BOTTLE_DIR}/drive_c/Program Files (x86)/Steam/steam.exe" ]] && return 0
f="$(find "${BOTTLE_DIR}/drive_c" -maxdepth 4 -iname 'steam.exe' -print -quit 2>/dev/null || true)"
[[ -n "${f}" ]]
}
gog_assert_no_steam_client() {
if gog_steam_client_in_bottle; then
echo "В bottle ${BOTTLE_NAME} найден Steam client — контур GOG/JA3 без Steam."
echo " bash ${GOG_DIR}/purge-steam-from-bottle.sh"
return 1
fi
if [[ "${BOTTLE_ID}" == "38412122-AAE1-4831-9F2E-6A0EB364B3F9" ]]; then
echo "❌ Это bottle HoMM-OldenEra (Steam). JA3 только в GOG-Install:"
echo " bash ${GOG_DIR}/use-bottle.sh <UUID-GOG-Install>"
return 1
fi
return 0
}
gog_wine_check() {
if [[ ! -x "${WINE64}" ]]; then
echo "Нет Wine: bash ${GAMES_DIR}/install-whiskywine-manual.sh"
exit 1
fi
if [[ ! -d "${BOTTLE_DIR}/drive_c" ]]; then
echo "❌ Нет drive_c в ${BOTTLE_DIR}"
echo " Откройте bottle «${BOTTLE_NAME}» в Whisky один раз."
exit 1
fi
}