adding module functionality and final setup

This commit is contained in:
uprightbass360
2025-10-01 03:26:18 -04:00
parent f66e3b7c47
commit e7b3fcdce2
12 changed files with 1983 additions and 53 deletions

1
.gitignore vendored
View File

@@ -1,3 +1,4 @@
data/
backups/
local-data-tools/
storage/

270
MODULE_MANAGEMENT.md Normal file
View File

@@ -0,0 +1,270 @@
# AzerothCore Module Management System
This document describes the automated module management system for AzerothCore Docker deployments.
## Overview
The module management system provides:
- ✅ Automated Git-based module installation
- ✅ Automatic database script execution (SQL imports)
- ✅ Configuration file management (.conf.dist → .conf)
- ✅ Module state tracking and rebuild detection
- ✅ Comprehensive rebuild automation
- ✅ Pre-compilation configuration analysis
## Architecture
### Components
1. **Module Manager Container** (`ac-modules`)
- Handles module downloading, SQL execution, and state tracking
- Runs as one-time setup during stack initialization
- Monitors module configuration changes
2. **Rebuild Detection System**
- Tracks module enable/disable state changes
- Automatically detects when compilation is required
- Provides detailed rebuild instructions
3. **Automated Rebuild Script** (`rebuild-with-modules.sh`)
- Orchestrates full compilation workflow
- Integrates with source-based Docker builds
- Handles module synchronization
## Module Types
### Pre-built Compatible
**None currently available** - All 28 analyzed modules require C++ compilation.
### Compilation Required
All current modules require source-based compilation:
- mod-playerbots (CRITICAL: Requires custom AzerothCore branch)
- mod-aoe-loot
- mod-learn-spells
- mod-fireworks-on-level
- mod-individual-progression (Auto-configures accounts)
- All other modules...
## Configuration
### Environment Variables
Modules are controlled via environment variables in `docker-compose-azerothcore-services.env`:
```bash
# Enable/disable modules (1 = enabled, 0 = disabled)
MODULE_PLAYERBOTS=1
MODULE_AOE_LOOT=1
MODULE_LEARN_SPELLS=1
# ... etc
```
### Critical Module Requirements
#### mod-playerbots
- **INCOMPATIBLE** with standard AzerothCore
- Requires custom branch: `liyunfan1223/azerothcore-wotlk/tree/Playerbot`
- Will not function with standard compilation
#### mod-individual-progression
- Auto-configures new accounts for individual progression
- Requires account creation after server setup
## Database Integration
### Automatic SQL Execution
The system automatically executes SQL scripts for enabled modules:
```bash
# SQL execution locations searched:
/modules/mod-name/data/sql/world/*.sql → acore_world database
/modules/mod-name/data/sql/auth/*.sql → acore_auth database
/modules/mod-name/data/sql/characters/*.sql → acore_characters database
/modules/mod-name/data/sql/*.sql → acore_world database (fallback)
/modules/mod-name/sql/*.sql → acore_world database (alternative)
```
### Error Handling
- ✅ Uses proper MySQL client with SSL verification disabled
- ✅ Implements exit code checking (not stderr redirection)
- ✅ Provides detailed success/failure feedback
- ✅ Continues processing if optional scripts fail
## Rebuild System
### Detection Logic
1. **Module State Tracking**
- Creates hash of all module enable/disable states
- Stores in `/modules/.modules_state`
- Compares current vs previous state on each run
2. **Change Detection**
```bash
# First run
📝 First run - establishing module state baseline
# No changes
✅ No module changes detected
# Changes detected
🔄 Module configuration has changed - rebuild required
```
### Rebuild Requirements
When modules are enabled, the system provides:
```bash
🚨 REBUILD REQUIRED 🚨
Module configuration has changed. To integrate C++ modules into AzerothCore:
1. Stop current services:
docker compose -f docker-compose-azerothcore-services.yml down
2. Build with source-based compilation:
docker compose -f /tmp/acore-dev-test/docker-compose.yml build
docker compose -f /tmp/acore-dev-test/docker-compose.yml up -d
3. Or use the automated rebuild script (if available):
./rebuild-with-modules.sh
```
### Automated Rebuild Script
The `rebuild-with-modules.sh` script provides:
1. **Pre-flight Checks**
- Verifies source repository availability
- Counts enabled modules
- Confirms rebuild necessity
2. **Build Process**
- Stops current services
- Syncs modules to source build
- Executes `docker compose build --no-cache`
- Starts services with compiled modules
3. **Error Handling**
- Build failure detection
- Service startup verification
- Detailed status reporting
## Usage Examples
### Enable New Module
1. Edit `docker-compose-azerothcore-services.env`:
```bash
MODULE_TRANSMOG=1
```
2. Restart module manager:
```bash
docker compose -f docker-compose-azerothcore-services.yml up ac-modules
```
3. Follow rebuild instructions or run:
```bash
./rebuild-with-modules.sh
```
### Disable Module
1. Edit environment file:
```bash
MODULE_TRANSMOG=0
```
2. Restart and rebuild (module code will be removed from compilation)
### Bulk Module Management
Enable multiple modules simultaneously:
```bash
# Edit .env file with multiple changes
MODULE_AUTOBALANCE=1
MODULE_TRANSMOG=1
MODULE_SOLO_LFG=1
# Single rebuild handles all changes
./rebuild-with-modules.sh
```
## Troubleshooting
### Common Issues
1. **SQL Execution Failures**
- Check MySQL container health
- Verify database credentials
- Review specific SQL script syntax
2. **Build Failures**
- Ensure adequate disk space (>10GB recommended)
- Check module compatibility
- Review Docker build logs
3. **Module Not Loading**
- Verify module appears in compilation output
- Check worldserver logs for load errors
- Confirm configuration files copied correctly
### Performance Considerations
- **Build Time**: 15-45 minutes depending on system performance
- **Storage**: Source builds require ~5-10GB additional space
- **Memory**: Compilation may require 4GB+ RAM
- **CPU**: Multi-core systems significantly faster
## Technical Implementation
### Module Installation Flow
```
1. Environment Variable Check → Module Enabled?
2. Git Clone/Pull → Download Latest Module Source
3. SQL Script Discovery → Find Database Scripts
4. Database Connection → Execute Scripts with Error Handling
5. Configuration Files → Copy .conf.dist to .conf
6. State Tracking → Update Module State Hash
7. Rebuild Detection → Compare Previous vs Current State
8. User Notification → Provide Rebuild Instructions
```
### Database Script Execution
```sql
-- Example execution pattern:
mysql --skip-ssl-verify -h ac-database -P 3306 -u root -p"password" acore_world < module.sql
-- Success detection via exit codes:
if [ $? -eq 0 ]; then
echo "✅ Successfully executed $(basename $sql_file)"
else
echo "❌ Failed to execute $sql_file"
fi
```
## Future Enhancements
- [ ] Support for pure configuration modules (no compilation)
- [ ] Module dependency resolution
- [ ] Incremental compilation for faster rebuilds
- [ ] Integration with CI/CD pipelines
- [ ] Module version management and rollback
- [ ] Health checks for module functionality
## Support
For issues with specific modules, refer to their individual GitHub repositories.
For system-level issues, check Docker Compose logs and module manager output.

