Improved system for installing things not available on the system when built.
This commit is contained in:
@@ -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"
|
||||
|
||||
244
usr/local/bin/stormux_install_helper.sh
Executable file
244
usr/local/bin/stormux_install_helper.sh
Executable 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
|
||||
}
|
||||
22
usr/share/stormux/downloadable_games.json
Normal file
22
usr/share/stormux/downloadable_games.json
Normal 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"
|
||||
}
|
||||
}
|
||||
}
|
||||
14
usr/share/stormux/installable_packages.json
Normal file
14
usr/share/stormux/installable_packages.json
Normal 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"
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user