Compare commits
5 Commits
2ecc0240f9
..
master
| Author | SHA1 | Date | |
|---|---|---|---|
| db508a46cd | |||
| b617aa6ea6 | |||
| 362feb044f | |||
| 03e72a8263 | |||
| ae37f1a71f |
@@ -1,6 +1,6 @@
|
||||
# Linux Game Manager Core Map
|
||||
|
||||
Last refreshed: 2026-04-12
|
||||
Last refreshed: 2026-04-14
|
||||
|
||||
## Top-Level Structure
|
||||
|
||||
@@ -16,7 +16,7 @@ Last refreshed: 2026-04-12
|
||||
|
||||
- Installers: 42 (`.install/*.sh`)
|
||||
- Launcher definitions: 42 (`.launch/*.game`)
|
||||
- Launcher runnable entries: 30 (`.launch/*.sh`, both symlinks and files)
|
||||
- Launcher runnable entries: 31 (`.launch/*.sh`, both symlinks and files)
|
||||
- Update scripts: 5 (`.update/*.sh`)
|
||||
|
||||
Regenerate this snapshot with:
|
||||
@@ -30,7 +30,8 @@ python3 .codex/skills/linux-game-manager-dev/scripts/audit_game_catalog.py
|
||||
1. **Install flow**
|
||||
- `game_installer` builds menu from `.install/*.sh`.
|
||||
- Selected installer is sourced in the current shell.
|
||||
- Shared downloads try `curl` first, fall back to `wget` when available, and reject obvious HTML error pages for unknown file types.
|
||||
- Shared downloads try `curl` first, fall back to `wget` when available, validate archive payloads before install, and reject obvious HTML error pages for unknown file types.
|
||||
- `download_named()` shares the same cache validation path as `download()`, so resolved asset URLs must still produce a valid payload for their file extension.
|
||||
- If `.launch/<game>.game` exists and `.launch/<game>.sh` does not, the manager creates a symlink using the repository root, even if the installer changed directories.
|
||||
|
||||
2. **Launch flow**
|
||||
@@ -40,7 +41,7 @@ python3 .codex/skills/linux-game-manager-dev/scripts/audit_game_catalog.py
|
||||
|
||||
3. **Removal flow**
|
||||
- `game_removal` resolves launcher entry to real script.
|
||||
- It extracts the first `installPath`-containing line from launcher script to infer directory to remove.
|
||||
- It scans launcher script lines for a non-comment `${installPath}/...` path assignment and uses that to infer the directory to remove.
|
||||
- If no `installPath` reference is found, only launcher entry is removed.
|
||||
|
||||
4. **Update flow**
|
||||
@@ -72,7 +73,7 @@ python3 .codex/skills/linux-game-manager-dev/scripts/audit_game_catalog.py
|
||||
|
||||
- Mismatched `.install/<Game>.sh` vs `.launch/<Game>.game` names create orphaned or invisible entries.
|
||||
- Missing `installPath` reference in launcher prevents full uninstall.
|
||||
- `game_removal` parses the first `installPath` match in launcher text, so comments containing `installPath` can break removal path detection.
|
||||
- `game_removal` expects a concrete `${installPath}/...` path in the launcher; indirect path construction can prevent removal from finding the install directory.
|
||||
- Missing `run_update()` in `.update` scripts breaks update flow.
|
||||
- Bypassing shared download helpers risks cache and validation regressions.
|
||||
- Installers may change the working directory; repository-relative manager paths must therefore use the resolved script root rather than `${0%/*}`.
|
||||
|
||||
@@ -127,5 +127,4 @@ Use this pattern for Python games installed with `uv` when runtime speech suppor
|
||||
- Launch via `uv run ...` from the same directory used for `uv sync`.
|
||||
|
||||
3. Removal safety:
|
||||
- Ensure first `installPath` line in launcher points to a path that lets `game_removal` infer the game root correctly.
|
||||
- Do not put `installPath` in comments above that path line, because removal currently grabs the first matching line.
|
||||
- Ensure the launcher contains a concrete `${installPath}/...` path assignment so `game_removal` can infer the game root correctly.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# shellcheck shell=bash disable=SC2154 # installPath and cache are set by linux-game-manager.sh
|
||||
check_architecture x86_64
|
||||
get_installer "omega-reach-linux-x64.zip" "https://shiftbacktick.itch.io/the-omega-reach"
|
||||
get_installer "the-omega-reach-linux-x64.zip" "https://shiftbacktick.itch.io/the-omega-reach"
|
||||
mkdir -p "${installPath}/Omega Reach"
|
||||
unzip -d "${installPath}/Omega Reach" "${cache}/omega-reach-linux-x64.zip"
|
||||
chmod +x "${installPath}/Omega Reach/omega-reach"
|
||||
unzip -d "${installPath}/Omega Reach" "${cache}/the-omega-reach-linux-x64.zip"
|
||||
chmod +x "${installPath}/Omega Reach/the-omega-reach"
|
||||
chmod +x "${installPath}/Omega Reach/chrome-sandbox"
|
||||
|
||||
+19
-2
@@ -1,7 +1,24 @@
|
||||
#!/usr/bin/env bash
|
||||
# shellcheck disable=SC2154 # set by linux-game-manager.sh
|
||||
check_architecture x86_64
|
||||
download "https://github.com/diamondStar35/top_speed/releases/download/release-build/TopSpeed-linux-x64-Release-v-2026.4.13.1.zip"
|
||||
|
||||
releaseMetadataFile="TopSpeed-release-build.json"
|
||||
releaseMetadataPath="${cache}/${releaseMetadataFile}"
|
||||
releaseMetadataUrl="https://api.github.com/repos/diamondStar35/top_speed/releases/tags/release-build"
|
||||
assetPattern='^TopSpeed-linux-x64-Release-v-.*\.zip$'
|
||||
|
||||
rm -f "${releaseMetadataPath}"
|
||||
download_named "${releaseMetadataFile}" "${releaseMetadataUrl}"
|
||||
|
||||
assetName="$(jq -r --arg assetPattern "${assetPattern}" '.assets[] | select(.name | test($assetPattern)) | .name' "${releaseMetadataPath}" | head -n 1)"
|
||||
assetUrl="$(jq -r --arg assetPattern "${assetPattern}" '.assets[] | select(.name | test($assetPattern)) | .browser_download_url' "${releaseMetadataPath}" | head -n 1)"
|
||||
|
||||
if [[ -z "${assetName}" ]] || [[ -z "${assetUrl}" ]] || [[ "${assetName}" == "null" ]] || [[ "${assetUrl}" == "null" ]]; then
|
||||
ui_msgbox "Linux Game Manager" "Linux Game Manager" "Unable to find the latest Top Speed Linux download in the GitHub release metadata."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
download_named "${assetName}" "${assetUrl}"
|
||||
mkdir -p "${installPath}/TopSpeed"
|
||||
unzip -o -d "${installPath}/TopSpeed" "${cache}/TopSpeed-linux-x64-Release-v-2026.4.13.1.zip"
|
||||
unzip -o -d "${installPath}/TopSpeed" "${cache}/${assetName}"
|
||||
chmod +x "${installPath}/TopSpeed/TopSpeed"
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
open_url "https://play.oriolgomez.com/"
|
||||
@@ -1,4 +1,4 @@
|
||||
# shellcheck shell=bash disable=SC2154 # installPath is set by linux-game-manager.sh
|
||||
gamePath="${installPath}/Omega Reach"
|
||||
pushd "${gamePath}" || return 1
|
||||
"${gamePath}/omega-reach"
|
||||
"${gamePath}/the-omega-reach"
|
||||
|
||||
@@ -7,6 +7,8 @@ Installer and launcher for accessible to the blind games that run natively in Li
|
||||
|
||||
As the project grows, more dependencies will most likely be added. When LGM is launched, it will check to make sure it has the required dependencies for it to do the work of downloading and extracting the game. Note that because every distro has a different package manager, dependencies for games themselves will not be resolved. Please consult the game's documentation to find out what is needed for the game to run.
|
||||
|
||||
Current base dependencies checked on launch: `7z`, `curl`, `dialog`, `jq`, `yad`, and `unzip`.
|
||||
|
||||
## Disabling game entries
|
||||
|
||||
To disable a game entry without deleting its script, set the first line of the script to start with `#//`.
|
||||
|
||||
+57
-38
@@ -556,44 +556,56 @@ download() {
|
||||
ui_msgbox "Linux Game Manager" "Linux Game Manager" "Could not download \"$i\"...\n\ndownload exit codes: ${downloadAttemptExitCodes}\nError details: ${downloadErrorLog}"
|
||||
exit 1
|
||||
fi; } | ui_progressbox "Linux Game Manager" "Downloading \"$dest\" from \"$i\""
|
||||
local downloadError=0
|
||||
case "${dest##*.}" in
|
||||
"pk3"|"zip")
|
||||
unzip -tq "${cache}/${dest}" | ui_progressbox "Linux Game Manager" "Validating ${dest##*.} file"
|
||||
downloadError=$?
|
||||
;;
|
||||
"7z")
|
||||
7z t "${cache}/${dest}" | ui_progressbox "Linux Game Manager" "Validating 7z file"
|
||||
downloadError=$?
|
||||
;;
|
||||
"exe")
|
||||
# Check if it's a valid Windows executable by looking at the MZ header
|
||||
if ! hexdump -n 2 -v -e '/1 "%02X"' "${cache}/${dest}" | grep -q "4D5A"; then
|
||||
downloadError=0
|
||||
fi
|
||||
;;
|
||||
"wad")
|
||||
if [[ "$(file -b --mime-type "${cache}/${dest}")" == "application/octet-stream" ]]; then
|
||||
downloadError=0
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
# Add HTML check for other file types
|
||||
if file -b "${cache}/${dest}" | grep -q "HTML document" ; then
|
||||
downloadError=1
|
||||
else
|
||||
downloadError=0
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
if [[ $downloadError -ne 0 ]]; then
|
||||
rm -fv "${cache}/${dest}"
|
||||
alert "Linux Game Manager" "Linux Game Manager" "Error downloading \"${dest}\". Installation cannot continue."
|
||||
exit 1
|
||||
fi
|
||||
validate_downloaded_cache_file "${dest}"
|
||||
done
|
||||
}
|
||||
|
||||
validate_downloaded_cache_file() {
|
||||
local dest="$1"
|
||||
local downloadError=0
|
||||
case "${dest##*.}" in
|
||||
"pk3"|"zip")
|
||||
if ! (
|
||||
set -o pipefail
|
||||
unzip -tq "${cache}/${dest}" | ui_progressbox "Linux Game Manager" "Validating ${dest##*.} file"
|
||||
); then
|
||||
downloadError=1
|
||||
fi
|
||||
;;
|
||||
"7z")
|
||||
if ! (
|
||||
set -o pipefail
|
||||
7z t "${cache}/${dest}" | ui_progressbox "Linux Game Manager" "Validating 7z file"
|
||||
); then
|
||||
downloadError=1
|
||||
fi
|
||||
;;
|
||||
"exe")
|
||||
# Check if it's a valid Windows executable by looking at the MZ header
|
||||
if ! hexdump -n 2 -v -e '/1 "%02X"' "${cache}/${dest}" | grep -q "4D5A"; then
|
||||
downloadError=0
|
||||
fi
|
||||
;;
|
||||
"wad")
|
||||
if [[ "$(file -b --mime-type "${cache}/${dest}")" == "application/octet-stream" ]]; then
|
||||
downloadError=0
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
if file -b "${cache}/${dest}" | grep -q "HTML document" ; then
|
||||
downloadError=1
|
||||
else
|
||||
downloadError=0
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
if [[ ${downloadError} -ne 0 ]]; then
|
||||
rm -fv "${cache}/${dest}"
|
||||
alert "Linux Game Manager" "Linux Game Manager" "Error downloading \"${dest}\". Installation cannot continue."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
download_named() {
|
||||
# Only needed if url breaks the name, e.g. downloads/?filename=1234
|
||||
# Required arguments: filename url
|
||||
@@ -614,6 +626,7 @@ download_named() {
|
||||
ui_msgbox "Linux Game Manager" "Linux Game Manager" "Could not download \"$dest\"...\n\ndownload exit codes: ${downloadAttemptExitCodes}\nError details: ${downloadErrorLog}"
|
||||
exit 1
|
||||
fi
|
||||
validate_downloaded_cache_file "${dest}"
|
||||
}
|
||||
|
||||
get_installer() {
|
||||
@@ -777,9 +790,14 @@ game_removal() {
|
||||
gameFile="$(readlink -f "${scriptRoot}/.launch/${gameName}.sh")"
|
||||
# Get the actual installation path from the .game file
|
||||
local gameInstallPath
|
||||
gameInstallPath="$(grep -F "installPath" "$gameFile" | grep -v 'pushd' | head -n1)"
|
||||
gameInstallPath="${gameInstallPath#*/}"
|
||||
gameInstallPath="${installPath}/${gameInstallPath%/*}"
|
||||
while IFS= read -r line; do
|
||||
[[ "${line}" == \#* ]] && continue
|
||||
[[ "${line}" == *'pushd'* ]] && continue
|
||||
if [[ "${line}" =~ \$\{installPath\}/([^\"]+) ]]; then
|
||||
gameInstallPath="${installPath}/${BASH_REMATCH[1]}"
|
||||
break
|
||||
fi
|
||||
done < "${gameFile}"
|
||||
if [[ -z "$gameInstallPath" ]] || [[ "${gameInstallPath%%/}" == "$installPath" ]]; then
|
||||
# No install path found, just remove from list
|
||||
ui_yesno "Linux Game Manager" "Linux Game Manager" "This will remove the game from your game list, but will not remove any files. Do you want to continue?" || exit 0
|
||||
@@ -946,6 +964,7 @@ requiredPackages=(
|
||||
"7z"
|
||||
"curl"
|
||||
"dialog"
|
||||
"jq"
|
||||
"yad"
|
||||
"unzip"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user