View File

@@ -3,6 +3,14 @@
# ==============================================
# Environment variables for auth server, world server, client data, modules, and optional services
# ==============================================
# DEPLOYMENT CONFIGURATION (REQUIRED)
# ==============================================
# Storage root path - local: ./storage, production: /nfs/containers or custom mount
STORAGE_ROOT=./storage
# Storage configuration (must match database layer)
STORAGE_PATH=${STORAGE_ROOT}/azerothcore
# ==============================================
# DATABASE CONNECTION (REQUIRED)
# ==============================================
@@ -62,14 +70,6 @@ AUTH_PORT=3724
WORLD_PORT=8085
SOAP_PORT=7878
# ==============================================
# DEPLOYMENT CONFIGURATION (REQUIRED)
# ==============================================
# Storage root path - local: ./storage, production: /nfs/containers or custom mount
STORAGE_ROOT=./storage
# Storage configuration (must match database layer)
STORAGE_PATH=${STORAGE_ROOT}/azerothcore
# ==============================================
# CONTAINER NAMES (REQUIRED)
# ==============================================
@@ -90,19 +90,52 @@ NETWORK_NAME=azerothcore
# ==============================================
# CUSTOM MODULE SETTINGS
# ==============================================
# GIT
GIT_EMAIL=uprightbass360@gmail.com
GIT_USERNAME=uprightbass360
GIT_PAT=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
# Playerbot settings
PLAYERBOT_ENABLED=1
PLAYERBOT_MAX_BOTS=40
# Module configuration
MODULE_PLAYERBOTS=1
MODULE_AOE_LOOT=0
MODULE_LEARN_SPELLS=0
MODULE_FIREWORKS=0
MODULE_INDIVIDUAL_PROGRESSION=0
MODULE_AOE_LOOT=1
MODULE_LEARN_SPELLS=1
MODULE_FIREWORKS=1
MODULE_INDIVIDUAL_PROGRESSION=1
# Deployment mode
DEPLOYMENT_MODE=portainer
# Quality of Life Modules
MODULE_AHBOT=1
MODULE_AUTOBALANCE=1
MODULE_TRANSMOG=1
MODULE_NPC_BUFFER=1
# Gameplay Enhancement Modules
MODULE_DYNAMIC_XP=1
MODULE_SOLO_LFG=1
MODULE_1V1_ARENA=1
MODULE_PHASED_DUELS=1
# Server Management Modules
MODULE_BREAKING_NEWS=1
MODULE_BOSS_ANNOUNCER=1
MODULE_ACCOUNT_ACHIEVEMENTS=1
# Additional Modules Found in Config
MODULE_AUTO_REVIVE=1
MODULE_GAIN_HONOR_GUARD=1
MODULE_ELUNA=1
MODULE_TIME_IS_TIME=1
MODULE_POCKET_PORTAL=1
MODULE_RANDOM_ENCHANTS=1
MODULE_SOLOCRAFT=1
MODULE_PVP_TITLES=1
MODULE_NPC_BEASTMASTER=1
MODULE_NPC_ENCHANTER=1
MODULE_INSTANCE_RESET=1
MODULE_LEVEL_GRANT=1
# ==============================================
# ADDITIONAL CONTAINER NAMES (OPTIONAL)

View File

