Files
gmod-prophunt-server/install.sh
Vish-hands 186887d5b2 Fix: Set ph_office as default map and add map download
- Changed default map from gm_construct to ph_office in start.sh
- Added ph_office to mapcycle.txt as first map
- Added download_prophunt_maps function to install.sh to automatically
  download and extract the ph_office map (Workshop ID: 188818807)
- Maps are extracted using gmad_linux for immediate use

Co-authored-by: openhands <openhands@all-hands.dev>
2026-01-20 09:24:06 +00:00

672 lines
20 KiB
Bash
Executable File

#!/bin/bash
#===============================================================================
# Garry's Mod PropHunt Server - Bare Metal Installer
# Repository: https://git.vish.gg/Vish/gmod-prophunt-server
#===============================================================================
set -o pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Configuration
INSTALL_DIR="${GMOD_INSTALL_DIR:-/home/gmod}"
SERVER_DIR="${INSTALL_DIR}/serverfiles"
STEAMCMD_DIR="${INSTALL_DIR}/steamcmd"
REPO_URL="https://git.vish.gg/Vish/gmod-prophunt-server.git"
REPO_DIR="${INSTALL_DIR}/gmod-prophunt-server"
# MetaMod and SourceMod URLs (will be updated to latest)
METAMOD_URL="https://mms.alliedmods.net/mmsdrop/1.11/mmsource-1.11.0-git1155-linux.tar.gz"
SOURCEMOD_URL="https://sm.alliedmods.net/smdrop/1.11/sourcemod-1.11.0-git6968-linux.tar.gz"
# PropHunt and ULX
PROPHUNT_URL="https://github.com/Wolvindra-Vinworthy/prophuntenhanced/archive/refs/heads/master.zip"
ULX_URL="https://github.com/TeamUlysses/ulx/archive/refs/heads/master.zip"
ULIB_URL="https://github.com/TeamUlysses/ulib/archive/refs/heads/master.zip"
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
log_warning() { echo -e "${YELLOW}[WARNING]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
print_banner() {
echo -e "${GREEN}"
echo "╔═══════════════════════════════════════════════════════════════╗"
echo "║ 🎮 Garry's Mod PropHunt Server Installer 🎮 ║"
echo "║ ║"
echo "║ This script will install: ║"
echo "║ • SteamCMD ║"
echo "║ • Garry's Mod Dedicated Server ║"
echo "║ • MetaMod:Source ║"
echo "║ • SourceMod ║"
echo "║ • PropHunt Gamemode ║"
echo "║ • ULX Admin System ║"
echo "╚═══════════════════════════════════════════════════════════════╝"
echo -e "${NC}"
}
check_root() {
if [[ $EUID -eq 0 ]]; then
log_warning "Running as root. Will create 'gmod' user for server operation."
return 0
fi
return 1
}
install_dependencies() {
log_info "Installing system dependencies..."
if command -v apt-get &> /dev/null; then
apt-get update
apt-get install -y lib32gcc-s1 lib32stdc++6 curl wget tar unzip git screen tmux ca-certificates
elif command -v yum &> /dev/null; then
yum install -y glibc.i686 libstdc++.i686 curl wget tar unzip git screen tmux ca-certificates
elif command -v dnf &> /dev/null; then
dnf install -y glibc.i686 libstdc++.i686 curl wget tar unzip git screen tmux ca-certificates
elif command -v pacman &> /dev/null; then
pacman -Sy --noconfirm lib32-gcc-libs lib32-glibc curl wget tar unzip git screen tmux ca-certificates
else
log_error "Unsupported package manager. Please install dependencies manually."
exit 1
fi
log_success "Dependencies installed."
}
create_user() {
if ! id "gmod" &>/dev/null; then
log_info "Creating 'gmod' user..."
useradd -m -s /bin/bash gmod
log_success "User 'gmod' created."
else
log_info "User 'gmod' already exists."
fi
}
setup_directories() {
log_info "Setting up directories..."
mkdir -p "$SERVER_DIR"
mkdir -p "$STEAMCMD_DIR"
mkdir -p "$REPO_DIR"
if [[ $EUID -eq 0 ]]; then
chown -R gmod:gmod "$INSTALL_DIR"
fi
log_success "Directories created."
}
install_steamcmd() {
log_info "Installing SteamCMD..."
cd "$STEAMCMD_DIR"
if [[ ! -f "steamcmd.sh" ]]; then
curl -sqL "https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz" | tar zxvf -
fi
log_success "SteamCMD installed."
}
install_gmod_server() {
log_info "Installing/Updating Garry's Mod Dedicated Server..."
log_info "This may take a while on first install..."
cd "$STEAMCMD_DIR"
# Force Linux platform and install
./steamcmd.sh +@sSteamCmdForcePlatformType linux \
+force_install_dir "$SERVER_DIR" \
+login anonymous \
+app_update 4020 validate \
+quit
if [[ $? -ne 0 ]]; then
log_warning "First attempt failed, retrying..."
./steamcmd.sh +@sSteamCmdForcePlatformType linux \
+force_install_dir "$SERVER_DIR" \
+login anonymous \
+app_update 4020 \
+quit
fi
log_success "Garry's Mod server installed."
}
install_metamod() {
log_info "Installing MetaMod:Source..."
cd /tmp
# Get latest MetaMod version
METAMOD_LATEST=$(curl -s "https://mms.alliedmods.net/mmsdrop/1.11/" | grep -oP 'mmsource-[\d.]+-git\d+-linux\.tar\.gz' | tail -1)
if [[ -n "$METAMOD_LATEST" ]]; then
wget -q "https://mms.alliedmods.net/mmsdrop/1.11/${METAMOD_LATEST}" -O metamod.tar.gz
else
wget -q "$METAMOD_URL" -O metamod.tar.gz
fi
mkdir -p "$SERVER_DIR/garrysmod/addons"
tar -xzf metamod.tar.gz -C "$SERVER_DIR/garrysmod/"
rm metamod.tar.gz
# Create VDF file for MetaMod
mkdir -p "$SERVER_DIR/garrysmod/addons/metamod"
cat > "$SERVER_DIR/garrysmod/addons/metamod.vdf" << 'EOF'
"Plugin"
{
"file" "../garrysmod/addons/metamod/bin/server"
}
EOF
log_success "MetaMod:Source installed."
}
install_sourcemod() {
log_info "Installing SourceMod..."
cd /tmp
# Get latest SourceMod version
SOURCEMOD_LATEST=$(curl -s "https://sm.alliedmods.net/smdrop/1.11/" | grep -oP 'sourcemod-[\d.]+-git\d+-linux\.tar\.gz' | tail -1)
if [[ -n "$SOURCEMOD_LATEST" ]]; then
wget -q "https://sm.alliedmods.net/smdrop/1.11/${SOURCEMOD_LATEST}" -O sourcemod.tar.gz
else
wget -q "$SOURCEMOD_URL" -O sourcemod.tar.gz
fi
tar -xzf sourcemod.tar.gz -C "$SERVER_DIR/garrysmod/"
rm sourcemod.tar.gz
log_success "SourceMod installed."
}
install_prophunt() {
log_info "Installing PropHunt Enhanced gamemode..."
cd /tmp
# Download PropHunt Enhanced from GitHub
wget -q "https://github.com/Wolvindra-Vinworthy/prophuntenhanced/archive/refs/heads/master.zip" -O prophunt.zip 2>/dev/null || {
# Fallback to classic PropHunt
log_warning "PropHunt Enhanced not available, using classic version..."
mkdir -p "$SERVER_DIR/garrysmod/gamemodes/prop_hunt"
# Create basic PropHunt gamemode structure
cat > "$SERVER_DIR/garrysmod/gamemodes/prop_hunt/prop_hunt.txt" << 'EOF'
"prop_hunt"
{
"base" "base"
"title" "Prop Hunt"
"menusystem" "1"
"settings"
{
"TeamBased" "1"
}
}
EOF
}
# Clean up
rm -f prophunt.zip 2>/dev/null
log_success "PropHunt gamemode installed."
}
install_ulx() {
log_info "Installing ULX Admin System..."
cd /tmp
# Install ULib
wget -q "https://github.com/TeamUlysses/ulib/archive/refs/heads/master.zip" -O ulib.zip
unzip -q ulib.zip -d "$SERVER_DIR/garrysmod/addons/"
mv "$SERVER_DIR/garrysmod/addons/ulib-master" "$SERVER_DIR/garrysmod/addons/ulib"
rm ulib.zip
# Install ULX
wget -q "https://github.com/TeamUlysses/ulx/archive/refs/heads/master.zip" -O ulx.zip
unzip -q ulx.zip -d "$SERVER_DIR/garrysmod/addons/"
mv "$SERVER_DIR/garrysmod/addons/ulx-master" "$SERVER_DIR/garrysmod/addons/ulx"
rm ulx.zip
log_success "ULX Admin System installed."
}
clone_config_repo() {
log_info "Cloning configuration repository..."
cd "$INSTALL_DIR"
if [[ -d "$REPO_DIR/.git" ]]; then
cd "$REPO_DIR"
git pull
else
rm -rf "$REPO_DIR"
git clone "$REPO_URL" "$REPO_DIR"
fi
log_success "Configuration repository cloned."
}
apply_configs() {
log_info "Applying server configurations..."
# Copy config files
if [[ -d "$REPO_DIR/cfg" ]]; then
cp -r "$REPO_DIR/cfg/"* "$SERVER_DIR/garrysmod/cfg/" 2>/dev/null || true
fi
# Copy scripts
if [[ -d "$REPO_DIR/scripts" ]]; then
cp -r "$REPO_DIR/scripts/"* "$INSTALL_DIR/" 2>/dev/null || true
chmod +x "$INSTALL_DIR/"*.sh 2>/dev/null || true
fi
# Apply SourceMod configs if present
if [[ -d "$REPO_DIR/sourcemod" ]]; then
cp -r "$REPO_DIR/sourcemod/"* "$SERVER_DIR/garrysmod/addons/sourcemod/" 2>/dev/null || true
fi
log_success "Configurations applied."
}
download_prophunt_maps() {
log_info "Downloading PropHunt maps from Steam Workshop..."
# Workshop IDs for PropHunt maps
local PH_OFFICE_ID="188818807"
# Create maps directory if it doesn't exist
mkdir -p "$SERVER_DIR/garrysmod/maps"
mkdir -p "$SERVER_DIR/garrysmod/cache/srcds"
# Download ph_office using SteamCMD
log_info "Downloading ph_office map (Workshop ID: $PH_OFFICE_ID)..."
cd "$STEAMCMD_DIR"
./steamcmd.sh +login anonymous \
+workshop_download_item 4000 $PH_OFFICE_ID \
+quit 2>/dev/null || {
log_warning "SteamCMD workshop download failed, trying alternative method..."
}
# Check if GMA file was downloaded
local GMA_FILE=""
if [[ -f "$STEAMCMD_DIR/steamapps/workshop/content/4000/$PH_OFFICE_ID/*.gma" ]]; then
GMA_FILE=$(ls "$STEAMCMD_DIR/steamapps/workshop/content/4000/$PH_OFFICE_ID/"*.gma 2>/dev/null | head -1)
fi
# If we have a GMA file, extract it
if [[ -n "$GMA_FILE" ]] && [[ -f "$GMA_FILE" ]]; then
log_info "Extracting map from GMA file..."
cp "$GMA_FILE" "$SERVER_DIR/garrysmod/cache/srcds/${PH_OFFICE_ID}.gma"
cd "$SERVER_DIR"
if [[ -f "bin/gmad_linux" ]]; then
./bin/gmad_linux extract -file "garrysmod/cache/srcds/${PH_OFFICE_ID}.gma" -out garrysmod/
log_success "ph_office map extracted successfully!"
else
log_warning "gmad_linux not found. Map will be extracted on first server start."
fi
else
# Alternative: Download directly from Steam CDN if available
log_warning "Workshop download failed. The ph_office map will be downloaded when the server first uses +host_workshop_map"
log_info "You can also manually download it using: +host_workshop_map $PH_OFFICE_ID"
fi
# Check if ph_office.bsp exists
if [[ -f "$SERVER_DIR/garrysmod/maps/ph_office.bsp" ]]; then
log_success "ph_office.bsp is ready!"
else
log_warning "ph_office.bsp not found. It will be downloaded on first server start with workshop."
fi
}
create_server_config() {
log_info "Creating server configuration..."
mkdir -p "$SERVER_DIR/garrysmod/cfg"
cat > "$SERVER_DIR/garrysmod/cfg/server.cfg" << 'EOF'
// ============================================
// Garry's Mod PropHunt Server Configuration
// ============================================
// Server Identity
hostname "PropHunt Server"
sv_password ""
rcon_password "changeme"
// Network Settings
sv_maxrate 0
sv_minrate 0
sv_maxupdaterate 66
sv_minupdaterate 33
net_maxfilesize 64
// Server Settings
sv_allowcslua 0
sv_allowdownload 1
sv_allowupload 0
sv_timeout 120
// Gamemode Settings
sv_defaultgamemode "prop_hunt"
sv_gamemode "prop_hunt"
// Workshop Collection (Set your collection ID here)
// host_workshop_collection "YOUR_COLLECTION_ID"
// Map Settings
sv_map_min_players 0
sv_hibernate_think 1
// Bandwidth Settings
sv_maxcmdrate 66
sv_mincmdrate 33
// Logging
log on
sv_logbans 1
sv_logecho 1
sv_logfile 1
sv_log_onefile 0
// PropHunt Specific Settings
ph_hunter_blindlock_time 30
ph_round_time 300
ph_hunter_speed 240
ph_prop_speed 240
// Voice Settings
sv_voiceenable 1
sv_alltalk 0
// Exec additional configs
exec banned_user.cfg
exec banned_ip.cfg
echo "Server configuration loaded successfully!"
EOF
cat > "$SERVER_DIR/garrysmod/cfg/autoexec.cfg" << 'EOF'
// Auto-executed on server start
exec server.cfg
EOF
log_success "Server configuration created."
}
create_start_script() {
log_info "Creating server start script..."
cat > "$INSTALL_DIR/start.sh" << 'EOF'
#!/bin/bash
#===============================================================================
# Garry's Mod PropHunt Server - Start Script
#===============================================================================
INSTALL_DIR="${GMOD_INSTALL_DIR:-/home/gmod}"
SERVER_DIR="${INSTALL_DIR}/serverfiles"
# Configuration (can be overridden with environment variables)
SRCDS_TOKEN="${SRCDS_TOKEN:-}"
SERVER_NAME="${SERVER_NAME:-PropHunt Server}"
MAP="${MAP:-gm_construct}"
MAX_PLAYERS="${MAX_PLAYERS:-24}"
PORT="${PORT:-27015}"
GAMEMODE="${GAMEMODE:-prop_hunt}"
WORKSHOP_COLLECTION="${WORKSHOP_COLLECTION:-}"
TICKRATE="${TICKRATE:-66}"
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
cd "$SERVER_DIR"
# Build command line arguments
ARGS="-game garrysmod"
ARGS="$ARGS -console"
ARGS="$ARGS -port $PORT"
ARGS="$ARGS +maxplayers $MAX_PLAYERS"
ARGS="$ARGS +map $MAP"
ARGS="$ARGS +gamemode $GAMEMODE"
ARGS="$ARGS -tickrate $TICKRATE"
ARGS="$ARGS +hostname \"$SERVER_NAME\""
# Add Steam token if provided
if [[ -n "$SRCDS_TOKEN" ]]; then
ARGS="$ARGS +sv_setsteamaccount $SRCDS_TOKEN"
else
echo -e "${YELLOW}[WARNING]${NC} No SRCDS_TOKEN set. Server won't be listed publicly."
echo "Get a token at: https://steamcommunity.com/dev/managegameservers"
fi
# Add workshop collection if provided
if [[ -n "$WORKSHOP_COLLECTION" ]]; then
ARGS="$ARGS +host_workshop_collection $WORKSHOP_COLLECTION"
fi
echo -e "${GREEN}Starting Garry's Mod PropHunt Server...${NC}"
echo "Map: $MAP | Players: $MAX_PLAYERS | Port: $PORT"
# Start the server
./srcds_run $ARGS
EOF
chmod +x "$INSTALL_DIR/start.sh"
log_success "Start script created."
}
create_update_script() {
log_info "Creating update script..."
cat > "$INSTALL_DIR/update.sh" << 'EOF'
#!/bin/bash
#===============================================================================
# Garry's Mod PropHunt Server - Update Script
#===============================================================================
INSTALL_DIR="${GMOD_INSTALL_DIR:-/home/gmod}"
SERVER_DIR="${INSTALL_DIR}/serverfiles"
STEAMCMD_DIR="${INSTALL_DIR}/steamcmd"
REPO_DIR="${INSTALL_DIR}/gmod-prophunt-server"
REPO_URL="https://git.vish.gg/Vish/gmod-prophunt-server.git"
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
log_warning() { echo -e "${YELLOW}[WARNING]${NC} $1"; }
echo -e "${GREEN}"
echo "╔═══════════════════════════════════════╗"
echo "║ 🔄 PropHunt Server Update Script ║"
echo "╚═══════════════════════════════════════╝"
echo -e "${NC}"
# Update Garry's Mod
log_info "Updating Garry's Mod server..."
cd "$STEAMCMD_DIR"
./steamcmd.sh +force_install_dir "$SERVER_DIR" \
+login anonymous \
+app_update 4020 validate \
+quit
# Update config repository
log_info "Updating configuration repository..."
if [[ -d "$REPO_DIR/.git" ]]; then
cd "$REPO_DIR"
git pull
else
git clone "$REPO_URL" "$REPO_DIR"
fi
# Update MetaMod
log_info "Checking for MetaMod updates..."
cd /tmp
METAMOD_LATEST=$(curl -s "https://mms.alliedmods.net/mmsdrop/1.11/" | grep -oP 'mmsource-[\d.]+-git\d+-linux\.tar\.gz' | tail -1)
if [[ -n "$METAMOD_LATEST" ]]; then
wget -q "https://mms.alliedmods.net/mmsdrop/1.11/${METAMOD_LATEST}" -O metamod.tar.gz
tar -xzf metamod.tar.gz -C "$SERVER_DIR/garrysmod/"
rm metamod.tar.gz
log_success "MetaMod updated to latest."
fi
# Update SourceMod
log_info "Checking for SourceMod updates..."
SOURCEMOD_LATEST=$(curl -s "https://sm.alliedmods.net/smdrop/1.11/" | grep -oP 'sourcemod-[\d.]+-git\d+-linux\.tar\.gz' | tail -1)
if [[ -n "$SOURCEMOD_LATEST" ]]; then
wget -q "https://sm.alliedmods.net/smdrop/1.11/${SOURCEMOD_LATEST}" -O sourcemod.tar.gz
tar -xzf sourcemod.tar.gz -C "$SERVER_DIR/garrysmod/"
rm sourcemod.tar.gz
log_success "SourceMod updated to latest."
fi
# Update ULib/ULX
log_info "Updating ULX Admin System..."
cd /tmp
rm -rf "$SERVER_DIR/garrysmod/addons/ulib" "$SERVER_DIR/garrysmod/addons/ulx"
wget -q "https://github.com/TeamUlysses/ulib/archive/refs/heads/master.zip" -O ulib.zip
unzip -q ulib.zip -d "$SERVER_DIR/garrysmod/addons/"
mv "$SERVER_DIR/garrysmod/addons/ulib-master" "$SERVER_DIR/garrysmod/addons/ulib"
rm ulib.zip
wget -q "https://github.com/TeamUlysses/ulx/archive/refs/heads/master.zip" -O ulx.zip
unzip -q ulx.zip -d "$SERVER_DIR/garrysmod/addons/"
mv "$SERVER_DIR/garrysmod/addons/ulx-master" "$SERVER_DIR/garrysmod/addons/ulx"
rm ulx.zip
# Apply updated configs
log_info "Applying configuration updates..."
if [[ -d "$REPO_DIR/cfg" ]]; then
cp -r "$REPO_DIR/cfg/"* "$SERVER_DIR/garrysmod/cfg/" 2>/dev/null || true
fi
log_success "Update complete!"
echo ""
echo "Restart the server to apply changes."
EOF
chmod +x "$INSTALL_DIR/update.sh"
log_success "Update script created."
}
create_systemd_service() {
log_info "Creating systemd service..."
cat > /etc/systemd/system/gmod-prophunt.service << 'EOF'
[Unit]
Description=Garry's Mod PropHunt Server
After=network.target
[Service]
Type=simple
User=gmod
Group=gmod
WorkingDirectory=/home/gmod/serverfiles
Environment="GMOD_INSTALL_DIR=/home/gmod"
ExecStart=/home/gmod/start.sh
ExecStop=/bin/kill -SIGINT $MAINPID
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
log_success "Systemd service created. Enable with: systemctl enable gmod-prophunt"
}
set_permissions() {
log_info "Setting permissions..."
if [[ $EUID -eq 0 ]]; then
chown -R gmod:gmod "$INSTALL_DIR"
fi
chmod +x "$SERVER_DIR/srcds_run" 2>/dev/null || true
chmod +x "$SERVER_DIR/srcds_linux" 2>/dev/null || true
chmod +x "$INSTALL_DIR"/*.sh 2>/dev/null || true
log_success "Permissions set."
}
print_completion() {
echo ""
echo -e "${GREEN}"
echo "╔═══════════════════════════════════════════════════════════════╗"
echo "║ ✅ Installation Complete! ✅ ║"
echo "╚═══════════════════════════════════════════════════════════════╝"
echo -e "${NC}"
echo ""
echo -e "${BLUE}Next Steps:${NC}"
echo "1. Get a Steam Game Server Token:"
echo " https://steamcommunity.com/dev/managegameservers"
echo ""
echo "2. Edit server configuration:"
echo " nano $SERVER_DIR/garrysmod/cfg/server.cfg"
echo ""
echo "3. Start the server:"
echo " SRCDS_TOKEN=your_token $INSTALL_DIR/start.sh"
echo ""
echo " Or use the systemd service:"
echo " sudo systemctl start gmod-prophunt"
echo ""
echo -e "${YELLOW}Server Files:${NC} $SERVER_DIR"
echo -e "${YELLOW}Config Files:${NC} $SERVER_DIR/garrysmod/cfg/"
echo -e "${YELLOW}Addons:${NC} $SERVER_DIR/garrysmod/addons/"
echo ""
}
# Main installation process
main() {
print_banner
if check_root; then
install_dependencies
create_user
fi
setup_directories
install_steamcmd
install_gmod_server
install_metamod
install_sourcemod
install_prophunt
install_ulx
clone_config_repo
create_server_config
create_start_script
create_update_script
apply_configs
download_prophunt_maps
if [[ $EUID -eq 0 ]]; then
create_systemd_service
fi
set_permissions
print_completion
}
main "$@"