258 lines
8.1 KiB
Bash
Executable File
258 lines
8.1 KiB
Bash
Executable File
#!/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"
|
|
# Clear previous log and start fresh
|
|
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"
|
|
|
|
# Extract to temp location first to handle any ZIP structure
|
|
local temp_extract="/tmp/stormux_install_$$"
|
|
mkdir -p "$temp_extract"
|
|
|
|
if ! unzip -q "$zipfile" -d "$temp_extract" 2>> "$LOG_FILE"; then
|
|
echo "Extraction failed" >> "$LOG_FILE"
|
|
rm -rf "$temp_extract"
|
|
return 2
|
|
fi
|
|
|
|
# Check if everything extracted into a single subdirectory
|
|
local extracted_items
|
|
extracted_items=("$temp_extract"/*)
|
|
|
|
if [[ ${#extracted_items[@]} -eq 1 ]] && [[ -d "${extracted_items[0]}" ]]; then
|
|
# Single directory - move its contents to game_dir
|
|
echo "Single directory extracted, moving contents" >> "$LOG_FILE"
|
|
mv "${extracted_items[0]}"/* "$game_dir/" 2>> "$LOG_FILE"
|
|
else
|
|
# Multiple items or single file - move everything
|
|
echo "Multiple items extracted, moving all" >> "$LOG_FILE"
|
|
mv "$temp_extract"/* "$game_dir/" 2>> "$LOG_FILE"
|
|
fi
|
|
|
|
rm -rf "$temp_extract"
|
|
|
|
# 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
|
|
echo "Reading games registry: $GAMES_REGISTRY" >> "$LOG_FILE"
|
|
local game_info
|
|
game_info=$(jq -r ".downloadable_games[\"$item_id\"] // empty" "$GAMES_REGISTRY" 2>> "$LOG_FILE")
|
|
echo "Game info result: ${game_info:-empty}" >> "$LOG_FILE"
|
|
|
|
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
|
|
if [[ ! -f "$GAMES_REGISTRY" ]] && [[ ! -f "$PACKAGES_REGISTRY" ]]; then
|
|
echo "Error: Registry files not found!" >> "$LOG_FILE"
|
|
echo " Expected: $GAMES_REGISTRY" >> "$LOG_FILE"
|
|
echo " Expected: $PACKAGES_REGISTRY" >> "$LOG_FILE"
|
|
speak "Error: Installation registry files not found. This may be a development system."
|
|
else
|
|
echo "Error: Item not found in registries: $item_id" >> "$LOG_FILE"
|
|
speak "Error: $item_id not found in installation registry"
|
|
fi
|
|
return 4
|
|
}
|