Improved system for installing things not available on the system when built.

This commit is contained in:
Storm Dragon
2025-10-09 23:13:27 -04:00
parent 3176d348c6
commit a02a8743d2
4 changed files with 287 additions and 8 deletions

View File

@@ -1,5 +1,8 @@
#!/usr/bin/env bash
# Source installation helper
source /usr/local/bin/stormux_install_helper.sh
# Function to run a game with FEXLoader
fex_load() {
local gameDir="$1"
@@ -365,16 +368,12 @@ case "$GAME" in
exec steam -bigpicture
;;
"thunderbird")
if ! command -v thunderbird &> /dev/null; then
yay -Sy --noconfirm thunderbird
fi
auto_install "thunderbird"
orca &
exec thunderbird
;;
"libreoffice")
if ! command -v libreoffice &> /dev/null; then
yay -Sy --noconfirm libreoffice-still
fi
auto_install "libreoffice"
orca &
exec libreoffice
;;
@@ -436,10 +435,10 @@ case "$GAME" in
run_native "wicked-quest" "wicked_quest.py"
;;
"Wreckingball")
setup_and_run_downloadable_url "https://sightlesswolf.com/wreckingball.zip" "wreckingball" "wreckingball.exe" "https://sightlesswolf.com" "nvda2speechd"
auto_install "wreckingball" && run_wine "wreckingball" "wreckingball.exe" "nvda2speechd"
;;
"Wreckingball (Pulped)")
setup_and_run_downloadable_url "https://sightlesswolf.com/wreckingball-pulped.zip" "wreckingball-pulped" "wreckingball.exe" "https://sightlesswolf.com" "nvda2speechd"
auto_install "wreckingball-pulped" && run_wine "wreckingball-pulped" "wreckingball.exe" "nvda2speechd"
;;
"Kitchensinc")
pushd "/home/stormux/.wine32/drive_c/Program Files/Kitchen's Sink"

View File