@@ -286,54 +286,790 @@ services:
user: "0:0" # Run as root to handle NFS permissions
volumes:
- ${STORAGE_PATH}/modules:/modules
- ${STORAGE_PATH}/config:/azerothcore/env/dist/etc
environment:
- GIT_EMAIL=${GIT_EMAIL}
- GIT_PAT=${GIT_PAT}
- GIT_USERNAME=${GIT_USERNAME}
- MODULE_PLAYERBOTS=${MODULE_PLAYERBOTS}
- MODULE_AOE_LOOT=${MODULE_AOE_LOOT}
- MODULE_LEARN_SPELLS=${MODULE_LEARN_SPELLS}
- MODULE_FIREWORKS=${MODULE_FIREWORKS}
- MODULE_INDIVIDUAL_PROGRESSION=${MODULE_INDIVIDUAL_PROGRESSION}
- DEPLOYMENT_MODE=${DEPLOYMENT_MODE}
# Quality of Life Modules
- MODULE_AHBOT=${MODULE_AHBOT}
- MODULE_AUTOBALANCE=${MODULE_AUTOBALANCE}
- MODULE_TRANSMOG=${MODULE_TRANSMOG}
- MODULE_NPC_BUFFER=${MODULE_NPC_BUFFER}
# Gameplay Enhancement Modules
- MODULE_DYNAMIC_XP=${MODULE_DYNAMIC_XP}
- MODULE_SOLO_LFG=${MODULE_SOLO_LFG}
- MODULE_1V1_ARENA=${MODULE_1V1_ARENA}
- MODULE_PHASED_DUELS=${MODULE_PHASED_DUELS}
# Server Management Modules
- MODULE_BREAKING_NEWS=${MODULE_BREAKING_NEWS}
- MODULE_BOSS_ANNOUNCER=${MODULE_BOSS_ANNOUNCER}
- MODULE_ACCOUNT_ACHIEVEMENTS=${MODULE_ACCOUNT_ACHIEVEMENTS}
# Additional Modules Found in Config
- MODULE_AUTO_REVIVE=${MODULE_AUTO_REVIVE}
- MODULE_GAIN_HONOR_GUARD=${MODULE_GAIN_HONOR_GUARD}
- MODULE_ELUNA=${MODULE_ELUNA}
- MODULE_TIME_IS_TIME=${MODULE_TIME_IS_TIME}
- MODULE_POCKET_PORTAL=${MODULE_POCKET_PORTAL}
- MODULE_RANDOM_ENCHANTS=${MODULE_RANDOM_ENCHANTS}
- MODULE_SOLOCRAFT=${MODULE_SOLOCRAFT}
- MODULE_PVP_TITLES=${MODULE_PVP_TITLES}
- MODULE_NPC_BEASTMASTER=${MODULE_NPC_BEASTMASTER}
- MODULE_NPC_ENCHANTER=${MODULE_NPC_ENCHANTER}
- MODULE_INSTANCE_RESET=${MODULE_INSTANCE_RESET}
- MODULE_LEVEL_GRANT=${MODULE_LEVEL_GRANT}
# Database connection for SQL execution
- CONTAINER_MYSQL=${CONTAINER_MYSQL}
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
- DB_AUTH_NAME=${DB_AUTH_NAME}
- DB_WORLD_NAME=${DB_WORLD_NAME}
- DB_CHARACTERS_NAME=${DB_CHARACTERS_NAME}
entrypoint: ["/bin/sh", "-c"]
command:
- |
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
if [ "$DEPLOYMENT_MODE" = "portainer" ]; then
echo 'Simple module setup for Portainer deployment...'
mkdir -p mod-playerbots
echo '✅ Playerbot module directory created'
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_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
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'
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'
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'
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'
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'
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...'
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'
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...'
git clone https://github.com/azerothcore/mod-eluna.git mod-eluna
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...'
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
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_LuaEngine.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
# 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.'
echo 'Executing module SQL scripts...'
# 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 mysql --skip-ssl-verify -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 mysql --skip-ssl-verify -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 mysql --skip-ssl-verify -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
}
# Install MySQL client if not available
which mysql >/dev/null 2>&1 || {
echo "Installing MySQL client..."
apk add --no-cache mysql-client >/dev/null 2>&1 || echo "Warning: Could not install MySQL 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_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
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 'Advanced module setup for local development...'
# Install Playerbots if enabled
if [ "$MODULE_PLAYERBOTS" = "1" ] && [ ! -d "mod-playerbots" ]; then
echo 'Installing mod-playerbots...'
git clone https://github.com/liyunfan1223/mod-playerbots.git mod-playerbots
fi
echo "📝 First run - establishing module state baseline"
REBUILD_REQUIRED=1
fi
# Install AOE Loot if enabled
if [ "$MODULE_AOE_LOOT" = "1" ] && [ ! -d "mod-aoe-loot" ]; then
echo 'Installing mod-aoe-loot...'
git clone https://github.com/azerothcore/mod-aoe-loot.git mod-aoe-loot
fi
# Save current state
echo "$CURRENT_STATE" > "$MODULES_STATE_FILE"
# Install Learn Spells if enabled
if [ "$MODULE_LEARN_SPELLS" = "1" ] && [ ! -d "mod-learn-spells" ]; then
echo 'Installing mod-learn-spells...'
git clone https://github.com/azerothcore/mod-learn-spells.git mod-learn-spells
fi
# 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_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"
# Install Fireworks on Level if enabled
if [ "$MODULE_FIREWORKS" = "1" ] && [ ! -d "mod-fireworks-on-level" ]; then
echo 'Installing mod-fireworks-on-level...'
git clone https://github.com/azerothcore/mod-fireworks-on-level.git mod-fireworks-on-level
fi
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
# Install Individual Progression if enabled
if [ "$MODULE_INDIVIDUAL_PROGRESSION" = "1" ] && [ ! -d "mod-individual-progression" ]; then
echo 'Installing mod-individual-progression...'
git clone https://github.com/azerothcore/mod-individual-progression.git mod-individual-progression
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 " ./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. Keeping container alive...'

View File

@@ -21,7 +21,7 @@ MYSQL_PORT=3306
# Storage root path - local: ./storage, production: /nfs/containers or custom mount
STORAGE_ROOT=./storage
# Storage for tools (unified with core stack)
STORAGE_PATH_TOOLS=${STORAGE_ROOT}/azerothcore
STORAGE_PATH=${STORAGE_ROOT}/azerothcore
# ==============================================
# NETWORK CONFIGURATION (REQUIRED)

View File

@@ -82,7 +82,7 @@ services:
ports:
- "${INFLUXDB_EXTERNAL_PORT:-8087}:8086"
volumes:
- ${STORAGE_PATH_TOOLS:-./storage/azerothcore}/azerothcore/influxdb:/var/lib/influxdb2
- ${STORAGE_PATH:-./storage/azerothcore}/azerothcore/influxdb:/var/lib/influxdb2
restart: unless-stopped
networks:
- azerothcore
@@ -110,7 +110,7 @@ services:
ports:
- "${GF_EXTERNAL_PORT:-3001}:3000"
volumes:
- ${STORAGE_PATH_TOOLS:-./storage/azerothcore}/azerothcore/grafana:/var/lib/grafana
- ${STORAGE_PATH:-./storage/azerothcore}/azerothcore/grafana:/var/lib/grafana
entrypoint: ["/bin/bash", "-c"]
command:
- |

View File

@@ -0,0 +1,75 @@
# ==============================================
# TEST WORLDSERVER ENVIRONMENT CONFIGURATION
# ==============================================
# This configuration is for testing worldserver with
# local game files vs. external volume mount
# ==============================================
# IMAGE CONFIGURATION (REQUIRED)
# ==============================================
AC_WORLDSERVER_IMAGE=acore/ac-wotlk-worldserver:14.0.0-dev
IMAGE_PULL_POLICY=if_not_present
# ==============================================
# PLAYERBOT CONFIGURATION (OPTIONAL)
# ==============================================
# Playerbot settings for AI-controlled bots
PLAYERBOT_ENABLED=1
PLAYERBOT_MAX_BOTS=40
# ==============================================
# HEALTH CHECK CONFIGURATION
# ==============================================
# World server health check - extended for download time
WORLD_HEALTHCHECK_INTERVAL=30s
WORLD_HEALTHCHECK_TIMEOUT=10s
WORLD_HEALTHCHECK_RETRIES=3
WORLD_HEALTHCHECK_START_PERIOD=1800s # 30 minutes for download/extraction
# ==============================================
# NETWORK CONFIGURATION (REQUIRED)
# ==============================================
# Test external ports (different from main deployment)
WORLD_EXTERNAL_PORT_TEST=8216 # Different port to avoid conflict
SOAP_EXTERNAL_PORT_TEST=7779 # Different port to avoid conflict
# Internal ports (container side)
WORLD_PORT=8085
SOAP_PORT=7878
# ==============================================
# DEPLOYMENT CONFIGURATION (REQUIRED)
# ==============================================
# Storage root path - local: ./storage, production: /nfs/containers or custom mount
STORAGE_ROOT=./storage
# Storage configuration (same as other layers for config/logs)
STORAGE_PATH=${STORAGE_ROOT}/azerothcore
# ==============================================
# CONTAINER NAMES (REQUIRED)
# ==============================================
# Test container name to avoid conflicts
CONTAINER_WORLDSERVER_TEST=ac-worldserver-test
# Database container name (for external linking)
CONTAINER_MYSQL=ac-mysql
# ==============================================
# NETWORK SETTINGS (REQUIRED)
# ==============================================
# Network must already exist from database layer
NETWORK_NAME=azerothcore
# ==============================================
# DATABASE CONFIGURATION (REQUIRED)
# ==============================================
# Database credentials and connection info
MYSQL_HOST=ac-mysql
MYSQL_PORT=3306
MYSQL_USER=root
MYSQL_ROOT_PASSWORD=azerothcore123
# Database names
DB_AUTH_NAME=acore_auth
DB_WORLD_NAME=acore_world
DB_CHARACTERS_NAME=acore_characters

View File

@@ -0,0 +1,192 @@
# ==============================================
# TEST WORLDSERVER WITH LOCAL GAME FILES
# ==============================================
# This is a test configuration to compare performance
# of worldserver with game files stored locally within
# the container vs. external volume mount
services:
# Test world server with local game files (no external data volume)
ac-worldserver-test:
image: ${AC_WORLDSERVER_IMAGE}
pull_policy: ${IMAGE_PULL_POLICY}
container_name: ${CONTAINER_WORLDSERVER_TEST}
user: "0:0" # Run as root to handle permissions
stdin_open: true
tty: true
# depends_on:
# - ac-authserver # Assumes authserver is already running from main deployment
environment:
AC_LOGIN_DATABASE_INFO: "${CONTAINER_MYSQL};${MYSQL_PORT};${MYSQL_USER};${MYSQL_ROOT_PASSWORD};${DB_AUTH_NAME}"
AC_WORLD_DATABASE_INFO: "${CONTAINER_MYSQL};${MYSQL_PORT};${MYSQL_USER};${MYSQL_ROOT_PASSWORD};${DB_WORLD_NAME}"
AC_CHARACTER_DATABASE_INFO: "${CONTAINER_MYSQL};${MYSQL_PORT};${MYSQL_USER};${MYSQL_ROOT_PASSWORD};${DB_CHARACTERS_NAME}"
AC_UPDATES_ENABLE_DATABASES: "0"
AC_BIND_IP: "0.0.0.0"
AC_DATA_DIR: "/azerothcore/data"
AC_SOAP_PORT: "7878"
AC_PROCESS_PRIORITY: "0"
PLAYERBOT_ENABLED: "${PLAYERBOT_ENABLED}"
PLAYERBOT_MAX_BOTS: "${PLAYERBOT_MAX_BOTS}"
# Logger configuration - Use config file defaults with proper log level
AC_LOG_LEVEL: "2"
ports:
- "${WORLD_EXTERNAL_PORT_TEST}:${WORLD_PORT}"
- "${SOAP_EXTERNAL_PORT_TEST}:${SOAP_PORT}"
volumes:
# Only mount config and logs, NOT the data directory (game files will be internal)
- ${STORAGE_PATH}/config:/azerothcore/env/dist/etc
- ${STORAGE_PATH}/logs-test:/azerothcore/logs
- ${STORAGE_PATH}/modules:/azerothcore/modules
# Mount cache directory to persist downloaded files across container restarts
- ${STORAGE_PATH}/cache-test:/cache
restart: unless-stopped
networks:
- azerothcore
cap_add:
- SYS_NICE
entrypoint: ["/bin/bash", "-c"]
command:
- |
echo "🧪 Starting TEST worldserver with local game files..."
# Install required packages for downloading
echo "📦 Installing download tools..."
apt-get update > /dev/null 2>&1
apt-get install -y curl wget unzip ca-certificates > /dev/null 2>&1
# Create cache and data directories
mkdir -p /cache /azerothcore/data
echo "🧪 Starting TEST worldserver with cached local game files..."
echo "📂 Cache directory: /cache (persistent across restarts)"
echo "🎯 Game files will be copied to local container storage for performance testing"
cd /tmp
# 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)
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'
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 for $$LATEST_TAG"
echo "📊 Cached file size: $$(ls -lh "$$CACHE_FILE" | awk '{print $$5}')"
echo "⚡ Using cached download (no internet download needed)"
cp "$$CACHE_FILE" data.zip
else
echo "🔄 Cached version ($$CACHED_VERSION) differs from latest ($$LATEST_TAG)"
echo "📥 Downloading new version..."
wget --progress=dot:giga -O "$$CACHE_FILE.tmp" "$$LATEST_URL"
if [ $$? -eq 0 ]; then
mv "$$CACHE_FILE.tmp" "$$CACHE_FILE"
echo "$$LATEST_TAG" > "$$VERSION_FILE"
echo "✅ Download completed and cached"
cp "$$CACHE_FILE" data.zip
else
echo "❌ Download failed!"
exit 1
fi
fi
else
echo "💾 No cache found, downloading and caching..."
echo "⏱️ Download started at: $(date)"
wget --progress=dot:giga -O "$$CACHE_FILE.tmp" "$$LATEST_URL"
if [ $$? -eq 0 ]; then
mv "$$CACHE_FILE.tmp" "$$CACHE_FILE"
echo "$$LATEST_TAG" > "$$VERSION_FILE"
echo "✅ Download completed and cached at: $(date)"
echo "📊 File size: $$(ls -lh "$$CACHE_FILE" | awk '{print $$5}')"
cp "$$CACHE_FILE" data.zip
else
echo "❌ Download failed!"
exit 1
fi
fi
# Extract game files to local container storage for performance testing
echo "📂 Extracting client data to local container storage..."
echo "🎯 This tests performance with files stored locally vs. external volume"
echo "⏱️ Extraction started at: $(date)"
# Clear any existing data
rm -rf /azerothcore/data/maps /azerothcore/data/vmaps /azerothcore/data/mmaps /azerothcore/data/dbc
# Extract with progress monitoring
unzip -o -q data.zip -d /azerothcore/data/ &
UNZIP_PID=$!
# Simple progress indicator
while kill -0 "$$UNZIP_PID" 2>/dev/null; do
echo "⏳ Extracting... ($(date '+%H:%M:%S'))"
sleep 30
done
wait $$UNZIP_PID
UNZIP_EXIT_CODE=$$?
if [ $$UNZIP_EXIT_CODE -ne 0 ]; then
echo "❌ Extraction failed!"
exit 1
fi
# Clean up zip file
rm -f data.zip
echo "✅ Extraction completed at: $(date)"
echo "💾 Game files are now stored locally in container for performance testing"
# Verify required directories exist and have content
echo '📁 Verifying extracted directories:'
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 verification failed!"
exit 1
fi
echo "🎉 Local game data setup complete!"
echo "🚀 Starting worldserver..."
echo "⏱️ Worldserver startup time: $(date)"
# Start the worldserver
exec /azerothcore/env/dist/bin/worldserver
healthcheck:
test: ["CMD", "sh", "-c", "ps aux | grep '[w]orldserver' | grep -v grep || exit 1"]
interval: ${WORLD_HEALTHCHECK_INTERVAL}
timeout: ${WORLD_HEALTHCHECK_TIMEOUT}
retries: ${WORLD_HEALTHCHECK_RETRIES}
start_period: 1800s # 30 minutes to allow for download and extraction
networks:
azerothcore:
external: true

110
readme.md
View File

@@ -24,6 +24,7 @@ This project is a Docker/Podman implementation based on:
## Table of Contents
- [Overview](#overview)
- [Features](#features)
- [Available Modules](#available-modules)
- [Requirements](#requirements)
- [Project Structure](#project-structure)
- [Container Architecture](#container-architecture)
@@ -76,6 +77,103 @@ This project provides a production-ready AzerothCore deployment using Docker/Pod
-**Network Isolation**: Custom bridge network for container communication
-**Persistent Storage**: Named volumes for data persistence
## Available Modules
This deployment includes an automated module management system that supports 28 AzerothCore modules. All modules are automatically downloaded from GitHub when enabled and include proper configuration files.
### Quality of Life Modules
| Module | Description | Repository | README | Post-Install Notes |
|--------|-------------|------------|--------|-------------------|
| **AutoBalance** | Dynamic difficulty scaling for dungeons/raids | [mod-autobalance](https://github.com/azerothcore/mod-autobalance) | [📖](https://github.com/azerothcore/mod-autobalance/blob/master/README.md) | Requires AutoBalance.conf configuration |
| **AHBot** | Auction House bot for populated auctions | [mod-ahbot](https://github.com/azerothcore/mod-ahbot) | [📖](https://github.com/azerothcore/mod-ahbot/blob/master/README.md) | Requires mod_ahbot.conf configuration |
| **Transmog** | Transmogrification system | [mod-transmog](https://github.com/azerothcore/mod-transmog) | [📖](https://github.com/azerothcore/mod-transmog/blob/master/README.md) | Requires transmog.conf configuration |
| **NPC Buffer** | Buff NPC services | [mod-npc-buffer](https://github.com/azerothcore/mod-npc-buffer) | [📖](https://github.com/azerothcore/mod-npc-buffer/blob/master/README.md) | Requires npc_buffer.conf configuration |
| **AoE Loot** | Area of effect looting feature | [mod-aoe-loot](https://github.com/azerothcore/mod-aoe-loot) | [📖](https://github.com/azerothcore/mod-aoe-loot/blob/master/.github/README.md) | No additional configuration required |
| **Learn Spells** | Automatic spell learning | [mod-learn-spells](https://github.com/azerothcore/mod-learn-spells) | [📖](https://github.com/azerothcore/mod-learn-spells/blob/master/README.md) | Requires mod_learnspells.conf configuration |
| **Auto Revive** | Auto-revive functionality for GMs | [mod-auto-revive](https://github.com/azerothcore/mod-auto-revive) | [📖](https://github.com/azerothcore/mod-auto-revive/blob/master/README.md) | Requires AutoRevive.conf configuration |
| **NPC Enchanter** | NPC-based gear enchantment services | [mod-npc-enchanter](https://github.com/azerothcore/mod-npc-enchanter) | [📖](https://github.com/azerothcore/mod-npc-enchanter/blob/master/README.md) | Requires npc_enchanter.conf configuration |
| **Instance Reset** | NPC-based instance reset functionality | [mod-instance-reset](https://github.com/azerothcore/mod-instance-reset) | [📖](https://github.com/azerothcore/mod-instance-reset/blob/master/README.md) | Requires instance-reset.conf configuration |
### Gameplay Enhancement Modules
| Module | Description | Repository | README | Post-Install Notes |
|--------|-------------|------------|--------|-------------------|
| **Individual Progression** | Custom character progression system | [mod-individual-progression](https://github.com/ZhengPeiRu21/mod-individual-progression) | [📖](https://github.com/ZhengPeiRu21/mod-individual-progression/blob/master/README.md) | Complex SQL imports required |
| **Dynamic XP** | Configurable experience rates | [mod-dynamic-xp](https://github.com/azerothcore/mod-dynamic-xp) | [📖](https://github.com/azerothcore/mod-dynamic-xp/blob/master/README.md) | Requires Individual-XP.conf configuration |
| **Solo LFG** | Solo dungeon finder system | [mod-solo-lfg](https://github.com/azerothcore/mod-solo-lfg) | [📖](https://github.com/azerothcore/mod-solo-lfg/blob/master/README.md) | Requires SoloLfg.conf configuration |
| **1v1 Arena** | Arena combat system | [mod-1v1-arena](https://github.com/azerothcore/mod-1v1-arena) | [📖](https://github.com/azerothcore/mod-1v1-arena/blob/master/README.md) | Database tables auto-created |
| **Phased Duels** | Isolated dueling system | [mod-phased-duels](https://github.com/azerothcore/mod-phased-duels) | [📖](https://github.com/azerothcore/mod-phased-duels/blob/master/README.md) | No additional configuration required |
| **Solocraft** | Solo dungeon scaling | [mod-solocraft](https://github.com/azerothcore/mod-solocraft) | [📖](https://github.com/azerothcore/mod-solocraft/blob/master/.github/README.md) | Requires Solocraft.conf configuration |
| **Random Enchants** | Random item enchantments | [mod-random-enchants](https://github.com/azerothcore/mod-random-enchants) | [📖](https://github.com/azerothcore/mod-random-enchants/blob/master/README.md) | Requires RandomEnchants.conf configuration |
| **Level Grant** | Quest-based level granting | [mod-quest-count-level](https://github.com/michaeldelago/mod-quest-count-level) | [📖](https://github.com/michaeldelago/mod-quest-count-level/blob/main/README.md) | Requires levelGrant.conf configuration |
### Server Management Modules
| Module | Description | Repository | README | Post-Install Notes |
|--------|-------------|------------|--------|-------------------|
| **Breaking News Override** | Server announcement system | [mod-breaking-news-override](https://github.com/azerothcore/mod-breaking-news-override) | [📖](https://github.com/azerothcore/mod-breaking-news-override/blob/master/README.md) | No additional configuration required |
| **Boss Announcer** | Raid boss kill notifications | [mod-boss-announcer](https://github.com/azerothcore/mod-boss-announcer) | [📖](https://github.com/azerothcore/mod-boss-announcer/blob/master/README.md) | No additional configuration required |
| **Account Achievements** | Cross-character achievements | [mod-account-achievements](https://github.com/azerothcore/mod-account-achievements) | [📖](https://github.com/azerothcore/mod-account-achievements/blob/master/README.md) | Database tables auto-created |
| **Gain Honor Guard** | Honor system for killing guards | [mod-gain-honor-guard](https://github.com/azerothcore/mod-gain-honor-guard) | [📖](https://github.com/azerothcore/mod-gain-honor-guard/blob/master/.github/README.md) | Requires GainHonorGuard.conf configuration |
| **PvP Titles** | Honor-based PvP title system | [mod-pvp-titles](https://github.com/azerothcore/mod-pvp-titles) | [📖](https://github.com/azerothcore/mod-pvp-titles/blob/master/README.md) | Requires mod_pvptitles.conf configuration |
| **Pocket Portal** | Teleportation portal system | [mod-pocket-portal](https://github.com/azerothcore/mod-pocket-portal) | [📖](https://github.com/azerothcore/mod-pocket-portal/blob/master/README.md) | Requires pocketportal.conf configuration |
### Core System Modules
| Module | Description | Repository | README | Post-Install Notes |
|--------|-------------|------------|--------|-------------------|
| **Playerbots** | AI-controlled bot system | [mod-playerbots](https://github.com/liyunfan1223/mod-playerbots) | [📖](https://github.com/liyunfan1223/mod-playerbots/blob/master/README.md) | Enabled by default, extensive configuration |
| **Fireworks** | Fireworks on level up | [mod-fireworks-on-level](https://github.com/azerothcore/mod-fireworks-on-level) | [📖](https://github.com/azerothcore/mod-fireworks-on-level/blob/master/README.md) | No additional configuration required |
| **Eluna** | Lua scripting engine | [mod-eluna](https://github.com/azerothcore/mod-eluna) | [📖](https://github.com/azerothcore/mod-eluna/blob/master/README.md) | Requires mod_LuaEngine.conf configuration |
| **Time Is Time** | Realistic day/night cycle | [mod-TimeIsTime](https://github.com/dunjeon/mod-TimeIsTime) | [📖](https://github.com/dunjeon/mod-TimeIsTime/blob/main/README.md) | Requires mod-time_is_time.conf configuration |
| **NPC Beastmaster** | Cross-class pet system | [mod-npc-beastmaster](https://github.com/azerothcore/mod-npc-beastmaster) | [📖](https://github.com/azerothcore/mod-npc-beastmaster/blob/master/README.md) | Requires npc_beastmaster.conf configuration |
### Module Configuration
Enable modules by setting their environment variables to `1` in `docker-compose-azerothcore-services.env`:
```bash
# Example: Enable AutoBalance and Transmog
MODULE_AUTOBALANCE=1
MODULE_TRANSMOG=1
```
After enabling/disabling modules:
1. Restart the module container: `docker-compose up -d ac-modules`
2. **Enabled modules** will be automatically downloaded to `storage/azerothcore/modules/`
3. **Disabled modules** will be automatically removed from the modules directory
4. **Configuration files** (`.conf.dist`) are automatically managed:
- **Enabled modules**: Config files copied to `storage/azerothcore/config/`
- **Disabled modules**: Config files removed from config directory
5. **Important**: Modules require server recompilation to be active
6. Some modules require database imports (check individual module README files)
### Module Management Behavior
The module management system provides complete automation:
- **Enable Module** (`MODULE_NAME=1`):
- Downloads module source code if not present
- Copies `.conf.dist` files to config directory
- **Disable Module** (`MODULE_NAME=0`):
- Removes module directory completely
- Removes associated configuration files
- **Module Persistence**: Only enabled modules and their configs remain
- **Clean Slate**: Disabling and re-enabling ensures fresh download and config
- **Zero Manual Setup**: No need to manually copy configuration files
### Post-Installation Requirements
⚠️ **Critical**: Most modules require additional steps after download:
1. **Server Recompilation**: Modules need to be compiled into the server
2. **Configuration Files**: Copy `.conf` files to config directory
3. **Database Imports**: Some modules include SQL files for database schema
4. **Module-Specific Setup**: Check each module's README for specific requirements
See the [AzerothCore Module Documentation](https://www.azerothcore.org/wiki/installing-a-module) for complete installation procedures.
## Requirements
### System Requirements
@@ -241,11 +339,11 @@ Configuration is managed through separate `.env` files for each layer:
- **Local development**: `./storage`
- **Production NFS**: `/nfs/containers`
- **Custom mount**: `/mnt/azerothcore-data`
- All layers derive their storage paths from `STORAGE_ROOT`:
- Database: `${STORAGE_ROOT}/azerothcore`
- Services: `${STORAGE_ROOT}/azerothcore`
- Tools: `${STORAGE_ROOT}/azerothcore`
- Optional: `${STORAGE_ROOT}/azerothcore`
- All layers use the same `STORAGE_PATH` variable derived from `STORAGE_ROOT`:
- Database: `STORAGE_PATH=${STORAGE_ROOT}/azerothcore`
- Services: `STORAGE_PATH=${STORAGE_ROOT}/azerothcore`
- Tools: `STORAGE_PATH=${STORAGE_ROOT}/azerothcore`
- Optional: `STORAGE_PATH=${STORAGE_ROOT}/azerothcore`
#### Database Layer (`docker-compose-azerothcore-database.env`)
- `MYSQL_ROOT_PASSWORD`: Database root password (default: azerothcore123)
@@ -270,7 +368,7 @@ Configuration is managed through separate `.env` files for each layer:
- `GF_EXTERNAL_PORT`: Grafana monitoring port (3001)
- `INFLUXDB_EXTERNAL_PORT`: InfluxDB metrics port (8087)
- `STORAGE_ROOT`: Root storage path (default: ./storage)
- `STORAGE_PATH_TOOLS`: Derived storage path (${STORAGE_ROOT}/azerothcore)
- `STORAGE_PATH`: Derived storage path (${STORAGE_ROOT}/azerothcore)
### Realm Configuration

128
rebuild-with-modules.sh Executable file
View File

@@ -0,0 +1,128 @@
#!/bin/bash
# AzerothCore Module Rebuild Script
# Automates the process of rebuilding AzerothCore with enabled modules
set -e
echo "🔧 AzerothCore Module Rebuild Script"
echo "==================================="
echo ""
# Check if source repository exists
SOURCE_COMPOSE="/tmp/acore-dev-test/docker-compose.yml"
if [ ! -f "$SOURCE_COMPOSE" ]; then
echo "❌ Error: Source-based Docker Compose file not found at $SOURCE_COMPOSE"
echo "Please ensure AzerothCore source repository is available for compilation."
exit 1
fi
# Check current module configuration
echo "📋 Checking current module configuration..."
MODULES_ENABLED=0
ENABLED_MODULES=""
# Read environment file to check enabled modules
if [ -f "docker-compose-azerothcore-services.env" ]; then
while IFS= read -r line; do
if echo "$line" | grep -q "^MODULE_.*=1$"; then
MODULE_NAME=$(echo "$line" | cut -d'=' -f1)
MODULES_ENABLED=$((MODULES_ENABLED + 1))
ENABLED_MODULES="$ENABLED_MODULES $MODULE_NAME"
fi
done < docker-compose-azerothcore-services.env
else
echo "⚠️ Warning: Environment file not found, checking default configuration..."
fi
echo "🔍 Found $MODULES_ENABLED enabled modules"
if [ $MODULES_ENABLED -eq 0 ]; then
echo "✅ No modules enabled - rebuild not required"
echo "You can use pre-built containers for better performance."
exit 0
fi
echo "📦 Enabled modules:$ENABLED_MODULES"
echo ""
# Confirm rebuild
read -p "🤔 Proceed with rebuild? This will take 15-45 minutes. (y/N): " -n 1 -r
echo ""
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
echo "❌ Rebuild cancelled"
exit 0
fi
echo ""
echo "🛑 Stopping current services..."
docker compose -f docker-compose-azerothcore-services.yml down || echo "⚠️ Services may not be running"
echo ""
echo "🔧 Starting source-based compilation..."
echo "⏱️ This will take 15-45 minutes depending on your system..."
echo ""
# Build with source
cd /tmp/acore-dev-test
echo "📁 Switched to source directory: $(pwd)"
# Copy modules to source build
echo "📋 Copying modules to source build..."
if [ -d "/home/upb/src/acore-compose2/storage/azerothcore/modules" ]; then
# Ensure modules directory exists in source
mkdir -p modules
# Copy enabled modules only
echo "🔄 Syncing enabled modules..."
for module_dir in /home/upb/src/acore-compose2/storage/azerothcore/modules/*/; do
if [ -d "$module_dir" ]; then
module_name=$(basename "$module_dir")
echo " Copying $module_name..."
cp -r "$module_dir" modules/
fi
done
else
echo "⚠️ Warning: No modules directory found"
fi
# Start build process
echo ""
echo "🚀 Building AzerothCore with modules..."
docker compose build --no-cache
if [ $? -eq 0 ]; then
echo ""
echo "✅ Build completed successfully!"
echo ""
# Start services
echo "🟢 Starting services with compiled modules..."
docker compose up -d
if [ $? -eq 0 ]; then
echo ""
echo "🎉 SUCCESS! AzerothCore is now running with compiled modules."
echo ""
echo "📊 Service status:"
docker compose ps
echo ""
echo "📝 To monitor logs:"
echo " docker compose logs -f"
echo ""
echo "🌐 Server should be available on configured ports once fully started."
else
echo "❌ Failed to start services"
exit 1
fi
else
echo "❌ Build failed"
echo ""
echo "🔍 Check build logs for errors:"
echo " docker compose logs"
exit 1
fi
echo ""
echo "✅ Rebuild process complete!"

View File

@@ -0,0 +1,172 @@
# Test Local Worldserver Performance
This test setup allows you to compare the performance of worldserver with game files stored locally within the container vs. external volume mount.
## What This Tests
### 🧪 **Test Configuration**: Local Game Files with NFS Caching
- Game files (maps, vmaps, mmaps, DBC) cached on NFS and copied to local container storage
- **No external volume mount** for `/azerothcore/data` (files stored locally for performance)
- **NFS cache** for downloaded files (persistent across container restarts)
- First run: ~15GB download and extraction time
- Subsequent runs: ~5-10 minutes (extraction only from cache)
### 📊 **Comparison with Standard Configuration**: External Volume
- Game files stored in external volume mount
- Persistent across container restarts
- One-time download, reused across deployments
## Quick Start
### Prerequisites
Make sure the database and authserver are running first:
```bash
# Start database layer
docker-compose --env-file docker-compose-azerothcore-database.env -f docker-compose-azerothcore-database.yml up -d
# Start authserver (minimal requirement)
docker-compose --env-file docker-compose-azerothcore-services.env -f docker-compose-azerothcore-services.yml up -d ac-authserver
```
### Run the Test
```bash
cd scripts
# Start test worldserver (downloads files locally)
./test-local-worldserver.sh
# Monitor logs
./test-local-worldserver.sh --logs
# Cleanup when done
./test-local-worldserver.sh --cleanup
```
## Test Details
### Port Configuration
- **Test Worldserver**: `localhost:8216` (game), `localhost:7779` (SOAP)
- **Regular Worldserver**: `localhost:8215` (game), `localhost:7778` (SOAP)
Both can run simultaneously without conflicts.
### Download Process
The test worldserver will:
1. Check for cached client data in NFS storage
2. If cached: Copy from cache (fast)
3. If not cached: Download ~15GB client data from GitHub releases and cache it
4. Extract maps, vmaps, mmaps, and DBC files to local container storage
5. Verify all required directories exist
6. Start the worldserver
**Expected startup time**:
- First run: 20-30 minutes (download + extraction)
- Subsequent runs: 5-10 minutes (extraction only from cache)
### Storage Locations
- **Game Files**: `/azerothcore/data` (inside container, not mounted - for performance testing)
- **Cache**: External mount at `storage/azerothcore/cache-test/` (persistent across restarts)
- **Config**: External mount (shared with regular deployment)
- **Logs**: External mount at `storage/azerothcore/logs-test/`
## Performance Metrics to Compare
### Startup Time
- **Regular**: ~2-3 minutes (files already extracted in external volume)
- **Test (first run)**: ~20-30 minutes (download + extraction + cache)
- **Test (cached)**: ~5-10 minutes (extraction only from cache)
### Runtime Performance
Compare these during gameplay:
- Map loading times
- Zone transitions
- Server responsiveness
- Memory usage
- CPU utilization
### Storage Usage
- **Regular**: Persistent ~15GB in external volume
- **Test**: ~15GB cache in external volume + ~15GB ephemeral inside container
- **Test Total**: ~30GB during operation (cache + local copy)
## Monitoring Commands
```bash
# Check container status
docker ps | grep test
# Monitor logs
docker logs ac-worldserver-test -f
# Check game data size (local in container)
docker exec ac-worldserver-test du -sh /azerothcore/data/*
# Check cache size (persistent)
ls -la storage/azerothcore/cache-test/
du -sh storage/azerothcore/cache-test/*
# Check cached version
cat storage/azerothcore/cache-test/client-data-version.txt
# Check server processes
docker exec ac-worldserver-test ps aux | grep worldserver
# Monitor resource usage
docker stats ac-worldserver-test
```
## Testing Scenarios
### 1. Startup Performance
```bash
# Time the full startup
time ./test-local-worldserver.sh
# Compare with regular worldserver restart
docker restart ac-worldserver
```
### 2. Runtime Performance
Connect a game client to both servers and compare:
- Zone loading times
- Combat responsiveness
- Large area rendering
### 3. Resource Usage
```bash
# Compare memory usage
docker stats ac-worldserver ac-worldserver-test --no-stream
# Compare disk I/O
docker exec ac-worldserver-test iostat 1 5
docker exec ac-worldserver iostat 1 5
```
## Cleanup
```bash
# Stop and remove test container
./test-local-worldserver.sh --cleanup
# Remove test logs
rm -rf storage/azerothcore/logs-test/
```
## Expected Results
### Pros of Local Files
- Potentially faster file I/O (no network mount overhead)
- Self-contained container
- No external volume dependencies
### Cons of Local Files
- Much longer startup time (20-30 minutes)
- Re-download on every container recreation
- Larger container footprint
- No persistence across restarts
## Conclusion
This test will help determine if the performance benefits of local file storage outweigh the significant startup time and storage overhead costs.

225
scripts/test-local-worldserver.sh Executable file
View File

@@ -0,0 +1,225 @@
#!/bin/bash
# ==============================================
# TEST LOCAL WORLDSERVER DEPLOYMENT SCRIPT
# ==============================================
# This script tests worldserver performance with local game files
# vs. external volume mount
set -e # Exit on any error
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
MAGENTA='\033[0;35m'
NC='\033[0m' # No Color
# Function to print colored output
print_status() {
local status=$1
local message=$2
case $status in
"INFO")
echo -e "${BLUE} ${message}${NC}"
;;
"SUCCESS")
echo -e "${GREEN}${message}${NC}"
;;
"WARNING")
echo -e "${YELLOW}⚠️ ${message}${NC}"
;;
"ERROR")
echo -e "${RED}${message}${NC}"
;;
"HEADER")
echo -e "\n${MAGENTA}=== ${message} ===${NC}"
;;
"TEST")
echo -e "${YELLOW}🧪 ${message}${NC}"
;;
esac
}
# Parse command line arguments
CLEANUP=false
LOGS=false
while [[ $# -gt 0 ]]; do
case $1 in
--cleanup)
CLEANUP=true
shift
;;
--logs)
LOGS=true
shift
;;
-h|--help)
echo "Test Local Worldserver Deployment Script"
echo ""
echo "Usage: $0 [OPTIONS]"
echo ""
echo "OPTIONS:"
echo " --cleanup Stop and remove test worldserver"
echo " --logs Follow test worldserver logs"
echo " --help Show this help message"
echo ""
echo "EXAMPLES:"
echo " $0 # Deploy test worldserver"
echo " $0 --logs # Follow logs of running test"
echo " $0 --cleanup # Clean up test deployment"
exit 0
;;
*)
echo "Unknown option $1"
echo "Use --help for usage information"
exit 1
;;
esac
done
# Change to parent directory for compose commands
cd "$(dirname "$0")/.."
if [ "$CLEANUP" = true ]; then
print_status "HEADER" "CLEANING UP TEST WORLDSERVER"
print_status "INFO" "Stopping test worldserver..."
docker-compose --env-file docker-compose-test-worldserver.env -f docker-compose-test-worldserver.yml down
print_status "INFO" "Removing test container if exists..."
docker rm -f ac-worldserver-test 2>/dev/null || true
print_status "SUCCESS" "Test cleanup completed"
exit 0
fi
if [ "$LOGS" = true ]; then
print_status "HEADER" "FOLLOWING TEST WORLDSERVER LOGS"
docker logs ac-worldserver-test -f
exit 0
fi
# Main deployment
print_status "HEADER" "DEPLOYING TEST WORLDSERVER WITH LOCAL GAME FILES"
# Check if docker is available
if ! command -v docker &> /dev/null; then
print_status "ERROR" "Docker is not installed or not in PATH"
exit 1
fi
# Check if main database is running
if ! docker ps | grep ac-mysql > /dev/null; then
print_status "ERROR" "Main database (ac-mysql) is not running"
print_status "INFO" "Please start the database layer first:"
print_status "INFO" " docker-compose --env-file docker-compose-azerothcore-database.env -f docker-compose-azerothcore-database.yml up -d"
exit 1
fi
# Check if authserver is running
if ! docker ps | grep ac-authserver > /dev/null; then
print_status "ERROR" "Auth server (ac-authserver) is not running"
print_status "INFO" "Please start the services layer first (or at least authserver):"
print_status "INFO" " docker-compose --env-file docker-compose-azerothcore-services.env -f docker-compose-azerothcore-services.yml up -d ac-authserver"
exit 1
fi
# Check if regular worldserver is running (warn about port conflicts)
if docker ps | grep ac-worldserver | grep -v test > /dev/null; then
print_status "WARNING" "Regular worldserver is running - test uses different ports"
print_status "INFO" "Test worldserver ports: 8216 (world), 7779 (SOAP)"
print_status "INFO" "Regular worldserver ports: 8215 (world), 7778 (SOAP)"
fi
print_status "INFO" "Prerequisites check passed"
# Check for cached files
if [ -f "storage/azerothcore/cache-test/client-data-version.txt" ]; then
CACHED_VERSION=$(cat storage/azerothcore/cache-test/client-data-version.txt 2>/dev/null)
print_status "INFO" "Found cached game files (version: $CACHED_VERSION)"
print_status "SUCCESS" "No internet download needed - using cached files!"
print_status "INFO" "Expected startup time: 5-10 minutes (extraction only)"
else
print_status "WARNING" "No cached files found - will download ~15GB from internet"
print_status "INFO" "Expected startup time: 20-30 minutes (download + extraction)"
fi
# Start test worldserver
print_status "TEST" "Starting test worldserver with cached local game files..."
print_status "INFO" "Cache location: storage/azerothcore/cache-test/"
print_status "INFO" "Game files will be copied to local container storage for performance testing"
print_status "INFO" "Test worldserver will be available on port 8216"
# Record start time
START_TIME=$(date +%s)
print_status "INFO" "Deployment started at: $(date)"
# Start the test container
docker-compose --env-file docker-compose-test-worldserver.env -f docker-compose-test-worldserver.yml up -d
print_status "SUCCESS" "Test worldserver container started"
print_status "INFO" "Container name: ac-worldserver-test"
print_status "HEADER" "MONITORING TEST DEPLOYMENT"
print_status "INFO" "Following logs for the first few minutes..."
print_status "INFO" "Press Ctrl+C to stop following logs (container will continue running)"
print_status "INFO" ""
print_status "TEST" "=== LIVE LOG OUTPUT ==="
# Follow logs for a bit
timeout 300 docker logs ac-worldserver-test -f 2>/dev/null || true
print_status "INFO" ""
print_status "HEADER" "TEST DEPLOYMENT STATUS"
# Check if container is still running
if docker ps | grep ac-worldserver-test > /dev/null; then
print_status "SUCCESS" "Test container is running"
# Calculate elapsed time
CURRENT_TIME=$(date +%s)
ELAPSED=$((CURRENT_TIME - START_TIME))
ELAPSED_MIN=$((ELAPSED / 60))
print_status "INFO" "Elapsed time: ${ELAPSED_MIN} minutes"
print_status "INFO" "Container status: $(docker ps --format '{{.Status}}' --filter name=ac-worldserver-test)"
print_status "HEADER" "USEFUL COMMANDS"
echo -e "${BLUE}Monitor logs:${NC}"
echo " $0 --logs"
echo " docker logs ac-worldserver-test -f"
echo ""
echo -e "${BLUE}Check container status:${NC}"
echo " docker ps | grep test"
echo " docker exec ac-worldserver-test ps aux | grep worldserver"
echo ""
echo -e "${BLUE}Check game data (local in container):${NC}"
echo " docker exec ac-worldserver-test ls -la /azerothcore/data/"
echo " docker exec ac-worldserver-test du -sh /azerothcore/data/*"
echo ""
echo -e "${BLUE}Check cached files (persistent):${NC}"
echo " ls -la storage/azerothcore/cache-test/"
echo " du -sh storage/azerothcore/cache-test/*"
echo " cat storage/azerothcore/cache-test/client-data-version.txt"
echo ""
echo -e "${BLUE}Connect to test server:${NC}"
echo " Game Port: localhost:8216"
echo " SOAP Port: localhost:7779"
echo ""
echo -e "${BLUE}Performance comparison:${NC}"
echo " docker stats ac-worldserver ac-worldserver-test --no-stream"
echo ""
echo -e "${BLUE}Cleanup test:${NC}"
echo " $0 --cleanup"
echo " rm -rf storage/azerothcore/cache-test/ # Remove cache"
else
print_status "ERROR" "Test container has stopped or failed"
print_status "INFO" "Check logs for details:"
print_status "INFO" " docker logs ac-worldserver-test"
exit 1
fi