From 238ee39234e1da2f28f67f44526124dcd727b163 Mon Sep 17 00:00:00 2001 From: Deckard Date: Tue, 7 Oct 2025 13:25:35 -0400 Subject: [PATCH] add inline scripts as standalone scritps for automations --- scripts/backup-scheduler.sh | 56 +++ scripts/db-import.sh | 30 ++ scripts/db-init.sh | 34 ++ scripts/download-client-data.sh | 166 ++++++++ scripts/manage-modules-sql.sh | 197 +++++++++ scripts/manage-modules.sh | 685 ++++++++++++++++++++++++++++++++ scripts/mysql-startup.sh | 104 +++++ 7 files changed, 1272 insertions(+) create mode 100644 scripts/backup-scheduler.sh create mode 100644 scripts/db-import.sh create mode 100644 scripts/db-init.sh create mode 100644 scripts/download-client-data.sh create mode 100644 scripts/manage-modules-sql.sh create mode 100644 scripts/manage-modules.sh create mode 100644 scripts/mysql-startup.sh diff --git a/scripts/backup-scheduler.sh b/scripts/backup-scheduler.sh new file mode 100644 index 0000000..fc072e2 --- /dev/null +++ b/scripts/backup-scheduler.sh @@ -0,0 +1,56 @@ +#!/bin/bash +set -e + +echo "πŸ”§ Starting enhanced backup service with hourly and daily schedules..." + +# Install curl if not available +apt-get update && apt-get install -y curl + +# Download backup scripts from GitHub +echo "πŸ“₯ Downloading backup scripts from GitHub..." +curl -fsSL https://raw.githubusercontent.com/uprightbass360/acore-compose/main/scripts/backup.sh -o /tmp/backup.sh +curl -fsSL https://raw.githubusercontent.com/uprightbass360/acore-compose/main/scripts/backup-hourly.sh -o /tmp/backup-hourly.sh +curl -fsSL https://raw.githubusercontent.com/uprightbass360/acore-compose/main/scripts/backup-daily.sh -o /tmp/backup-daily.sh +chmod +x /tmp/backup.sh /tmp/backup-hourly.sh /tmp/backup-daily.sh + +# Wait for MySQL to be ready before starting backup service +echo "⏳ Waiting for MySQL to be ready..." +sleep 30 + +# Run initial daily backup +echo "πŸš€ Running initial daily backup..." +/tmp/backup-daily.sh + +# Enhanced scheduler with hourly and daily backups +echo "⏰ Starting enhanced backup scheduler:" +echo " πŸ“… Daily backups: ${BACKUP_DAILY_TIME}:00 UTC (retention: ${BACKUP_RETENTION_DAYS} days)" +echo " ⏰ Hourly backups: every hour (retention: ${BACKUP_RETENTION_HOURS} hours)" + +# Track last backup times to avoid duplicates +last_daily_hour="" +last_hourly_minute="" + +while true; do + current_hour=$(date +%H) + current_minute=$(date +%M) + current_time="$current_hour:$current_minute" + + # Daily backup check (configurable time) + if [ "$current_hour" = "${BACKUP_DAILY_TIME}" ] && [ "$current_minute" = "00" ] && [ "$last_daily_hour" != "$current_hour" ]; then + echo "πŸ“… [$(date)] Daily backup time reached, running daily backup..." + /tmp/backup-daily.sh + last_daily_hour="$current_hour" + # Sleep for 2 minutes to avoid running multiple times + sleep 120 + # Hourly backup check (every hour at minute 0, except during daily backup) + elif [ "$current_minute" = "00" ] && [ "$current_hour" != "${BACKUP_DAILY_TIME}" ] && [ "$last_hourly_minute" != "$current_minute" ]; then + echo "⏰ [$(date)] Hourly backup time reached, running hourly backup..." + /tmp/backup-hourly.sh + last_hourly_minute="$current_minute" + # Sleep for 2 minutes to avoid running multiple times + sleep 120 + else + # Sleep for 1 minute before checking again + sleep 60 + fi +done \ No newline at end of file diff --git a/scripts/db-import.sh b/scripts/db-import.sh new file mode 100644 index 0000000..8e2e7f6 --- /dev/null +++ b/scripts/db-import.sh @@ -0,0 +1,30 @@ +#!/bin/bash +set -e + +echo 'Waiting for databases to be ready...' + +# Wait for databases to exist with longer timeout +for i in $(seq 1 120); do + if mysql -h ${CONTAINER_MYSQL} -u${MYSQL_USER} -p${MYSQL_ROOT_PASSWORD} -e "USE ${DB_AUTH_NAME}; USE ${DB_WORLD_NAME}; USE ${DB_CHARACTERS_NAME};" >/dev/null 2>&1; then + echo "βœ… All databases accessible" + break + fi + echo "⏳ Waiting for databases... attempt $i/120" + sleep 5 +done + +echo 'Creating config file for dbimport...' +mkdir -p /azerothcore/env/dist/etc +cat > /azerothcore/env/dist/etc/dbimport.conf </dev/null 2>&1; then + echo "βœ… MySQL is responsive" + break + fi + echo "⏳ Waiting for MySQL... attempt $i/${DB_WAIT_RETRIES}" + sleep ${DB_WAIT_SLEEP} +done + +# Check if we should restore from backup +if [ -f "/var/lib/mysql-persistent/backup.sql" ]; then + echo "πŸ”„ Restoring databases from backup..." + mysql -h ${MYSQL_HOST} -u${MYSQL_USER} -p${MYSQL_ROOT_PASSWORD} < /var/lib/mysql-persistent/backup.sql || { + echo "⚠️ Backup restore failed, will create fresh databases" + } +fi + +echo "πŸ—„οΈ Creating/verifying AzerothCore databases..." +mysql -h ${MYSQL_HOST} -u${MYSQL_USER} -p${MYSQL_ROOT_PASSWORD} -e " +CREATE DATABASE IF NOT EXISTS ${DB_AUTH_NAME} DEFAULT CHARACTER SET ${MYSQL_CHARACTER_SET} COLLATE ${MYSQL_COLLATION}; +CREATE DATABASE IF NOT EXISTS ${DB_WORLD_NAME} DEFAULT CHARACTER SET ${MYSQL_CHARACTER_SET} COLLATE ${MYSQL_COLLATION}; +CREATE DATABASE IF NOT EXISTS ${DB_CHARACTERS_NAME} DEFAULT CHARACTER SET ${MYSQL_CHARACTER_SET} COLLATE ${MYSQL_COLLATION}; +SHOW DATABASES; +" || { + echo "❌ Failed to create databases" + exit 1 +} +echo "βœ… Databases ready!" \ No newline at end of file diff --git a/scripts/download-client-data.sh b/scripts/download-client-data.sh new file mode 100644 index 0000000..781f28f --- /dev/null +++ b/scripts/download-client-data.sh @@ -0,0 +1,166 @@ +#!/bin/bash +set -e + +echo 'πŸš€ Starting AzerothCore game data setup...' + +# Get the latest release info from wowgaming/client-data +echo 'πŸ“‘ Fetching latest client data release info...' +RELEASE_INFO=$(wget -qO- https://api.github.com/repos/wowgaming/client-data/releases/latest 2>/dev/null) + +if [ -n "$RELEASE_INFO" ]; then + LATEST_URL=$(echo "$RELEASE_INFO" | grep '"browser_download_url":' | grep '\.zip' | cut -d'"' -f4 | head -1) + LATEST_TAG=$(echo "$RELEASE_INFO" | grep '"tag_name":' | cut -d'"' -f4) + LATEST_SIZE=$(echo "$RELEASE_INFO" | grep '"size":' | head -1 | grep -o '[0-9]*') +fi + +if [ -z "$LATEST_URL" ]; then + echo '❌ Could not fetch latest release URL' + echo 'πŸ“₯ Using fallback: direct download from v16 release' + LATEST_URL='https://github.com/wowgaming/client-data/releases/download/v16/data.zip' + LATEST_TAG='v16' + LATEST_SIZE='0' +fi + +echo "πŸ“ Latest release: $LATEST_TAG" +echo "πŸ“₯ Download URL: $LATEST_URL" + +# Cache file paths +CACHE_FILE="/cache/client-data-$LATEST_TAG.zip" +VERSION_FILE="/cache/client-data-version.txt" + +# Check if we have a cached version +if [ -f "$CACHE_FILE" ] && [ -f "$VERSION_FILE" ]; then + CACHED_VERSION=$(cat "$VERSION_FILE" 2>/dev/null) + if [ "$CACHED_VERSION" = "$LATEST_TAG" ]; then + echo "βœ… Found cached client data version $LATEST_TAG" + echo "πŸ“Š Cached file size: $(ls -lh "$CACHE_FILE" | awk '{print $5}')" + + # Verify cache file integrity + if unzip -t "$CACHE_FILE" > /dev/null 2>&1; then + echo "βœ… Cache file integrity verified" + echo "⚑ Using cached download - skipping download phase" + cp "$CACHE_FILE" data.zip + else + echo "⚠️ Cache file corrupted, will re-download" + rm -f "$CACHE_FILE" "$VERSION_FILE" + fi + else + echo "πŸ“¦ Cache version ($CACHED_VERSION) differs from latest ($LATEST_TAG)" + echo "πŸ—‘οΈ Removing old cache" + rm -f /cache/client-data-*.zip "$VERSION_FILE" + fi +fi + +# Download if we don't have a valid cached file +if [ ! -f "data.zip" ]; then + echo "πŸ“₯ Downloading client data (~15GB, may take 10-30 minutes)..." + echo "πŸ“ Source: $LATEST_URL" + + # Download with clean progress indication + echo "πŸ“₯ Starting download..." + wget --progress=dot:giga -O "$CACHE_FILE.tmp" "$LATEST_URL" 2>&1 | sed 's/^/πŸ“Š /' || { + echo '❌ wget failed, trying curl...' + curl -L --progress-bar -o "$CACHE_FILE.tmp" "$LATEST_URL" || { + echo '❌ All download methods failed' + rm -f "$CACHE_FILE.tmp" + exit 1 + } + } + + # Verify download integrity + if unzip -t "$CACHE_FILE.tmp" > /dev/null 2>&1; then + mv "$CACHE_FILE.tmp" "$CACHE_FILE" + echo "$LATEST_TAG" > "$VERSION_FILE" + echo 'βœ… Download completed and verified' + echo "πŸ“Š File size: $(ls -lh "$CACHE_FILE" | awk '{print $5}')" + cp "$CACHE_FILE" data.zip + else + echo '❌ Downloaded file is corrupted' + rm -f "$CACHE_FILE.tmp" + exit 1 + fi +fi + +echo 'πŸ“‚ Extracting client data (this may take 10-15 minutes)...' +echo '⏳ Please wait while extracting...' + +# Clear existing data if extraction failed previously +rm -rf /azerothcore/data/maps /azerothcore/data/vmaps /azerothcore/data/mmaps /azerothcore/data/dbc + +# Extract with detailed progress tracking +echo 'πŸ”„ Starting extraction with progress monitoring...' + +# Start extraction in background with overwrite +unzip -o -q data.zip -d /azerothcore/data/ & + +UNZIP_PID=$! +LAST_CHECK_TIME=0 + +# Monitor progress with directory size checks +while kill -0 "$UNZIP_PID" 2>/dev/null; do + CURRENT_TIME=$(date +%s) + if [ $((CURRENT_TIME - LAST_CHECK_TIME)) -ge 30 ]; then + LAST_CHECK_TIME=$CURRENT_TIME + + # Check what's been extracted so far + PROGRESS_MSG="πŸ“Š Progress at $(date '+%H:%M:%S'):" + + if [ -d "/azerothcore/data/dbc" ] && [ -n "$(ls -A /azerothcore/data/dbc 2>/dev/null)" ]; then + DBC_SIZE=$(du -sh /azerothcore/data/dbc 2>/dev/null | cut -f1) + PROGRESS_MSG="$PROGRESS_MSG DBC($DBC_SIZE)" + fi + + if [ -d "/azerothcore/data/maps" ] && [ -n "$(ls -A /azerothcore/data/maps 2>/dev/null)" ]; then + MAPS_SIZE=$(du -sh /azerothcore/data/maps 2>/dev/null | cut -f1) + PROGRESS_MSG="$PROGRESS_MSG Maps($MAPS_SIZE)" + fi + + if [ -d "/azerothcore/data/vmaps" ] && [ -n "$(ls -A /azerothcore/data/vmaps 2>/dev/null)" ]; then + VMAPS_SIZE=$(du -sh /azerothcore/data/vmaps 2>/dev/null | cut -f1) + PROGRESS_MSG="$PROGRESS_MSG VMaps($VMAPS_SIZE)" + fi + + if [ -d "/azerothcore/data/mmaps" ] && [ -n "$(ls -A /azerothcore/data/mmaps 2>/dev/null)" ]; then + MMAPS_SIZE=$(du -sh /azerothcore/data/mmaps 2>/dev/null | cut -f1) + PROGRESS_MSG="$PROGRESS_MSG MMaps($MMAPS_SIZE)" + fi + + echo "$PROGRESS_MSG" + fi + sleep 5 +done + +wait "$UNZIP_PID" +UNZIP_EXIT_CODE=$? + +if [ $UNZIP_EXIT_CODE -ne 0 ]; then + echo '❌ Extraction failed' + rm -f data.zip + exit 1 +fi + +# Clean up temporary extraction file (keep cached version) +rm -f data.zip + +echo 'βœ… Client data extraction complete!' +echo 'πŸ“ Verifying extracted directories:' + +# Verify required directories exist and have content +ALL_GOOD=true +for dir in maps vmaps mmaps dbc; do + if [ -d "/azerothcore/data/$dir" ] && [ -n "$(ls -A /azerothcore/data/$dir 2>/dev/null)" ]; then + DIR_SIZE=$(du -sh /azerothcore/data/$dir 2>/dev/null | cut -f1) + echo "βœ… $dir directory: OK ($DIR_SIZE)" + else + echo "❌ $dir directory: MISSING or EMPTY" + ALL_GOOD=false + fi +done + +if [ "$ALL_GOOD" = "true" ]; then + echo 'πŸŽ‰ Game data setup complete! AzerothCore worldserver can now start.' + echo "πŸ’Ύ Cached version $LATEST_TAG for future use" +else + echo '❌ Some directories are missing or empty' + exit 1 +fi \ No newline at end of file diff --git a/scripts/manage-modules-sql.sh b/scripts/manage-modules-sql.sh new file mode 100644 index 0000000..0cfb5d7 --- /dev/null +++ b/scripts/manage-modules-sql.sh @@ -0,0 +1,197 @@ +#!/bin/bash +set -e + +# Function to execute SQL files for a module +execute_module_sql() { + local module_dir="$1" + local module_name="$2" + + echo "Processing SQL scripts for $module_name..." + + # Find and execute SQL files in the module + if [ -d "$module_dir/data/sql" ]; then + # Execute world database scripts + if [ -d "$module_dir/data/sql/world" ]; then + find "$module_dir/data/sql/world" -name "*.sql" -type f | while read sql_file; do + echo " Executing world SQL: $(basename "$sql_file")" + if mariadb --ssl=false -h "${CONTAINER_MYSQL}" -P 3306 -u root -p"${MYSQL_ROOT_PASSWORD}" "${DB_WORLD_NAME}" < "$sql_file" >/dev/null 2>&1; then + echo " βœ… Successfully executed $(basename "$sql_file")" + else + echo " ❌ Failed to execute $sql_file" + fi + done + fi + + # Execute auth database scripts + if [ -d "$module_dir/data/sql/auth" ]; then + find "$module_dir/data/sql/auth" -name "*.sql" -type f | while read sql_file; do + echo " Executing auth SQL: $(basename "$sql_file")" + if mariadb --ssl=false -h "${CONTAINER_MYSQL}" -P 3306 -u root -p"${MYSQL_ROOT_PASSWORD}" "${DB_AUTH_NAME}" < "$sql_file" >/dev/null 2>&1; then + echo " βœ… Successfully executed $(basename "$sql_file")" + else + echo " ❌ Failed to execute $sql_file" + fi + done + fi + + # Execute character database scripts + if [ -d "$module_dir/data/sql/characters" ]; then + find "$module_dir/data/sql/characters" -name "*.sql" -type f | while read sql_file; do + echo " Executing characters SQL: $(basename "$sql_file")" + if mariadb --ssl=false -h "${CONTAINER_MYSQL}" -P 3306 -u root -p"${MYSQL_ROOT_PASSWORD}" "${DB_CHARACTERS_NAME}" < "$sql_file" >/dev/null 2>&1; then + echo " βœ… Successfully executed $(basename "$sql_file")" + else + echo " ❌ Failed to execute $sql_file" + fi + done + fi + + # Execute base SQL files (common pattern) + find "$module_dir/data/sql" -maxdepth 1 -name "*.sql" -type f | while read sql_file; do + echo " Executing base SQL: $(basename "$sql_file")" + mysql -h "${CONTAINER_MYSQL}" -P 3306 -u root -p"${MYSQL_ROOT_PASSWORD}" "${DB_WORLD_NAME}" < "$sql_file" 2>/dev/null || echo " Warning: Failed to execute $sql_file" + done + fi + + # Look for SQL files in other common locations + if [ -d "$module_dir/sql" ]; then + find "$module_dir/sql" -name "*.sql" -type f | while read sql_file; do + echo " Executing SQL: $(basename "$sql_file")" + mysql -h "${CONTAINER_MYSQL}" -P 3306 -u root -p"${MYSQL_ROOT_PASSWORD}" "${DB_WORLD_NAME}" < "$sql_file" 2>/dev/null || echo " Warning: Failed to execute $sql_file" + done + fi +} + +# Main function to execute SQL for all enabled modules +execute_module_sql_scripts() { + # Install MariaDB client if not available + which mariadb >/dev/null 2>&1 || { + echo "Installing MariaDB client..." + apk add --no-cache mariadb-client >/dev/null 2>&1 || echo "Warning: Could not install MariaDB client" + } + + # Execute SQL for enabled modules only + if [ "$MODULE_PLAYERBOTS" = "1" ] && [ -d "mod-playerbots" ]; then + execute_module_sql "mod-playerbots" "Playerbots" + fi + + if [ "$MODULE_AOE_LOOT" = "1" ] && [ -d "mod-aoe-loot" ]; then + execute_module_sql "mod-aoe-loot" "AoE Loot" + fi + + if [ "$MODULE_LEARN_SPELLS" = "1" ] && [ -d "mod-learn-spells" ]; then + execute_module_sql "mod-learn-spells" "Learn Spells" + fi + + if [ "$MODULE_FIREWORKS" = "1" ] && [ -d "mod-fireworks-on-level" ]; then + execute_module_sql "mod-fireworks-on-level" "Fireworks" + fi + + if [ "$MODULE_INDIVIDUAL_PROGRESSION" = "1" ] && [ -d "mod-individual-progression" ]; then + execute_module_sql "mod-individual-progression" "Individual Progression" + fi + + if [ "$MODULE_AHBOT" = "1" ] && [ -d "mod-ahbot" ]; then + execute_module_sql "mod-ahbot" "AHBot" + fi + + if [ "$MODULE_AUTOBALANCE" = "1" ] && [ -d "mod-autobalance" ]; then + execute_module_sql "mod-autobalance" "AutoBalance" + fi + + if [ "$MODULE_TRANSMOG" = "1" ] && [ -d "mod-transmog" ]; then + execute_module_sql "mod-transmog" "Transmog" + fi + + if [ "$MODULE_NPC_BUFFER" = "1" ] && [ -d "mod-npc-buffer" ]; then + execute_module_sql "mod-npc-buffer" "NPC Buffer" + fi + + if [ "$MODULE_DYNAMIC_XP" = "1" ] && [ -d "mod-dynamic-xp" ]; then + execute_module_sql "mod-dynamic-xp" "Dynamic XP" + fi + + if [ "$MODULE_SOLO_LFG" = "1" ] && [ -d "mod-solo-lfg" ]; then + execute_module_sql "mod-solo-lfg" "Solo LFG" + fi + + if [ "$MODULE_1V1_ARENA" = "1" ] && [ -d "mod-1v1-arena" ]; then + execute_module_sql "mod-1v1-arena" "1v1 Arena" + fi + + if [ "$MODULE_PHASED_DUELS" = "1" ] && [ -d "mod-phased-duels" ]; then + execute_module_sql "mod-phased-duels" "Phased Duels" + fi + + if [ "$MODULE_BREAKING_NEWS" = "1" ] && [ -d "mod-breaking-news-override" ]; then + execute_module_sql "mod-breaking-news-override" "Breaking News" + fi + + if [ "$MODULE_BOSS_ANNOUNCER" = "1" ] && [ -d "mod-boss-announcer" ]; then + execute_module_sql "mod-boss-announcer" "Boss Announcer" + fi + + if [ "$MODULE_ACCOUNT_ACHIEVEMENTS" = "1" ] && [ -d "mod-account-achievements" ]; then + execute_module_sql "mod-account-achievements" "Account Achievements" + fi + + if [ "$MODULE_AUTO_REVIVE" = "1" ] && [ -d "mod-auto-revive" ]; then + execute_module_sql "mod-auto-revive" "Auto Revive" + fi + + if [ "$MODULE_GAIN_HONOR_GUARD" = "1" ] && [ -d "mod-gain-honor-guard" ]; then + execute_module_sql "mod-gain-honor-guard" "Gain Honor Guard" + fi + + if [ "$MODULE_ELUNA" = "1" ] && [ -d "mod-eluna" ]; then + execute_module_sql "mod-eluna" "Eluna" + fi + if [ "$MODULE_ARAC" = "1" ] && [ -d "mod-arac" ]; then + execute_module_sql "mod-arac" "All Races All Classes" + fi + + if [ "$MODULE_TIME_IS_TIME" = "1" ] && [ -d "mod-TimeIsTime" ]; then + execute_module_sql "mod-TimeIsTime" "Time Is Time" + fi + + if [ "$MODULE_POCKET_PORTAL" = "1" ] && [ -d "mod-pocket-portal" ]; then + execute_module_sql "mod-pocket-portal" "Pocket Portal" + fi + + if [ "$MODULE_RANDOM_ENCHANTS" = "1" ] && [ -d "mod-random-enchants" ]; then + execute_module_sql "mod-random-enchants" "Random Enchants" + fi + + if [ "$MODULE_SOLOCRAFT" = "1" ] && [ -d "mod-solocraft" ]; then + execute_module_sql "mod-solocraft" "Solocraft" + fi + + if [ "$MODULE_PVP_TITLES" = "1" ] && [ -d "mod-pvp-titles" ]; then + execute_module_sql "mod-pvp-titles" "PvP Titles" + fi + + if [ "$MODULE_NPC_BEASTMASTER" = "1" ] && [ -d "mod-npc-beastmaster" ]; then + execute_module_sql "mod-npc-beastmaster" "NPC Beastmaster" + fi + + if [ "$MODULE_NPC_ENCHANTER" = "1" ] && [ -d "mod-npc-enchanter" ]; then + execute_module_sql "mod-npc-enchanter" "NPC Enchanter" + fi + + if [ "$MODULE_INSTANCE_RESET" = "1" ] && [ -d "mod-instance-reset" ]; then + execute_module_sql "mod-instance-reset" "Instance Reset" + fi + + if [ "$MODULE_LEVEL_GRANT" = "1" ] && [ -d "mod-quest-count-level" ]; then + execute_module_sql "mod-quest-count-level" "Level Grant" + fi + if [ "$MODULE_ASSISTANT" = "1" ] && [ -d "mod-assistant" ]; then + execute_module_sql "mod-assistant" "Assistant" + fi + if [ "$MODULE_REAGENT_BANK" = "1" ] && [ -d "mod-reagent-bank" ]; then + execute_module_sql "mod-reagent-bank" "Reagent Bank" + fi + if [ "$MODULE_BLACK_MARKET_AUCTION_HOUSE" = "1" ] && [ -d "mod-black-market" ]; then + execute_module_sql "mod-black-market" "Black Market" + fi +} \ No newline at end of file diff --git a/scripts/manage-modules.sh b/scripts/manage-modules.sh new file mode 100644 index 0000000..feabe3c --- /dev/null +++ b/scripts/manage-modules.sh @@ -0,0 +1,685 @@ +#!/bin/bash +set -e + +echo 'Setting up git user' +git config --global user.name "$GIT_USERNAME" +git config --global user.email "$GIT_EMAIL" +git config --global url.https://$GIT_PAT@github.com/.insteadOf https://github.com/ + +echo 'Initializing module management...' +cd /modules + +echo 'Cleaning up disabled modules...' + +# Remove modules if disabled +if [ "$MODULE_PLAYERBOTS" != "1" ] && [ -d "mod-playerbots" ]; then + echo 'Removing mod-playerbots (disabled)...' + rm -rf mod-playerbots +fi + +if [ "$MODULE_AOE_LOOT" != "1" ] && [ -d "mod-aoe-loot" ]; then + echo 'Removing mod-aoe-loot (disabled)...' + rm -rf mod-aoe-loot +fi + +if [ "$MODULE_LEARN_SPELLS" != "1" ] && [ -d "mod-learn-spells" ]; then + echo 'Removing mod-learn-spells (disabled)...' + rm -rf mod-learn-spells +fi + +if [ "$MODULE_FIREWORKS" != "1" ] && [ -d "mod-fireworks-on-level" ]; then + echo 'Removing mod-fireworks-on-level (disabled)...' + rm -rf mod-fireworks-on-level +fi + +if [ "$MODULE_INDIVIDUAL_PROGRESSION" != "1" ] && [ -d "mod-individual-progression" ]; then + echo 'Removing mod-individual-progression (disabled)...' + rm -rf mod-individual-progression +fi + +if [ "$MODULE_AHBOT" != "1" ] && [ -d "mod-ahbot" ]; then + echo 'Removing mod-ahbot (disabled)...' + rm -rf mod-ahbot +fi + +if [ "$MODULE_AUTOBALANCE" != "1" ] && [ -d "mod-autobalance" ]; then + echo 'Removing mod-autobalance (disabled)...' + rm -rf mod-autobalance +fi + +if [ "$MODULE_TRANSMOG" != "1" ] && [ -d "mod-transmog" ]; then + echo 'Removing mod-transmog (disabled)...' + rm -rf mod-transmog +fi + +if [ "$MODULE_NPC_BUFFER" != "1" ] && [ -d "mod-npc-buffer" ]; then + echo 'Removing mod-npc-buffer (disabled)...' + rm -rf mod-npc-buffer +fi + +if [ "$MODULE_DYNAMIC_XP" != "1" ] && [ -d "mod-dynamic-xp" ]; then + echo 'Removing mod-dynamic-xp (disabled)...' + rm -rf mod-dynamic-xp +fi + +if [ "$MODULE_SOLO_LFG" != "1" ] && [ -d "mod-solo-lfg" ]; then + echo 'Removing mod-solo-lfg (disabled)...' + rm -rf mod-solo-lfg +fi + +if [ "$MODULE_1V1_ARENA" != "1" ] && [ -d "mod-1v1-arena" ]; then + echo 'Removing mod-1v1-arena (disabled)...' + rm -rf mod-1v1-arena +fi + +if [ "$MODULE_PHASED_DUELS" != "1" ] && [ -d "mod-phased-duels" ]; then + echo 'Removing mod-phased-duels (disabled)...' + rm -rf mod-phased-duels +fi + +if [ "$MODULE_BREAKING_NEWS" != "1" ] && [ -d "mod-breaking-news-override" ]; then + echo 'Removing mod-breaking-news-override (disabled)...' + rm -rf mod-breaking-news-override +fi + +if [ "$MODULE_BOSS_ANNOUNCER" != "1" ] && [ -d "mod-boss-announcer" ]; then + echo 'Removing mod-boss-announcer (disabled)...' + rm -rf mod-boss-announcer +fi + +if [ "$MODULE_ACCOUNT_ACHIEVEMENTS" != "1" ] && [ -d "mod-account-achievements" ]; then + echo 'Removing mod-account-achievements (disabled)...' + rm -rf mod-account-achievements +fi + +if [ "$MODULE_AUTO_REVIVE" != "1" ] && [ -d "mod-auto-revive" ]; then + echo 'Removing mod-auto-revive (disabled)...' + rm -rf mod-auto-revive +fi + +if [ "$MODULE_GAIN_HONOR_GUARD" != "1" ] && [ -d "mod-gain-honor-guard" ]; then + echo 'Removing mod-gain-honor-guard (disabled)...' + rm -rf mod-gain-honor-guard +fi + +if [ "$MODULE_ELUNA" != "1" ] && [ -d "mod-eluna" ]; then + echo 'Removing mod-eluna (disabled)...' + rm -rf mod-eluna +fi +if [ "$MODULE_ARAC" != "1" ] && [ -d "mod-arac" ]; then + echo 'Removing mod-arac (disabled)...' + rm -rf mod-arac +fi + +if [ "$MODULE_TIME_IS_TIME" != "1" ] && [ -d "mod-TimeIsTime" ]; then + echo 'Removing mod-TimeIsTime (disabled)...' + rm -rf mod-TimeIsTime +fi + +if [ "$MODULE_POCKET_PORTAL" != "1" ] && [ -d "mod-pocket-portal" ]; then + echo 'Removing mod-pocket-portal (disabled)...' + rm -rf mod-pocket-portal +fi + +if [ "$MODULE_RANDOM_ENCHANTS" != "1" ] && [ -d "mod-random-enchants" ]; then + echo 'Removing mod-random-enchants (disabled)...' + rm -rf mod-random-enchants +fi + +if [ "$MODULE_SOLOCRAFT" != "1" ] && [ -d "mod-solocraft" ]; then + echo 'Removing mod-solocraft (disabled)...' + rm -rf mod-solocraft +fi + +if [ "$MODULE_PVP_TITLES" != "1" ] && [ -d "mod-pvp-titles" ]; then + echo 'Removing mod-pvp-titles (disabled)...' + rm -rf mod-pvp-titles +fi + +if [ "$MODULE_NPC_BEASTMASTER" != "1" ] && [ -d "mod-npc-beastmaster" ]; then + echo 'Removing mod-npc-beastmaster (disabled)...' + rm -rf mod-npc-beastmaster +fi + +if [ "$MODULE_NPC_ENCHANTER" != "1" ] && [ -d "mod-npc-enchanter" ]; then + echo 'Removing mod-npc-enchanter (disabled)...' + rm -rf mod-npc-enchanter +fi + +if [ "$MODULE_INSTANCE_RESET" != "1" ] && [ -d "mod-instance-reset" ]; then + echo 'Removing mod-instance-reset (disabled)...' + rm -rf mod-instance-reset +fi + +if [ "$MODULE_LEVEL_GRANT" != "1" ] && [ -d "mod-quest-count-level" ]; then + echo 'Removing mod-quest-count-level (disabled)...' + rm -rf mod-quest-count-level +fi +if [ "$MODULE_ASSISTANT" != "1" ] && [ -d "mod-assistant" ]; then + echo 'Removing mod-assistant (disabled)...' + rm -rf mod-assistant +fi +if [ "$MODULE_REAGENT_BANK" != "1" ] && [ -d "mod-reagent-bank" ]; then + echo 'Removing mod-reagent-bank (disabled)...' + rm -rf mod-reagent-bank +fi +if [ "$MODULE_BLACK_MARKET_AUCTION_HOUSE" != "1" ] && [ -d "mod-black-market" ]; then + echo 'Removing mod-black-market (disabled)...' + rm -rf mod-black-market +fi + +echo 'Installing enabled modules...' + +# Install Playerbots if enabled +if [ "$MODULE_PLAYERBOTS" = "1" ] && [ ! -d "mod-playerbots" ]; then + echo 'πŸ€– Installing mod-playerbots...' + echo ' πŸ“– Project: https://github.com/liyunfan1223/mod-playerbots' + echo ' 🚨 CRITICAL: REQUIRES Custom AzerothCore branch (liyunfan1223/azerothcore-wotlk/tree/Playerbot)' + echo ' 🚨 INCOMPATIBLE with standard AzerothCore - module will not function properly' + echo ' πŸ”§ REBUILD REQUIRED: Container must be rebuilt with source-based compilation' + echo ' πŸ“‹ POST-INSTALL: Requires manual account/character configuration' + echo ' πŸ”¬ STATUS: IN TESTING - Currently under verification' + git clone https://github.com/liyunfan1223/mod-playerbots.git mod-playerbots +fi + +# Install AOE Loot if enabled +if [ "$MODULE_AOE_LOOT" = "1" ] && [ ! -d "mod-aoe-loot" ]; then + echo 'πŸ’° Installing mod-aoe-loot...' + echo ' πŸ“– Project: https://github.com/azerothcore/mod-aoe-loot' + echo ' ℹ️ Allows looting multiple corpses with one action' + echo ' πŸ”§ REBUILD REQUIRED: Container must be rebuilt with source-based compilation' + echo ' πŸ”¬ STATUS: IN TESTING - Currently under verification' + git clone https://github.com/azerothcore/mod-aoe-loot.git mod-aoe-loot +fi + +# Install Learn Spells if enabled +if [ "$MODULE_LEARN_SPELLS" = "1" ] && [ ! -d "mod-learn-spells" ]; then + echo 'πŸ“š Installing mod-learn-spells...' + echo ' πŸ“– Project: https://github.com/azerothcore/mod-learn-spells' + echo ' ℹ️ Automatically teaches class spells on level up' + echo ' πŸ”§ REBUILD REQUIRED: Container must be rebuilt with source-based compilation' + echo ' πŸ”¬ STATUS: IN TESTING - Currently under verification' + git clone https://github.com/azerothcore/mod-learn-spells.git mod-learn-spells +fi + +# Install Fireworks on Level if enabled +if [ "$MODULE_FIREWORKS" = "1" ] && [ ! -d "mod-fireworks-on-level" ]; then + echo 'πŸŽ† Installing mod-fireworks-on-level...' + echo ' πŸ“– Project: https://github.com/azerothcore/mod-fireworks-on-level' + echo ' ℹ️ Displays fireworks when players level up' + echo ' πŸ”§ REBUILD REQUIRED: Container must be rebuilt with source-based compilation' + echo ' πŸ”¬ STATUS: IN TESTING - Currently under verification' + git clone https://github.com/azerothcore/mod-fireworks-on-level.git mod-fireworks-on-level +fi + +# Install Individual Progression if enabled +if [ "$MODULE_INDIVIDUAL_PROGRESSION" = "1" ] && [ ! -d "mod-individual-progression" ]; then + echo '⏳ Installing mod-individual-progression...' + echo ' πŸ“– Project: https://github.com/ZhengPeiRu21/mod-individual-progression' + echo ' ℹ️ Simulates authentic Vanillaβ†’TBCβ†’WotLK progression per player' + echo ' βœ… AUTO-CONFIG: Automatically sets EnablePlayerSettings=1 and DBC.EnforceItemAttributes=0' + echo ' πŸ”§ REBUILD REQUIRED: Container must be rebuilt with source-based compilation' + echo ' πŸ“ Optional client files available in optional/ directory' + echo ' πŸ”¬ STATUS: IN TESTING - Currently under verification' + git clone https://github.com/ZhengPeiRu21/mod-individual-progression.git mod-individual-progression +fi + +# Quality of Life Modules +if [ "$MODULE_AHBOT" = "1" ] && [ ! -d "mod-ahbot" ]; then + echo 'πŸͺ Installing mod-ahbot...' + echo ' πŸ“– Project: https://github.com/azerothcore/mod-ahbot' + echo ' ℹ️ Auction house bot that buys and sells items automatically' + echo ' πŸ”§ REBUILD REQUIRED: Container must be rebuilt with source-based compilation' + echo ' πŸ“‹ POST-INSTALL: Requires manual account/character setup in mod_ahbot.conf' + git clone https://github.com/azerothcore/mod-ahbot.git mod-ahbot +fi + +if [ "$MODULE_AUTOBALANCE" = "1" ] && [ ! -d "mod-autobalance" ]; then + echo 'βš–οΈ Installing mod-autobalance...' + echo ' πŸ“– Project: https://github.com/azerothcore/mod-autobalance' + echo ' ℹ️ Automatically adjusts dungeon difficulty based on party size' + echo ' πŸ”§ REBUILD REQUIRED: Container must be rebuilt with source-based compilation' + git clone https://github.com/azerothcore/mod-autobalance.git mod-autobalance +fi + +if [ "$MODULE_TRANSMOG" = "1" ] && [ ! -d "mod-transmog" ]; then + echo '🎭 Installing mod-transmog...' + echo ' πŸ“– Project: https://github.com/azerothcore/mod-transmog' + echo ' ℹ️ Allows appearance customization of equipment' + echo ' πŸ”§ REBUILD REQUIRED: Container must be rebuilt with source-based compilation' + echo ' πŸ”¬ STATUS: IN TESTING - Currently under verification' + git clone https://github.com/azerothcore/mod-transmog.git mod-transmog +fi + +if [ "$MODULE_NPC_BUFFER" = "1" ] && [ ! -d "mod-npc-buffer" ]; then + echo 'Installing mod-npc-buffer...' + git clone https://github.com/azerothcore/mod-npc-buffer.git mod-npc-buffer +fi + +# Gameplay Enhancement Modules +if [ "$MODULE_DYNAMIC_XP" = "1" ] && [ ! -d "mod-dynamic-xp" ]; then + echo 'Installing mod-dynamic-xp...' + git clone https://github.com/azerothcore/mod-dynamic-xp.git mod-dynamic-xp +fi + +if [ "$MODULE_SOLO_LFG" = "1" ] && [ ! -d "mod-solo-lfg" ]; then + echo 'πŸ” Installing mod-solo-lfg...' + echo ' πŸ“– Project: https://github.com/azerothcore/mod-solo-lfg' + echo ' ℹ️ Allows dungeon finder for solo players and small groups' + echo ' πŸ”§ REBUILD REQUIRED: Container must be rebuilt with source-based compilation' + echo ' πŸ’‘ Pairs perfectly with mod-solocraft and mod-autobalance' + echo ' πŸ”¬ STATUS: IN TESTING - Currently under verification' + git clone https://github.com/azerothcore/mod-solo-lfg.git mod-solo-lfg +fi + +if [ "$MODULE_1V1_ARENA" = "1" ] && [ ! -d "mod-1v1-arena" ]; then + echo 'Installing mod-1v1-arena...' + git clone https://github.com/azerothcore/mod-1v1-arena.git mod-1v1-arena +fi + +if [ "$MODULE_PHASED_DUELS" = "1" ] && [ ! -d "mod-phased-duels" ]; then + echo 'Installing mod-phased-duels...' + git clone https://github.com/azerothcore/mod-phased-duels.git mod-phased-duels +fi + +# Server Management Modules +if [ "$MODULE_BREAKING_NEWS" = "1" ] && [ ! -d "mod-breaking-news-override" ]; then + echo 'πŸ“° Installing mod-breaking-news-override...' + echo ' πŸ“– Project: https://github.com/azerothcore/mod-breaking-news-override' + echo ' ℹ️ Displays custom breaking news on character selection screen' + echo ' πŸ”§ REBUILD REQUIRED: Container must be rebuilt with source-based compilation' + echo ' πŸ“‹ POST-INSTALL: Requires custom HTML file creation and path configuration' + git clone https://github.com/azerothcore/mod-breaking-news-override.git mod-breaking-news-override +fi + +if [ "$MODULE_BOSS_ANNOUNCER" = "1" ] && [ ! -d "mod-boss-announcer" ]; then + echo 'Installing mod-boss-announcer...' + git clone https://github.com/azerothcore/mod-boss-announcer.git mod-boss-announcer +fi + +if [ "$MODULE_ACCOUNT_ACHIEVEMENTS" = "1" ] && [ ! -d "mod-account-achievements" ]; then + echo 'Installing mod-account-achievements...' + git clone https://github.com/azerothcore/mod-account-achievements.git mod-account-achievements +fi + +# Additional Modules Found in Config +if [ "$MODULE_AUTO_REVIVE" = "1" ] && [ ! -d "mod-auto-revive" ]; then + echo 'Installing mod-auto-revive...' + git clone https://github.com/azerothcore/mod-auto-revive.git mod-auto-revive +fi + +if [ "$MODULE_GAIN_HONOR_GUARD" = "1" ] && [ ! -d "mod-gain-honor-guard" ]; then + echo 'Installing mod-gain-honor-guard...' + git clone https://github.com/azerothcore/mod-gain-honor-guard.git mod-gain-honor-guard +fi + +if [ "$MODULE_ELUNA" = "1" ] && [ ! -d "mod-eluna" ]; then + echo 'πŸ–₯️ Installing mod-eluna...' + echo ' πŸ“– Project: https://github.com/azerothcore/mod-eluna' + echo ' ℹ️ Lua scripting engine for custom server functionality' + echo ' πŸ”§ REBUILD REQUIRED: Container must be rebuilt with source-based compilation' + echo ' πŸ”¬ STATUS: IN TESTING - Currently under verification' + git clone https://github.com/azerothcore/mod-eluna.git mod-eluna +fi +if [ "$MODULE_ARAC" = "1" ] && [ ! -d "mod-arac" ]; then + echo '🌈 Installing mod-arac...' + echo ' πŸ“– Project: https://github.com/heyitsbench/mod-arac' + echo ' ℹ️ All Races All Classes - Removes class restrictions' + echo ' 🚨 CRITICAL: Requires DBC file updates and client patch!' + echo ' πŸ“‹ POST-INSTALL: Apply Patch-A.MPQ to client WoW/Data/ directory' + echo ' πŸ”¬ STATUS: IN TESTING - Currently under verification' + git clone https://github.com/heyitsbench/mod-arac.git mod-arac +fi + +if [ "$MODULE_TIME_IS_TIME" = "1" ] && [ ! -d "mod-TimeIsTime" ]; then + echo 'Installing mod-TimeIsTime...' + git clone https://github.com/dunjeon/mod-TimeIsTime.git mod-TimeIsTime +fi + +if [ "$MODULE_POCKET_PORTAL" = "1" ] && [ ! -d "mod-pocket-portal" ]; then + echo 'Installing mod-pocket-portal...' + git clone https://github.com/azerothcore/mod-pocket-portal.git mod-pocket-portal +fi + +if [ "$MODULE_RANDOM_ENCHANTS" = "1" ] && [ ! -d "mod-random-enchants" ]; then + echo 'Installing mod-random-enchants...' + git clone https://github.com/azerothcore/mod-random-enchants.git mod-random-enchants +fi + +if [ "$MODULE_SOLOCRAFT" = "1" ] && [ ! -d "mod-solocraft" ]; then + echo '🎯 Installing mod-solocraft...' + echo ' πŸ“– Project: https://github.com/azerothcore/mod-solocraft' + echo ' ℹ️ Scales dungeon/raid difficulty for solo players' + echo ' πŸ”§ REBUILD REQUIRED: Container must be rebuilt with source-based compilation' + echo ' πŸ’‘ Works well with mod-autobalance and mod-solo-lfg' + git clone https://github.com/azerothcore/mod-solocraft.git mod-solocraft +fi + +if [ "$MODULE_PVP_TITLES" = "1" ] && [ ! -d "mod-pvp-titles" ]; then + echo 'Installing mod-pvp-titles...' + git clone https://github.com/azerothcore/mod-pvp-titles.git mod-pvp-titles +fi + +if [ "$MODULE_NPC_BEASTMASTER" = "1" ] && [ ! -d "mod-npc-beastmaster" ]; then + echo 'Installing mod-npc-beastmaster...' + git clone https://github.com/azerothcore/mod-npc-beastmaster.git mod-npc-beastmaster +fi + +if [ "$MODULE_NPC_ENCHANTER" = "1" ] && [ ! -d "mod-npc-enchanter" ]; then + echo '✨ Installing mod-npc-enchanter...' + echo ' πŸ“– Project: https://github.com/azerothcore/mod-npc-enchanter' + echo ' ℹ️ NPC that provides enchanting services' + echo ' πŸ”§ REBUILD REQUIRED: Container must be rebuilt with source-based compilation' + echo ' πŸ”¬ STATUS: IN TESTING - Currently under verification' + git clone https://github.com/azerothcore/mod-npc-enchanter.git mod-npc-enchanter +fi + +if [ "$MODULE_INSTANCE_RESET" = "1" ] && [ ! -d "mod-instance-reset" ]; then + echo 'Installing mod-instance-reset...' + git clone https://github.com/azerothcore/mod-instance-reset.git mod-instance-reset +fi + +if [ "$MODULE_LEVEL_GRANT" = "1" ] && [ ! -d "mod-quest-count-level" ]; then + echo 'Installing mod-quest-count-level...' + git clone https://github.com/michaeldelago/mod-quest-count-level.git mod-quest-count-level +fi +if [ "$MODULE_ASSISTANT" = "1" ] && [ ! -d "mod-assistant" ]; then + echo 'πŸ€– Installing mod-assistant...' + echo ' πŸ“– Project: https://github.com/noisiver/mod-assistant' + echo ' ℹ️ NPC (ID: 9000000) providing heirlooms, glyphs, gems, profession services' + echo ' πŸ”§ REBUILD REQUIRED: Container must be rebuilt with source-based compilation' + echo ' πŸ”¬ STATUS: IN TESTING - Currently under verification' + git clone https://github.com/noisiver/mod-assistant.git mod-assistant +fi +if [ "$MODULE_REAGENT_BANK" = "1" ] && [ ! -d "mod-reagent-bank" ]; then + echo '🏦 Installing mod-reagent-bank...' + echo ' πŸ“– Project: https://github.com/ZhengPeiRu21/mod-reagent-bank' + echo ' ℹ️ Reagent banker NPC for storing crafting materials, frees bag space' + echo ' πŸ”§ REBUILD REQUIRED: Container must be rebuilt with source-based compilation' + echo ' πŸ”¬ STATUS: IN TESTING - Currently under verification' + git clone https://github.com/ZhengPeiRu21/mod-reagent-bank.git mod-reagent-bank +fi +if [ "$MODULE_BLACK_MARKET_AUCTION_HOUSE" = "1" ] && [ ! -d "mod-black-market" ]; then + echo 'πŸ΄β€β˜ οΈ Installing mod-black-market...' + echo ' πŸ“– Project: https://github.com/Youpeoples/Black-Market-Auction-House' + echo ' ℹ️ MoP Black Market Auction House backported using Eluna Lua engine' + echo ' ⚠️ SPECIAL MODULE: Uses Lua scripts, not C++ compilation' + echo ' πŸ”§ REQUIRES: mod-eluna must be enabled and functional' + echo ' πŸ”¬ STATUS: IN TESTING - Currently under verification' + git clone https://github.com/Youpeoples/Black-Market-Auction-House.git mod-black-market + + # Special handling: Copy Lua scripts to lua_scripts directory + if [ "$MODULE_ELUNA" = "1" ] && [ -d "mod-black-market/Server Files/lua_scripts" ]; then + echo ' πŸ”§ Integrating Black Market Lua scripts with mod-eluna...' + mkdir -p /azerothcore/lua_scripts + cp -r mod-black-market/Server\ Files/lua_scripts/* /azerothcore/lua_scripts/ 2>/dev/null || true + echo ' βœ… Black Market Lua scripts copied to /azerothcore/lua_scripts directory' + ls -la /azerothcore/lua_scripts/ | grep -E "\.lua$" || echo " ℹ️ No .lua files found after copy" + else + echo ' ⚠️ WARNING: mod-eluna not enabled - Black Market will not function' + fi +fi + +echo 'Managing configuration files...' + +# Remove configuration files for disabled modules +if [ "$MODULE_PLAYERBOTS" != "1" ]; then + rm -f /azerothcore/env/dist/etc/playerbots.conf* +fi + +if [ "$MODULE_AOE_LOOT" != "1" ]; then + rm -f /azerothcore/env/dist/etc/mod_aoe_loot.conf* +fi + +if [ "$MODULE_LEARN_SPELLS" != "1" ]; then + rm -f /azerothcore/env/dist/etc/mod_learnspells.conf* +fi + +if [ "$MODULE_FIREWORKS" != "1" ]; then + rm -f /azerothcore/env/dist/etc/mod_fireworks.conf* +fi + +if [ "$MODULE_INDIVIDUAL_PROGRESSION" != "1" ]; then + rm -f /azerothcore/env/dist/etc/individual_progression.conf* +fi + +if [ "$MODULE_AHBOT" != "1" ]; then + rm -f /azerothcore/env/dist/etc/mod_ahbot.conf* +fi + +if [ "$MODULE_AUTOBALANCE" != "1" ]; then + rm -f /azerothcore/env/dist/etc/AutoBalance.conf* +fi + +if [ "$MODULE_TRANSMOG" != "1" ]; then + rm -f /azerothcore/env/dist/etc/transmog.conf* +fi + +if [ "$MODULE_NPC_BUFFER" != "1" ]; then + rm -f /azerothcore/env/dist/etc/npc_buffer.conf* +fi + +if [ "$MODULE_DYNAMIC_XP" != "1" ]; then + rm -f /azerothcore/env/dist/etc/Individual-XP.conf* +fi + +if [ "$MODULE_SOLO_LFG" != "1" ]; then + rm -f /azerothcore/env/dist/etc/SoloLfg.conf* +fi + +if [ "$MODULE_1V1_ARENA" != "1" ]; then + rm -f /azerothcore/env/dist/etc/1v1arena.conf* +fi + +if [ "$MODULE_PHASED_DUELS" != "1" ]; then + rm -f /azerothcore/env/dist/etc/phasedduels.conf* +fi + +if [ "$MODULE_BREAKING_NEWS" != "1" ]; then + rm -f /azerothcore/env/dist/etc/breaking_news.conf* +fi + +if [ "$MODULE_BOSS_ANNOUNCER" != "1" ]; then + rm -f /azerothcore/env/dist/etc/boss_announcer.conf* +fi + +if [ "$MODULE_ACCOUNT_ACHIEVEMENTS" != "1" ]; then + rm -f /azerothcore/env/dist/etc/account_achievements.conf* +fi + +if [ "$MODULE_AUTO_REVIVE" != "1" ]; then + rm -f /azerothcore/env/dist/etc/AutoRevive.conf* +fi + +if [ "$MODULE_GAIN_HONOR_GUARD" != "1" ]; then + rm -f /azerothcore/env/dist/etc/GainHonorGuard.conf* +fi + +if [ "$MODULE_ELUNA" != "1" ]; then + rm -f /azerothcore/env/dist/etc/mod_eluna.conf* +fi +if [ "$MODULE_ARAC" != "1" ]; then + rm -f /azerothcore/env/dist/etc/arac.conf* +fi + +if [ "$MODULE_TIME_IS_TIME" != "1" ]; then + rm -f /azerothcore/env/dist/etc/mod-time_is_time.conf* +fi + +if [ "$MODULE_POCKET_PORTAL" != "1" ]; then + rm -f /azerothcore/env/dist/etc/pocketportal.conf* +fi + +if [ "$MODULE_RANDOM_ENCHANTS" != "1" ]; then + rm -f /azerothcore/env/dist/etc/RandomEnchants.conf* +fi + +if [ "$MODULE_SOLOCRAFT" != "1" ]; then + rm -f /azerothcore/env/dist/etc/Solocraft.conf* +fi + +if [ "$MODULE_PVP_TITLES" != "1" ]; then + rm -f /azerothcore/env/dist/etc/mod_pvptitles.conf* +fi + +if [ "$MODULE_NPC_BEASTMASTER" != "1" ]; then + rm -f /azerothcore/env/dist/etc/npc_beastmaster.conf* +fi + +if [ "$MODULE_NPC_ENCHANTER" != "1" ]; then + rm -f /azerothcore/env/dist/etc/npc_enchanter.conf* +fi + +if [ "$MODULE_INSTANCE_RESET" != "1" ]; then + rm -f /azerothcore/env/dist/etc/instance-reset.conf* +fi + +if [ "$MODULE_LEVEL_GRANT" != "1" ]; then + rm -f /azerothcore/env/dist/etc/levelGrant.conf* +fi + +if [ "$MODULE_ASSISTANT" != "1" ]; then + rm -f /azerothcore/env/dist/etc/mod_assistant.conf* +fi + +if [ "$MODULE_REAGENT_BANK" != "1" ]; then + rm -f /azerothcore/env/dist/etc/mod_reagent_bank.conf* +fi + +if [ "$MODULE_BLACK_MARKET_AUCTION_HOUSE" != "1" ]; then + rm -f /azerothcore/env/dist/etc/mod_black_market.conf* +fi + +# Install configuration files for enabled modules +for module_dir in mod-*; do + if [ -d "$module_dir" ]; then + echo "Installing config files for $module_dir..." + find "$module_dir" -name "*.conf.dist" -exec cp {} /azerothcore/env/dist/etc/ \; 2>/dev/null || true + fi +done + +echo 'Configuration file management complete.' + +# Source the SQL module management functions +source /scripts/manage-modules-sql.sh + +echo 'Executing module SQL scripts...' +execute_module_sql_scripts + +echo 'SQL execution complete.' + +# Module state tracking and rebuild logic +echo 'Checking for module changes that require rebuild...' + +MODULES_STATE_FILE="/modules/.modules_state" +CURRENT_STATE="" +REBUILD_REQUIRED=0 + +# Create current module state hash +for module_var in MODULE_PLAYERBOTS MODULE_AOE_LOOT MODULE_LEARN_SPELLS MODULE_FIREWORKS MODULE_INDIVIDUAL_PROGRESSION MODULE_AHBOT MODULE_AUTOBALANCE MODULE_TRANSMOG MODULE_NPC_BUFFER MODULE_DYNAMIC_XP MODULE_SOLO_LFG MODULE_1V1_ARENA MODULE_PHASED_DUELS MODULE_BREAKING_NEWS MODULE_BOSS_ANNOUNCER MODULE_ACCOUNT_ACHIEVEMENTS MODULE_AUTO_REVIVE MODULE_GAIN_HONOR_GUARD MODULE_ELUNA MODULE_TIME_IS_TIME MODULE_POCKET_PORTAL MODULE_RANDOM_ENCHANTS MODULE_SOLOCRAFT MODULE_PVP_TITLES MODULE_NPC_BEASTMASTER MODULE_NPC_ENCHANTER MODULE_INSTANCE_RESET MODULE_LEVEL_GRANT; do + eval "value=\$$module_var" + CURRENT_STATE="$CURRENT_STATE$module_var=$value|" +done + +# Check if state has changed +if [ -f "$MODULES_STATE_FILE" ]; then + PREVIOUS_STATE=$(cat "$MODULES_STATE_FILE") + if [ "$CURRENT_STATE" != "$PREVIOUS_STATE" ]; then + echo "πŸ”„ Module configuration has changed - rebuild required" + REBUILD_REQUIRED=1 + else + echo "βœ… No module changes detected" + fi +else + echo "πŸ“ First run - establishing module state baseline" + REBUILD_REQUIRED=1 +fi + +# Save current state +echo "$CURRENT_STATE" > "$MODULES_STATE_FILE" + +# Check if any C++ modules are enabled (all current modules require compilation) +ENABLED_MODULES="" +[ "$MODULE_PLAYERBOTS" = "1" ] && ENABLED_MODULES="$ENABLED_MODULES mod-playerbots" +[ "$MODULE_AOE_LOOT" = "1" ] && ENABLED_MODULES="$ENABLED_MODULES mod-aoe-loot" +[ "$MODULE_LEARN_SPELLS" = "1" ] && ENABLED_MODULES="$ENABLED_MODULES mod-learn-spells" +[ "$MODULE_FIREWORKS" = "1" ] && ENABLED_MODULES="$ENABLED_MODULES mod-fireworks-on-level" +[ "$MODULE_INDIVIDUAL_PROGRESSION" = "1" ] && ENABLED_MODULES="$ENABLED_MODULES mod-individual-progression" +[ "$MODULE_AHBOT" = "1" ] && ENABLED_MODULES="$ENABLED_MODULES mod-ahbot" +[ "$MODULE_AUTOBALANCE" = "1" ] && ENABLED_MODULES="$ENABLED_MODULES mod-autobalance" +[ "$MODULE_TRANSMOG" = "1" ] && ENABLED_MODULES="$ENABLED_MODULES mod-transmog" +[ "$MODULE_NPC_BUFFER" = "1" ] && ENABLED_MODULES="$ENABLED_MODULES mod-npc-buffer" +[ "$MODULE_DYNAMIC_XP" = "1" ] && ENABLED_MODULES="$ENABLED_MODULES mod-dynamic-xp" +[ "$MODULE_SOLO_LFG" = "1" ] && ENABLED_MODULES="$ENABLED_MODULES mod-solo-lfg" +[ "$MODULE_1V1_ARENA" = "1" ] && ENABLED_MODULES="$ENABLED_MODULES mod-1v1-arena" +[ "$MODULE_PHASED_DUELS" = "1" ] && ENABLED_MODULES="$ENABLED_MODULES mod-phased-duels" +[ "$MODULE_BREAKING_NEWS" = "1" ] && ENABLED_MODULES="$ENABLED_MODULES mod-breaking-news-override" +[ "$MODULE_BOSS_ANNOUNCER" = "1" ] && ENABLED_MODULES="$ENABLED_MODULES mod-boss-announcer" +[ "$MODULE_ACCOUNT_ACHIEVEMENTS" = "1" ] && ENABLED_MODULES="$ENABLED_MODULES mod-account-achievements" +[ "$MODULE_AUTO_REVIVE" = "1" ] && ENABLED_MODULES="$ENABLED_MODULES mod-auto-revive" +[ "$MODULE_GAIN_HONOR_GUARD" = "1" ] && ENABLED_MODULES="$ENABLED_MODULES mod-gain-honor-guard" +[ "$MODULE_ELUNA" = "1" ] && ENABLED_MODULES="$ENABLED_MODULES mod-eluna" +[ "$MODULE_ARAC" = "1" ] && ENABLED_MODULES="$ENABLED_MODULES mod-arac" +[ "$MODULE_TIME_IS_TIME" = "1" ] && ENABLED_MODULES="$ENABLED_MODULES mod-time-is-time" +[ "$MODULE_POCKET_PORTAL" = "1" ] && ENABLED_MODULES="$ENABLED_MODULES mod-pocket-portal" +[ "$MODULE_RANDOM_ENCHANTS" = "1" ] && ENABLED_MODULES="$ENABLED_MODULES mod-random-enchants" +[ "$MODULE_SOLOCRAFT" = "1" ] && ENABLED_MODULES="$ENABLED_MODULES mod-solocraft" +[ "$MODULE_PVP_TITLES" = "1" ] && ENABLED_MODULES="$ENABLED_MODULES mod-pvp-titles" +[ "$MODULE_NPC_BEASTMASTER" = "1" ] && ENABLED_MODULES="$ENABLED_MODULES mod-npc-beastmaster" +[ "$MODULE_NPC_ENCHANTER" = "1" ] && ENABLED_MODULES="$ENABLED_MODULES mod-npc-enchanter" +[ "$MODULE_INSTANCE_RESET" = "1" ] && ENABLED_MODULES="$ENABLED_MODULES mod-instance-reset" +[ "$MODULE_LEVEL_GRANT" = "1" ] && ENABLED_MODULES="$ENABLED_MODULES mod-quest-count-level" +[ "$MODULE_ASSISTANT" = "1" ] && ENABLED_MODULES="$ENABLED_MODULES mod-assistant" +[ "$MODULE_REAGENT_BANK" = "1" ] && ENABLED_MODULES="$ENABLED_MODULES mod-reagent-bank" +# Note: mod-black-market is Lua-based, doesn't need C++ compilation + +if [ -n "$ENABLED_MODULES" ]; then + ENABLED_COUNT=$(echo $ENABLED_MODULES | wc -w) + echo "πŸ”§ Detected $ENABLED_COUNT enabled C++ modules requiring compilation:" + for mod in $ENABLED_MODULES; do + echo " β€’ $mod" + done + + if [ "$REBUILD_REQUIRED" = "1" ]; then + echo "" + echo "🚨 REBUILD REQUIRED 🚨" + echo "Module configuration has changed. To integrate C++ modules into AzerothCore:" + echo "" + echo "1. Stop current services:" + echo " docker compose -f docker-compose-azerothcore-services.yml down" + echo "" + echo "2. Build with source-based compilation:" + echo " docker compose -f /tmp/acore-dev-test/docker-compose.yml build" + echo " docker compose -f /tmp/acore-dev-test/docker-compose.yml up -d" + echo "" + echo "3. Or use the automated rebuild script (if available):" + echo " ./scripts/rebuild-with-modules.sh" + echo "" + echo "πŸ“‹ NOTE: Source-based build will compile AzerothCore with all enabled modules" + echo "⏱️ Expected build time: 15-45 minutes depending on system performance" + echo "" + fi +else + echo "βœ… No C++ modules enabled - pre-built containers can be used" +fi + +echo 'Module management complete.' + +# Download rebuild script from GitHub for local access +echo 'πŸ“₯ Downloading rebuild-with-modules.sh from GitHub...' +apk add --no-cache curl +if curl -fsSL https://raw.githubusercontent.com/uprightbass360/acore-compose/main/scripts/rebuild-with-modules.sh -o /tmp/rebuild-with-modules.sh 2>/dev/null; then + echo 'βœ… Downloaded rebuild-with-modules.sh from GitHub' + chmod +x /tmp/rebuild-with-modules.sh + echo 'πŸ“ Script available at: /tmp/rebuild-with-modules.sh' +elif [ -f "/project/scripts/rebuild-with-modules.sh" ]; then + echo 'πŸ“ Using local rebuild-with-modules.sh for testing' + cp /project/scripts/rebuild-with-modules.sh /tmp/rebuild-with-modules.sh + chmod +x /tmp/rebuild-with-modules.sh + echo 'βœ… Copied to /tmp/rebuild-with-modules.sh' +else + echo '⚠️ Warning: rebuild-with-modules.sh not found in GitHub or locally' +fi + +echo 'Keeping container alive...' +tail -f /dev/null \ No newline at end of file diff --git a/scripts/mysql-startup.sh b/scripts/mysql-startup.sh new file mode 100644 index 0000000..c825d5f --- /dev/null +++ b/scripts/mysql-startup.sh @@ -0,0 +1,104 @@ +#!/bin/bash +set -e + +echo "πŸ”§ Starting MySQL with NFS-compatible setup and auto-restore..." +mkdir -p /var/lib/mysql-runtime +chown -R mysql:mysql /var/lib/mysql-runtime +chmod 755 /var/lib/mysql-runtime + +# Check if MySQL data directory is empty (fresh start) +if [ ! -d "/var/lib/mysql-runtime/mysql" ]; then + echo "πŸ†• Fresh MySQL installation detected..." + + # Check for available backups (prefer daily, fallback to hourly, then legacy) + if [ -d "/backups" ] && [ "$(ls -A /backups)" ]; then + # Try daily backups first + if [ -d "/backups/daily" ] && [ "$(ls -A /backups/daily)" ]; then + LATEST_BACKUP=$(ls -1t /backups/daily | head -n 1) + if [ -n "$LATEST_BACKUP" ] && [ -d "/backups/daily/$LATEST_BACKUP" ]; then + echo "πŸ“¦ Latest daily backup found: $LATEST_BACKUP" + echo "πŸ”„ Will restore after MySQL initializes..." + export RESTORE_BACKUP="/backups/daily/$LATEST_BACKUP" + fi + # Try hourly backups second + elif [ -d "/backups/hourly" ] && [ "$(ls -A /backups/hourly)" ]; then + LATEST_BACKUP=$(ls -1t /backups/hourly | head -n 1) + if [ -n "$LATEST_BACKUP" ] && [ -d "/backups/hourly/$LATEST_BACKUP" ]; then + echo "πŸ“¦ Latest hourly backup found: $LATEST_BACKUP" + echo "πŸ”„ Will restore after MySQL initializes..." + export RESTORE_BACKUP="/backups/hourly/$LATEST_BACKUP" + fi + # Try legacy backup structure last + else + LATEST_BACKUP=$(ls -1t /backups | head -n 1) + if [ -n "$LATEST_BACKUP" ] && [ -d "/backups/$LATEST_BACKUP" ]; then + echo "πŸ“¦ Latest legacy backup found: $LATEST_BACKUP" + echo "πŸ”„ Will restore after MySQL initializes..." + export RESTORE_BACKUP="/backups/$LATEST_BACKUP" + else + echo "πŸ†• No valid backups found, will initialize fresh..." + fi + fi + else + echo "πŸ†• No backup directory found, will initialize fresh..." + fi +else + echo "πŸ“ Existing MySQL data found, skipping restore..." +fi + +echo "πŸš€ Starting MySQL server with custom datadir..." + +# Start MySQL in background for potential restore +if [ -n "$RESTORE_BACKUP" ]; then + echo "⚑ Starting MySQL in background for restore operation..." + docker-entrypoint.sh mysqld \ + --datadir=/var/lib/mysql-runtime \ + --default-authentication-plugin=mysql_native_password \ + --character-set-server=${MYSQL_CHARACTER_SET} \ + --collation-server=${MYSQL_COLLATION} \ + --max_connections=${MYSQL_MAX_CONNECTIONS} \ + --innodb-buffer-pool-size=${MYSQL_INNODB_BUFFER_POOL_SIZE} \ + --innodb-log-file-size=${MYSQL_INNODB_LOG_FILE_SIZE} & + + MYSQL_PID=$! + + # Wait for MySQL to be ready + echo "⏳ Waiting for MySQL to become ready for restore..." + while ! mysqladmin ping -h localhost -u root --silent; do + sleep 2 + done + + echo "πŸ”„ MySQL ready, starting restore from $RESTORE_BACKUP..." + + # Install curl for downloading restore script + apt-get update && apt-get install -y curl + + # Download restore script from GitHub + curl -fsSL https://raw.githubusercontent.com/uprightbass360/acore-compose/main/scripts/restore.sh -o /tmp/restore.sh + chmod +x /tmp/restore.sh + + # Modify restore script to skip confirmation and use correct backup path + sed -i 's/sleep 10/echo "Auto-restore mode, skipping confirmation..."/' /tmp/restore.sh + sed -i 's/BACKUP_DIR=\${BACKUP_DIR:-\/backups}/BACKUP_DIR=\/backups/' /tmp/restore.sh + sed -i 's/MYSQL_PASSWORD=\${MYSQL_PASSWORD:-password}/MYSQL_PASSWORD=${MYSQL_ROOT_PASSWORD}/' /tmp/restore.sh + + # Extract timestamp from backup path and run restore + BACKUP_TIMESTAMP=$(basename "$RESTORE_BACKUP") + echo "πŸ—„οΈ Restoring databases from backup: $BACKUP_TIMESTAMP" + /tmp/restore.sh "$BACKUP_TIMESTAMP" + + echo "βœ… Database restore completed successfully!" + + # Keep MySQL running in foreground + wait $MYSQL_PID +else + # Normal startup without restore + exec docker-entrypoint.sh mysqld \ + --datadir=/var/lib/mysql-runtime \ + --default-authentication-plugin=mysql_native_password \ + --character-set-server=${MYSQL_CHARACTER_SET} \ + --collation-server=${MYSQL_COLLATION} \ + --max_connections=${MYSQL_MAX_CONNECTIONS} \ + --innodb-buffer-pool-size=${MYSQL_INNODB_BUFFER_POOL_SIZE} \ + --innodb-log-file-size=${MYSQL_INNODB_LOG_FILE_SIZE} +fi \ No newline at end of file