@@ -0,0 +1,244 @@
#!/usr/bin/env bash
# Stormux Installation Helper
# Provides automatic installation with speech feedback and progress indicators
# Configuration
GAMES_REGISTRY="/usr/share/stormux/downloadable_games.json"
PACKAGES_REGISTRY="/usr/share/stormux/installable_packages.json"
LOG_DIR="$HOME/Logs"
LOG_FILE="$LOG_DIR/installer.log"
INSTALL_BASE="$HOME/.local/games"
NVDA_DLL_SOURCE="$HOME/.local/games/nvda"
# Initialize logging
init_logging() {
mkdir -p "$LOG_DIR"
echo "=== Installation started at $(date) ===" >> "$LOG_FILE"
}
# Speech output
speak() {
local message="$1"
echo "$message" >> "$LOG_FILE"
spd-say "$message" 2>/dev/null || echo "$message"
}
# Progress beep
progress_beep() {
# Simple beep using speaker-test or paplay
if command -v paplay &> /dev/null && [[ -f /usr/share/sounds/freedesktop/stereo/message.oga ]]; then
paplay /usr/share/sounds/freedesktop/stereo/message.oga 2>/dev/null &
fi
}
# Download with progress feedback
download_with_progress() {
local url="$1"
local output="$2"
local name="$3"
speak "Downloading $name"
echo "Downloading from: $url" >> "$LOG_FILE"
# Start background process for progress beeps
(
while kill -0 $$ 2>/dev/null; do
sleep 5
progress_beep
done
) &
local beep_pid=$!
# Download with curl
if curl -L -f --progress-bar -o "$output" "$url" 2>> "$LOG_FILE"; then
kill $beep_pid 2>/dev/null
wait $beep_pid 2>/dev/null
echo "Download successful" >> "$LOG_FILE"
return 0
else
kill $beep_pid 2>/dev/null
wait $beep_pid 2>/dev/null
echo "Download failed" >> "$LOG_FILE"
return 1
fi
}
# Replace NVDA DLLs in game directory
replace_nvda_dlls() {
local game_dir="$1"
if [[ ! -d "$NVDA_DLL_SOURCE" ]]; then
echo "Warning: NVDA DLL source directory not found" >> "$LOG_FILE"
return 0
fi
# Replace all NVDA DLLs
{
find "$game_dir" -type f -name "nvdaControllerClient32.dll" -exec cp -v "$NVDA_DLL_SOURCE/nvdaControllerClient32.dll" '{}' \;
find "$game_dir" -type f -name "nvdaControllerClient64.dll" -exec cp -v "$NVDA_DLL_SOURCE/nvdaControllerClient64.dll" '{}' \;
find "$game_dir" -type f -name "nvdaControllerClient.dll" -exec cp -v "$NVDA_DLL_SOURCE/nvdaControllerClient64.dll" '{}' \;
} >> "$LOG_FILE" 2>&1
}
# Extract and setup game from ZIP
setup_game_zip() {
local zipfile="$1"
local game_dir="$2"
local game_name="$3"
speak "Installing $game_name"
echo "Extracting to: $game_dir" >> "$LOG_FILE"
# Remove old installation
rm -rf "$game_dir"
mkdir -p "$game_dir"
# Check if zip has a single top-level directory
mapfile -t topDirs < <(unzip -l "$zipfile" 2>> "$LOG_FILE" | awk 'NR>3 {print $4}' | grep '/$' | cut -d/ -f1 | sort -u | grep -v '^$')
if [[ ${#topDirs[@]} -eq 1 ]]; then
# Zip has a single top-level dir - extract to parent, then rename if needed
echo "Single top-level directory detected: ${topDirs[0]}" >> "$LOG_FILE"
if ! unzip -q "$zipfile" -d "$INSTALL_BASE" 2>> "$LOG_FILE"; then
echo "Extraction failed" >> "$LOG_FILE"
return 2
fi
# If the extracted dir name differs from target, rename it
if [[ "${topDirs[0]}" != "$(basename "$game_dir")" ]]; then
mv "$INSTALL_BASE/${topDirs[0]}" "$game_dir" 2>> "$LOG_FILE"
fi
else
# Multiple top-level entries - extract directly to game_dir
echo "Multiple top-level entries detected" >> "$LOG_FILE"
if ! unzip -q "$zipfile" -d "$game_dir" 2>> "$LOG_FILE"; then
echo "Extraction failed" >> "$LOG_FILE"
return 2
fi
fi
# Replace NVDA DLLs
replace_nvda_dlls "$game_dir"
# Clean up temp file
rm -f "$zipfile"
echo "Installation complete" >> "$LOG_FILE"
return 0
}
# Install system package via yay
install_system_package() {
local package="$1"
local name="$2"
speak "Installing $name"
echo "Installing package: $package" >> "$LOG_FILE"
if yay -Sy --noconfirm "$package" >> "$LOG_FILE" 2>&1; then
echo "Package installation successful" >> "$LOG_FILE"
return 0
else
echo "Package installation failed" >> "$LOG_FILE"
speak "Installation of $name failed. Check logs."
return 1
fi
}
# Check if game is installed
is_game_installed() {
local game_dir="$1"
local executable="$2"
[[ -e "$game_dir/$executable" ]]
}
# Check if package is installed
is_package_installed() {
local verify_command="$1"
eval "$verify_command" &>/dev/null
}
# Auto-install: Main function
# Usage: auto_install <item_id>
# Returns: 0 if ready to launch, non-zero on failure
auto_install() {
local item_id="$1"
init_logging
# Try to find in games registry
if [[ -f "$GAMES_REGISTRY" ]]; then
local game_info
game_info=$(jq -r ".downloadable_games[\"$item_id\"] // empty" "$GAMES_REGISTRY" 2>/dev/null)
if [[ -n "$game_info" ]]; then
local name url directory executable game_dir
name=$(echo "$game_info" | jq -r '.name')
url=$(echo "$game_info" | jq -r '.url')
directory=$(echo "$game_info" | jq -r '.directory')
executable=$(echo "$game_info" | jq -r '.executable')
game_dir="$INSTALL_BASE/$directory"
# Check if already installed
if is_game_installed "$game_dir" "$executable"; then
echo "Game already installed: $name" >> "$LOG_FILE"
return 0
fi
# Download and install
local temp_zip="/tmp/${directory}_download.zip"
if download_with_progress "$url" "$temp_zip" "$name"; then
if setup_game_zip "$temp_zip" "$game_dir" "$name"; then
# Verify installation
if is_game_installed "$game_dir" "$executable"; then
speak "Installation complete"
return 0
else
speak "Installation failed. Executable not found."
echo "Error: Executable not found after installation: $executable" >> "$LOG_FILE"
return 3
fi
else
speak "Installation failed. Could not extract game."
return 2
fi
else
speak "Download failed. Check your internet connection."
return 1
fi
fi
fi
# Try to find in packages registry
if [[ -f "$PACKAGES_REGISTRY" ]]; then
local package_info
package_info=$(jq -r ".installable_packages[\"$item_id\"] // empty" "$PACKAGES_REGISTRY" 2>/dev/null)
if [[ -n "$package_info" ]]; then
local name package verify_command
name=$(echo "$package_info" | jq -r '.name')
package=$(echo "$package_info" | jq -r '.package')
verify_command=$(echo "$package_info" | jq -r '.verify_command')
# Check if already installed
if is_package_installed "$verify_command"; then
echo "Package already installed: $name" >> "$LOG_FILE"
return 0
fi
# Install package
if install_system_package "$package" "$name"; then
speak "Installation complete"
return 0
else
return 1
fi
fi
fi
# Item not found in any registry
echo "Error: Item not found in registries: $item_id" >> "$LOG_FILE"
return 4
}

View File

@@ -0,0 +1,22 @@
{
"downloadable_games": {
"wreckingball": {
"name": "Wreckingball",
"section": "Arcade",
"url": "https://sightlesswolf.com/wreckingball.zip",
"directory": "wreckingball",
"executable": "wreckingball.exe",
"launch_mode": "wine",
"needs_nvda": "nvda2speechd"
},
"wreckingball-pulped": {
"name": "Wreckingball (Pulped)",
"section": "Arcade",
"url": "https://sightlesswolf.com/wreckingball-pulped.zip",
"directory": "wreckingball-pulped",
"executable": "wreckingball.exe",
"launch_mode": "wine",
"needs_nvda": "nvda2speechd"
}
}
}

View File

@@ -0,0 +1,14 @@
{
"installable_packages": {
"thunderbird": {
"name": "Thunderbird Email Client",
"package": "thunderbird",
"verify_command": "command -v thunderbird"
},
"libreoffice": {
"name": "LibreOffice",
"package": "libreoffice-still",
"verify_command": "command -v libreoffice"
}
}
}