555 lines
16 KiB
Bash
Executable File
555 lines
16 KiB
Bash
Executable File
#!/bin/bash
|
||
set -e
|
||
|
||
# Monocoque Universal Installer
|
||
# Works on: Arch, Debian/Ubuntu, Fedora, and other major distros
|
||
# Version: 1.0.0
|
||
|
||
SCRIPT_VERSION="1.0.0"
|
||
INSTALL_DIR="${MONOCOQUE_INSTALL_DIR:-${XDG_DATA_HOME:-$HOME/.local/share}/monocoque}"
|
||
CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}"
|
||
BIN_DIR="${HOME}/.local/bin"
|
||
|
||
# Color output
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
NC='\033[0m' # No Color
|
||
|
||
# Logging functions
|
||
log_info() {
|
||
echo -e "${BLUE}[INFO]${NC} $1"
|
||
}
|
||
|
||
log_success() {
|
||
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||
}
|
||
|
||
log_warn() {
|
||
echo -e "${YELLOW}[WARN]${NC} $1"
|
||
}
|
||
|
||
log_error() {
|
||
echo -e "${RED}[ERROR]${NC} $1"
|
||
}
|
||
|
||
print_header() {
|
||
echo ""
|
||
echo "╔══════════════════════════════════════════════════════════════════╗"
|
||
echo "║ Monocoque Universal Installer v${SCRIPT_VERSION} ║"
|
||
echo "╚══════════════════════════════════════════════════════════════════╝"
|
||
echo ""
|
||
}
|
||
|
||
# Detect distribution
|
||
detect_distro() {
|
||
if [ -f /etc/os-release ]; then
|
||
. /etc/os-release
|
||
DISTRO=$ID
|
||
DISTRO_VERSION=$VERSION_ID
|
||
DISTRO_LIKE=$ID_LIKE
|
||
elif [ -f /etc/arch-release ]; then
|
||
DISTRO="arch"
|
||
else
|
||
DISTRO="unknown"
|
||
fi
|
||
|
||
# Normalize Arch-based distributions
|
||
if [[ "$DISTRO_LIKE" == *"arch"* ]] || [[ "$DISTRO" == "manjaro" ]] || [[ "$DISTRO" == "garuda" ]] || [[ "$DISTRO" == "endeavouros" ]]; then
|
||
log_info "Detected distribution: $DISTRO (Arch-based)"
|
||
DISTRO="arch"
|
||
else
|
||
log_info "Detected distribution: $DISTRO"
|
||
fi
|
||
}
|
||
|
||
# Check if running as root
|
||
check_root() {
|
||
if [ "$EUID" -eq 0 ]; then
|
||
log_error "Please do not run this script as root"
|
||
exit 1
|
||
fi
|
||
}
|
||
|
||
# Check for required commands
|
||
check_requirements() {
|
||
local missing_commands=()
|
||
|
||
for cmd in git cmake make gcc; do
|
||
if ! command -v $cmd &> /dev/null; then
|
||
missing_commands+=($cmd)
|
||
fi
|
||
done
|
||
|
||
if [ ${#missing_commands[@]} -ne 0 ]; then
|
||
log_error "Missing required commands: ${missing_commands[*]}"
|
||
log_info "Please install them first"
|
||
exit 1
|
||
fi
|
||
}
|
||
|
||
# Install dependencies based on distro
|
||
install_dependencies() {
|
||
log_info "Installing dependencies for $DISTRO..."
|
||
|
||
case $DISTRO in
|
||
arch|manjaro)
|
||
local deps="yder libuv argtable libserialport libconfig hidapi lua libxdg-basedir mingw-w64-gcc"
|
||
|
||
# Check if yay is available for AUR
|
||
if command -v yay &> /dev/null; then
|
||
log_info "Using yay to check for AUR packages..."
|
||
echo ""
|
||
echo "You can install monocoque from AUR instead:"
|
||
echo " yay -S simapi-git simd-git monocoque-git"
|
||
echo ""
|
||
read -p "Install from AUR? (recommended) [Y/n]: " use_aur
|
||
|
||
if [[ ! $use_aur =~ ^[Nn]$ ]]; then
|
||
log_info "Installing from AUR..."
|
||
yay -S --needed simapi-git simd-git monocoque-git
|
||
|
||
# Still need simshmbridge
|
||
log_info "Building simshmbridge (not in AUR)..."
|
||
build_simshmbridge_only
|
||
|
||
# Setup configs and services
|
||
setup_configs
|
||
setup_systemd_services
|
||
# create_launcher_scripts uses SCRIPT_DIR which is set in main()
|
||
create_launcher_scripts
|
||
|
||
log_success "Installation complete (AUR method)!"
|
||
print_next_steps
|
||
exit 0
|
||
fi
|
||
fi
|
||
|
||
log_info "Installing build dependencies with pacman..."
|
||
sudo pacman -S --needed --noconfirm $deps
|
||
;;
|
||
|
||
ubuntu|debian|linuxmint|pop)
|
||
local deps="build-essential git cmake libyder-dev libuv1-dev libargtable2-dev libserialport-dev libconfig-dev libhidapi-dev lua5.3 liblua5.3-dev libxdg-basedir-dev mingw-w64"
|
||
|
||
log_info "Updating package lists..."
|
||
sudo apt-get update
|
||
|
||
log_info "Installing build dependencies..."
|
||
sudo apt-get install -y $deps
|
||
;;
|
||
|
||
fedora|rhel|centos)
|
||
local deps="git cmake gcc gcc-c++ yder-devel libuv-devel argtable-devel libserialport-devel libconfig-devel hidapi-devel lua-devel libxdg-basedir-devel mingw64-gcc"
|
||
|
||
log_info "Installing build dependencies..."
|
||
sudo dnf install -y $deps
|
||
;;
|
||
|
||
opensuse*)
|
||
local deps="git cmake gcc gcc-c++ libyder-devel libuv-devel argtable-devel libserialport-devel libconfig-devel hidapi-devel lua-devel libxdg-basedir-devel mingw64-gcc"
|
||
|
||
log_info "Installing build dependencies..."
|
||
sudo zypper install -y $deps
|
||
;;
|
||
|
||
*)
|
||
log_error "Unsupported distribution: $DISTRO"
|
||
log_info "Please install dependencies manually and try again"
|
||
log_info "Required: git, cmake, gcc, yder, libuv, argtable, libserialport, libconfig, hidapi, lua, libxdg-basedir, mingw-gcc"
|
||
exit 1
|
||
;;
|
||
esac
|
||
|
||
log_success "Dependencies installed"
|
||
}
|
||
|
||
# Clone repositories
|
||
clone_repositories() {
|
||
log_info "Creating installation directory: $INSTALL_DIR"
|
||
mkdir -p "$INSTALL_DIR"
|
||
cd "$INSTALL_DIR"
|
||
|
||
# Clone monocoque
|
||
if [ ! -d "monocoque" ]; then
|
||
log_info "Cloning monocoque..."
|
||
git clone https://github.com/Spacefreak18/monocoque.git
|
||
cd monocoque
|
||
git submodule sync --recursive
|
||
git submodule update --init --recursive
|
||
else
|
||
log_info "monocoque already cloned, updating..."
|
||
cd monocoque
|
||
git pull
|
||
git submodule sync --recursive
|
||
git submodule update --init --recursive
|
||
fi
|
||
cd "$INSTALL_DIR"
|
||
|
||
# Clone simapi
|
||
if [ ! -d "simapi" ]; then
|
||
log_info "Cloning simapi..."
|
||
git clone https://github.com/Spacefreak18/simapi.git
|
||
else
|
||
log_info "simapi already cloned, updating..."
|
||
cd simapi
|
||
git pull
|
||
fi
|
||
cd "$INSTALL_DIR"
|
||
|
||
# Clone simshmbridge
|
||
if [ ! -d "simshmbridge" ]; then
|
||
log_info "Cloning simshmbridge..."
|
||
git clone https://github.com/spacefreak18/simshmbridge.git
|
||
cd simshmbridge
|
||
git submodule sync --recursive
|
||
git submodule update --init --recursive
|
||
else
|
||
log_info "simshmbridge already cloned, updating..."
|
||
cd simshmbridge
|
||
git pull
|
||
git submodule sync --recursive
|
||
git submodule update --init --recursive
|
||
fi
|
||
|
||
log_success "Repositories cloned/updated"
|
||
}
|
||
|
||
# Build simapi
|
||
build_simapi() {
|
||
log_info "Building simapi..."
|
||
cd "$INSTALL_DIR/simapi"
|
||
|
||
mkdir -p build
|
||
cd build
|
||
cmake ..
|
||
make -j$(nproc)
|
||
|
||
log_info "Installing simapi library..."
|
||
sudo make install
|
||
|
||
# Update library cache
|
||
sudo ldconfig 2>/dev/null || true
|
||
|
||
log_success "simapi built and installed"
|
||
}
|
||
|
||
# Build simd
|
||
build_simd() {
|
||
log_info "Building simd..."
|
||
cd "$INSTALL_DIR/simapi/simd"
|
||
|
||
rm -rf build
|
||
mkdir -p build
|
||
cd build
|
||
cmake ..
|
||
make -j$(nproc)
|
||
|
||
log_success "simd built"
|
||
}
|
||
|
||
# Build simshmbridge
|
||
build_simshmbridge() {
|
||
log_info "Building simshmbridge..."
|
||
cd "$INSTALL_DIR/simshmbridge"
|
||
|
||
make clean || true
|
||
make -j$(nproc)
|
||
|
||
log_success "simshmbridge built"
|
||
}
|
||
|
||
build_simshmbridge_only() {
|
||
mkdir -p "$INSTALL_DIR"
|
||
cd "$INSTALL_DIR"
|
||
|
||
if [ ! -d "simshmbridge" ]; then
|
||
log_info "Cloning simshmbridge..."
|
||
git clone https://github.com/spacefreak18/simshmbridge.git
|
||
cd simshmbridge
|
||
git submodule sync --recursive
|
||
git submodule update --init --recursive
|
||
fi
|
||
|
||
build_simshmbridge
|
||
}
|
||
|
||
# Build monocoque
|
||
build_monocoque() {
|
||
log_info "Building monocoque..."
|
||
cd "$INSTALL_DIR/monocoque"
|
||
|
||
mkdir -p build
|
||
cd build
|
||
cmake ..
|
||
make -j$(nproc)
|
||
|
||
log_success "monocoque built"
|
||
}
|
||
|
||
# Setup configuration files
|
||
setup_configs() {
|
||
log_info "Setting up configuration files..."
|
||
|
||
# simd config
|
||
mkdir -p "$CONFIG_DIR/simd"
|
||
if [ ! -f "$CONFIG_DIR/simd/simd.config" ]; then
|
||
if [ -f "$INSTALL_DIR/simapi/simd/conf/simd.config" ]; then
|
||
cp "$INSTALL_DIR/simapi/simd/conf/simd.config" "$CONFIG_DIR/simd/simd.config"
|
||
log_success "Created simd config"
|
||
fi
|
||
else
|
||
log_info "simd config already exists, skipping"
|
||
fi
|
||
|
||
# monocoque config
|
||
mkdir -p "$CONFIG_DIR/monocoque"
|
||
if [ ! -f "$CONFIG_DIR/monocoque/monocoque.config" ]; then
|
||
cat > "$CONFIG_DIR/monocoque/monocoque.config" << 'EOF'
|
||
configs = (
|
||
{
|
||
sim = "default";
|
||
car = "default";
|
||
devices = (
|
||
// Add your devices here
|
||
// Example: Serial device (ESP32/Arduino)
|
||
/*
|
||
{
|
||
device = "Serial";
|
||
type = "Custom";
|
||
config = "None";
|
||
baud = 115200;
|
||
devpath = "/dev/ttyUSB0";
|
||
},
|
||
*/
|
||
|
||
// Example: Bass shaker
|
||
/*
|
||
{
|
||
device = "Sound";
|
||
effect = "Engine";
|
||
devid = "alsa_output.your_device_here";
|
||
pan = 0;
|
||
fps = 60;
|
||
threshold = 0.2;
|
||
channels = 2;
|
||
volume = 70;
|
||
modulation = "frequency";
|
||
frequency = 17;
|
||
frequencyMax = 37;
|
||
},
|
||
*/
|
||
);
|
||
}
|
||
);
|
||
EOF
|
||
log_success "Created monocoque config"
|
||
else
|
||
log_info "monocoque config already exists, skipping"
|
||
fi
|
||
}
|
||
|
||
# Create launcher scripts
|
||
create_launcher_scripts() {
|
||
log_info "Creating launcher scripts in $BIN_DIR..."
|
||
mkdir -p "$BIN_DIR"
|
||
|
||
# Find simd binary location
|
||
local SIMD_BIN=""
|
||
if [ -f "$INSTALL_DIR/simapi/simd/build/simd" ]; then
|
||
SIMD_BIN="$INSTALL_DIR/simapi/simd/build/simd"
|
||
elif command -v simd &> /dev/null; then
|
||
SIMD_BIN=$(which simd)
|
||
fi
|
||
|
||
# Find monocoque binary location
|
||
local MONOCOQUE_BIN=""
|
||
if [ -f "$INSTALL_DIR/monocoque/build/monocoque" ]; then
|
||
MONOCOQUE_BIN="$INSTALL_DIR/monocoque/build/monocoque"
|
||
elif command -v monocoque &> /dev/null; then
|
||
MONOCOQUE_BIN=$(which monocoque)
|
||
fi
|
||
|
||
# start-simd script
|
||
cat > "$BIN_DIR/start-simd" << EOF
|
||
#!/bin/bash
|
||
export LD_LIBRARY_PATH=\$LD_LIBRARY_PATH:/usr/local/lib:/usr/local/lib64
|
||
exec $SIMD_BIN -vv "\$@"
|
||
EOF
|
||
chmod +x "$BIN_DIR/start-simd"
|
||
|
||
# start-monocoque script
|
||
cat > "$BIN_DIR/start-monocoque" << EOF
|
||
#!/bin/bash
|
||
exec $MONOCOQUE_BIN play "\$@"
|
||
EOF
|
||
chmod +x "$BIN_DIR/start-monocoque"
|
||
|
||
# test-monocoque script
|
||
cat > "$BIN_DIR/test-monocoque" << EOF
|
||
#!/bin/bash
|
||
exec $MONOCOQUE_BIN test -vv "\$@"
|
||
EOF
|
||
chmod +x "$BIN_DIR/test-monocoque"
|
||
|
||
# monocoque-manager TUI
|
||
log_info "Looking for monocoque-manager to install..."
|
||
local MANAGER_INSTALLED=false
|
||
|
||
# Use the SCRIPT_DIR exported from main()
|
||
# Try multiple locations
|
||
local SEARCH_PATHS=(
|
||
"$SCRIPT_DIR/monocoque-manager"
|
||
"$SCRIPT_DIR/tools/monocoque-manager"
|
||
)
|
||
|
||
for MANAGER_PATH in "${SEARCH_PATHS[@]}"; do
|
||
log_info "Checking: $MANAGER_PATH"
|
||
if [ -f "$MANAGER_PATH" ]; then
|
||
log_info "Found monocoque-manager at: $MANAGER_PATH"
|
||
cp "$MANAGER_PATH" "$BIN_DIR/monocoque-manager"
|
||
chmod +x "$BIN_DIR/monocoque-manager"
|
||
log_success "✓ Installed monocoque-manager TUI to $BIN_DIR/monocoque-manager"
|
||
MANAGER_INSTALLED=true
|
||
break
|
||
fi
|
||
done
|
||
|
||
if [ "$MANAGER_INSTALLED" = false ]; then
|
||
log_error "monocoque-manager not found!"
|
||
log_warn "Searched in: ${SEARCH_PATHS[*]}"
|
||
log_warn "SCRIPT_DIR was: $SCRIPT_DIR"
|
||
log_info "Please copy it manually: cp $SCRIPT_DIR/monocoque-manager ~/.local/bin/"
|
||
fi
|
||
|
||
# Check if BIN_DIR is in PATH
|
||
if [[ ":$PATH:" != *":$BIN_DIR:"* ]]; then
|
||
log_warn "$BIN_DIR is not in your PATH"
|
||
log_info "Add this to your shell config:"
|
||
echo " # For bash/zsh:"
|
||
echo " export PATH=\"\$HOME/.local/bin:\$PATH\""
|
||
echo ""
|
||
echo " # For fish:"
|
||
echo " fish_add_path ~/.local/bin"
|
||
fi
|
||
|
||
log_success "Launcher scripts created"
|
||
}
|
||
|
||
# Setup systemd user services
|
||
setup_systemd_services() {
|
||
local SYSTEMD_DIR="$HOME/.config/systemd/user"
|
||
mkdir -p "$SYSTEMD_DIR"
|
||
|
||
log_info "Creating systemd service files..."
|
||
|
||
# Find binary locations
|
||
local SIMD_BIN=""
|
||
if [ -f "$INSTALL_DIR/simapi/simd/build/simd" ]; then
|
||
SIMD_BIN="$INSTALL_DIR/simapi/simd/build/simd"
|
||
elif command -v simd &> /dev/null; then
|
||
SIMD_BIN=$(which simd)
|
||
fi
|
||
|
||
# simd service
|
||
cat > "$SYSTEMD_DIR/simd.service" << EOF
|
||
[Unit]
|
||
Description=Sim Telemetry Daemon
|
||
Documentation=https://spacefreak18.github.io/simapi/
|
||
After=network.target
|
||
|
||
[Service]
|
||
Type=simple
|
||
Environment="LD_LIBRARY_PATH=/usr/local/lib:/usr/local/lib64"
|
||
ExecStart=$SIMD_BIN
|
||
Restart=on-failure
|
||
RestartSec=5
|
||
|
||
[Install]
|
||
WantedBy=default.target
|
||
EOF
|
||
|
||
log_success "systemd services created"
|
||
log_info "To enable auto-start on boot:"
|
||
echo " systemctl --user enable simd.service"
|
||
echo " systemctl --user start simd.service"
|
||
}
|
||
|
||
# Print next steps
|
||
print_next_steps() {
|
||
echo ""
|
||
echo "╔══════════════════════════════════════════════════════════════════╗"
|
||
echo "║ Installation Complete! ║"
|
||
echo "╚══════════════════════════════════════════════════════════════════╝"
|
||
echo ""
|
||
log_success "Monocoque and all components are installed!"
|
||
echo ""
|
||
echo "📁 Installation location: $INSTALL_DIR"
|
||
echo "⚙️ Configuration: $CONFIG_DIR/simd and $CONFIG_DIR/monocoque"
|
||
echo "🚀 Launcher scripts: $BIN_DIR"
|
||
echo ""
|
||
echo "Next steps:"
|
||
echo ""
|
||
echo "1️⃣ Configure your games (REQUIRED!)"
|
||
echo " See: https://github.com/Spacefreak18/monocoque/blob/master/HOW-TO-USE.md"
|
||
echo ""
|
||
echo "2️⃣ Start the services:"
|
||
echo " Terminal 1: start-simd"
|
||
echo " Terminal 2: start-monocoque"
|
||
echo ""
|
||
echo " OR enable auto-start:"
|
||
echo " systemctl --user enable --now simd.service"
|
||
echo ""
|
||
echo "3️⃣ Configure your devices:"
|
||
echo " Edit: $CONFIG_DIR/monocoque/monocoque.config"
|
||
echo ""
|
||
echo "4️⃣ Test your setup:"
|
||
echo " test-monocoque"
|
||
echo ""
|
||
echo "🎮 Supported games:"
|
||
echo " • Assetto Corsa / ACC"
|
||
echo " • Automobilista 2"
|
||
echo " • Project Cars 2"
|
||
echo " • RFactor 2"
|
||
echo " • Euro/American Truck Simulator"
|
||
echo ""
|
||
echo "📚 Documentation: https://spacefreak18.github.io/simapi/"
|
||
echo ""
|
||
}
|
||
|
||
# Main installation flow
|
||
main() {
|
||
# Save the directory where this script is located
|
||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
export SCRIPT_DIR
|
||
|
||
print_header
|
||
|
||
check_root
|
||
detect_distro
|
||
check_requirements
|
||
|
||
log_info "Starting installation..."
|
||
echo ""
|
||
|
||
install_dependencies
|
||
clone_repositories
|
||
|
||
log_info "Building components (this may take a few minutes)..."
|
||
build_simapi
|
||
build_simd
|
||
build_monocoque
|
||
build_simshmbridge
|
||
|
||
setup_configs
|
||
create_launcher_scripts
|
||
setup_systemd_services
|
||
|
||
print_next_steps
|
||
}
|
||
|
||
# Run main function
|
||
main "$@"
|
||
|