diff --git a/.env.template b/.env.template index 2fd8416..b913c58 100644 --- a/.env.template +++ b/.env.template @@ -31,6 +31,7 @@ MYSQL_INNODB_LOG_FILE_SIZE=64M DB_AUTH_NAME=acore_auth DB_WORLD_NAME=acore_world DB_CHARACTERS_NAME=acore_characters +DB_PLAYERBOTS_NAME=acore_playerbots # DB import image AC_DB_IMPORT_IMAGE=acore/ac-wotlk-db-import:14.0.0-dev @@ -130,6 +131,7 @@ MODULE_BLACK_MARKET_AUCTION_HOUSE=0 # Rebuild automation # ===================== AUTO_REBUILD_ON_DEPLOY=0 +# Default AzerothCore source checkout used for module rebuilds MODULES_REBUILD_SOURCE_PATH=./source/azerothcore # ===================== diff --git a/README.md b/README.md index 435db9c..97ea5b1 100644 --- a/README.md +++ b/README.md @@ -1,148 +1,400 @@ -# ac-compose Deployment Guide +# AzerothCore Docker/Compose Stack -This guide walks through the end-to-end deployment workflow for the `ac-compose` stack. It focuses on the supported automation scripts, the order in which to run them, the default services/ports that come online, and the optional manual steps you may need when enabling additional modules. +A complete containerized deployment of AzerothCore WoW 3.3.5a (Wrath of the Lich King) private server with enhanced modules, automated management, and production-ready features. +## πŸš€ Quick Start -## 1. Prerequisites +### Prerequisites +- **Docker** and **Docker Compose v2** installed +- **4GB+ RAM** and **20GB+ storage** +- **Linux/macOS/WSL2** (Windows with WSL2 recommended) -Before you begin: +### ⚑ Automated Setup (Recommended) -- **Docker** and **Docker Compose v2** installed on the host. -- A POSIX-compatible shell (the provided scripts target Bash). -- Sufficient disk space for game assets, module clones, and source builds (β€―β‰ˆβ€―20β€―GB recommended). -- Network access to GitHub (or a local mirror) for cloning AzerothCore source and modules. - -> Tip: If you use a distinct user/group mapping (e.g., NFS-backed storage) the setup wizard will let you pick non-root UIDs/GIDs. - - -## 2. Generate `.env` via `setup.sh` - -All environment configuration lives in `ac-compose/.env`. Generate or refresh it by running: +**1. Get the Code** +```bash +git clone https://github.com/uprightbass360/acore-compose.git +cd acore-compose +``` +**2. Run Interactive Setup** ```bash ./setup.sh ``` -The wizard will ask you to confirm: - -1. **Deployment type** (local, LAN, or public) – sets bind address and default ports. -2. **Filesystem ownership** for container volumes. -3. **Exterior ports** for Auth (default 3784), World (8215), SOAP (7778), and MySQL (64306). -4. **Storage path** (default `./storage`) and backup retention. -5. **Module preset**. The wizard defaults to a safe set (Solo LFG, Solocraft, Autobalance, Transmog, NPC Buffer, Learn Spells, Fireworks). Manual mode lets you toggle more modules, while warning you about unsafe or incompatible ones. - -### Module notes from the wizard - -- **AHBot** – remains disabled until the upstream module exports `Addmod_ahbotScripts()` (linker failure otherwise). -- **Quest Count Level** – disabled: relies on deprecated ConfigMgr calls and fails to compile. -- **Eluna** – bundled with AzerothCore by default. To disable the runtime later, edit the `AC_ELUNA_ENABLED` flag under β€œEluna runtime” in `.env`. -- Other disabled modules (Individual Progression, Breaking News, TimeIsTime, Pocket Portal, Random Enchants, NPC Beastmaster/Enchanter, Instance Reset, etc.) require additional SQL, DBC, or in-game configuration. Inline comments in `.env` describe these requirements. - -When the wizard completes, it writes the fully populated `.env`. Re-run `./setup.sh` anytime you want to regenerate the file; make backups first if you have custom edits. - - -## 3. (Optional) Clone AzerothCore Source - -Certain modules require recompiling the AzerothCore core. If you plan to enable any of them, clone/update the source repository first: - +**3. Deploy Your Realm** ```bash -./scripts/setup-source.sh +./deploy.sh ``` -This script: +**4. Create Admin Account** -- Reads `MODULES_REBUILD_SOURCE_PATH` (default `./source/azerothcore`). -- Clones or updates the repository (uses the Playerbot fork if `MODULE_PLAYERBOTS=1`). -- Ensures the desired branch is checked out. - -You can rerun it whenever you need to pull upstream updates. - - -## 4. Deploy with `deploy.sh` - -Use `deploy.sh` to perform a full module-aware deployment. Example: +Once the worldserver is running: ```bash -./deploy.sh --profile modules +# Attach to worldserver console +docker attach ac-worldserver + +# In the worldserver console, create admin account: +account create admin yourpassword +account set gmlevel admin 3 -1 +server info + +# Detach from console without stopping: Ctrl+P, Ctrl+Q ``` -What the script does: +**5. Configure Game Client** -1. Stops any running stack (unless `--keep-running` is supplied) to avoid container-name conflicts. -2. Runs the modules manager (`docker compose --profile db --profile modules up ac-modules`) to clone missing modules, apply configuration, and execute module SQL. -3. Rebuilds AzerothCore from source if any C++ modules are enabled. The helper also tags the freshly-built images as `acore/ac-wotlk-{worldserver,authserver}:modules-latest` for subsequent compose runs. -4. Stages the runtime profile by invoking `./scripts/stage-modules.sh --yes`. -5. Tails the `ac-worldserver` logs by default (omit with `--no-watch`). +**Client Connection Instructions**: -Useful flags: - -- `--profile {standard|playerbots|modules}` – force a specific services profile instead of auto-detecting by module toggles. -- `--skip-rebuild` – skip the source rebuild even if modules demand it (not recommended unless you are certain rebuilt images already exist). -- `--keep-running` – do not stop existing containers before syncing modules (use sparingly; stale `ac-db-import` containers can block the rebuild stage). -- `--no-watch` – exit after staging without tailing worldserver logs. - -All Docker Compose commands run with the project name derived from `COMPOSE_PROJECT_NAME` in `.env` (default `ac-compose`). - - -### If you prefer a health check after deployment - -Run: +1. **Locate your WoW 3.3.5a client directory** +2. **Edit `realmlist.wtf` file** (in your WoW client folder): + ``` + set realmlist SERVER_ADDRESS + ``` +**Examples based on your server configuration**: ```bash -./verify-deployment.sh --skip-deploy --quick +# Local development +set realmlist 127.0.0.1 + +# LAN server +set realmlist 192.168.1.100 + +# Public server with custom port +set realmlist your-domain.com 8215 +# or for IP with custom port +set realmlist 203.0.113.100 8215 ``` -This script inspects container health states and key ports without altering the running stack. +**6. Access Your Realm** +- **Game Server**: `your-server-ip:8215` (or port you configured) +- **Database Admin**: http://localhost:8081 (phpMyAdmin) +- **Game Content Editor**: http://localhost:4201 (Keira3) - -## 5. Service Inventory & Default Ports - -| Service / Container | Role | Ports (host β†’ container) | Profile(s) | -|----------------------------|-------------------------------------|--------------------------|----------------------------| -| `ac-mysql` | MySQL 8.0 database | `64306 β†’ 3306` | `db` | -| `ac-db-import` | One-shot DB import/update | – | `db` | -| `ac-db-init` | Schema bootstrap helper | – | `db` | -| `ac-authserver` | Auth server (no modules) | `3784 β†’ 3724` | `services-standard` | -| `ac-worldserver` | World server (no modules) | `8215 β†’ 8085`, `7778 β†’ 7878` (SOAP) | `services-standard` | -| `ac-authserver-modules` | Auth server w/ custom build | `3784 β†’ 3724` | `services-modules` | -| `ac-worldserver-modules` | World server w/ custom build | `8215 β†’ 8085`, `7778 β†’ 7878` | `services-modules` | -| `ac-authserver-playerbots` | Playerbots auth image | `3784 β†’ 3724` | `services-playerbots` | -| `ac-worldserver-playerbots`| Playerbots world image | `8215 β†’ 8085`, `7778 β†’ 7878` | `services-playerbots` | -| `ac-client-data-standard` | Client-data fetcher | – | `client-data` | -| `ac-modules` | Module management / SQL executor | – | `modules` | -| `ac-phpmyadmin` | phpMyAdmin UI | `8081 β†’ 80` | `tools` | -| `ac-keira3` | Keira3 world editor | `4201 β†’ 8080` | `tools` | - -Additional services (e.g., backups, monitoring) can be enabled by editing `.env` and the compose file as needed. - - -## 6. Manual Tasks & Advanced Options - -- **Disabling Eluna**: Eluna’s runtime flags live near the end of `.env`. Set `AC_ELUNA_ENABLED=0` if you do not want Lua scripting loaded. -- **Enabling experimental modules**: Edit `.env` toggles. Review the inline comments carefullyβ€”some modules require additional SQL, DBC patches, or configuration files before they work safely. -- **Custom `.env` variants**: You can create `.env.custom` files and run `docker compose --env-file` if you maintain multiple environments. The setup wizard always writes `./.env`. -- **Manual source rebuild**: If you prefer to rebuild without staging services, run `./scripts/rebuild-with-modules.sh --yes`. The script now stops and cleans up its own compose project to avoid lingering containers. -- **Health check**: `verify-deployment.sh` can also be run without `--skip-deploy` to bring up a stack and verify container states using the default profiles. - - -## 7. Clean-Up & Re-running - -- To tear down everything: `docker compose --profile db --profile services-standard --profile services-playerbots --profile services-modules --profile client-data --profile modules --profile tools down`. -- To force the module manager to re-run (e.g., after toggling modules in `.env`): `docker compose --profile db --profile modules up --build ac-modules`. -- Storage (logs, configs, client data) lives under `./storage` by default; remove directories carefully if you need a clean slate. - - -## 8. Further Reading - -For a full description of individual modules, sample workflows, or deeper dive into AzerothCore internals, consult the original **V1 README** and linked documentation inside the `V1/` directory. Those docs provide module-specific CMake and SQL references you can adapt if you decide to maintain custom forks. +βœ… **That's it!** Your realm is ready with all enabled modules installed and configured. --- -You now have a repeatable, script-driven deployment process: +## πŸ“‹ What Gets Installed Automatically -1. Configure once with `setup.sh`. -2. (Optional) Pull upstream source via `scripts/setup-source.sh`. -3. Deploy and stage via `deploy.sh`. -4. Verify with `verify-deployment.sh` or directly inspect `docker compose ps`. +### βœ… Core Server Components +- **AzerothCore 3.3.5a** - WotLK server application +- **MySQL 8.0** - Database with intelligent initialization and restoration +- **Smart Module System** - Automated module management and source builds +- **phpMyAdmin** - Web-based database administration +- **Keira3** - Game content editor and developer tools -Happy adventuring! +### βœ… Available Enhanced Modules + +All modules are automatically downloaded, configured, and SQL scripts executed when enabled: + +| Module | Description | Default Status | +|--------|-------------|----------------| +| **mod-solo-lfg** | Solo dungeon finder access | βœ… ENABLED | +| **mod-solocraft** | Dynamic instance scaling for solo play | βœ… ENABLED | +| **mod-autobalance** | Automatic raid/dungeon balancing | βœ… ENABLED | +| **mod-transmog** | Appearance customization system | βœ… ENABLED | +| **mod-npc-buffer** | NPC buffing services | βœ… ENABLED | +| **mod-learn-spells** | Automatic spell learning | βœ… ENABLED | +| **mod-fireworks** | Level-up celebrations | βœ… ENABLED | +| **mod-playerbots** | AI companions for solo play | πŸ”§ OPTIONAL | +| **mod-aoe-loot** | Streamlined loot collection | πŸ”§ OPTIONAL | +| **mod-individual-progression** | Personal advancement system | ❌ DISABLED* | +| **mod-ahbot** | Auction house bot | ❌ DISABLED* | +| **mod-dynamic-xp** | Dynamic experience rates | πŸ”§ OPTIONAL | +| **mod-1v1-arena** | Solo arena battles | πŸ”§ OPTIONAL | +| **mod-phased-duels** | Phased dueling system | πŸ”§ OPTIONAL | +| **mod-breaking-news** | Server announcement system | ❌ DISABLED* | +| **mod-boss-announcer** | Boss kill announcements | πŸ”§ OPTIONAL | +| **mod-account-achievements** | Account-wide achievements | πŸ”§ OPTIONAL | +| **mod-auto-revive** | Automatic resurrection | πŸ”§ OPTIONAL | +| **mod-gain-honor-guard** | Honor from guard kills | πŸ”§ OPTIONAL | +| **mod-time-is-time** | Time manipulation | ❌ DISABLED* | +| **mod-pocket-portal** | Portal convenience | ❌ DISABLED* | +| **mod-random-enchants** | Random item enchantments | πŸ”§ OPTIONAL | +| **mod-pvp-titles** | PvP title system | πŸ”§ OPTIONAL | +| **mod-npc-beastmaster** | Pet management NPC | ❌ DISABLED* | +| **mod-npc-enchanter** | Enchanting services NPC | ❌ DISABLED* | +| **mod-instance-reset** | Instance reset controls | ❌ DISABLED* | + +*\* Disabled modules require additional configuration or have compatibility issues* + +### βœ… Automated Configuration +- **Intelligent Database Setup** - Smart backup detection, restoration, and conditional schema import +- **Module Integration** - Automatic source builds when C++ modules are enabled +- **Realmlist Configuration** - Server address and port setup +- **Service Orchestration** - Profile-based deployment (standard/playerbots/modules) +- **Health Monitoring** - Container health checks and restart policies + +--- + +## πŸ—οΈ Architecture Overview + +### Container Profiles +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Tools Profile β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ phpMyAdmin β”‚ β”‚ Keira3 β”‚ β”‚ +β”‚ β”‚ :8081 β”‚ β”‚ :4201 β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Services Profiles β”‚ +β”‚ Standard | Playerbots | Modules β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ Auth β”‚ β”‚ World β”‚ β”‚ Client β”‚ β”‚ +β”‚ β”‚ :3784 β”‚ β”‚ :8215 β”‚ β”‚ Data β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Database & Modules β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ MySQL β”‚ β”‚ Module β”‚ β”‚ DB-Init β”‚ β”‚ +β”‚ β”‚ :64306 β”‚ β”‚ Manager β”‚ β”‚ & Imp. β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### Service Inventory & Ports + +| Service / Container | Role | Ports (host β†’ container) | Profile | +|---------------------|------|--------------------------|---------| +| `ac-mysql` | MySQL 8.0 database | `64306 β†’ 3306` | `db` | +| `ac-authserver` | Auth server (standard) | `3784 β†’ 3724` | `services-standard` | +| `ac-worldserver` | World server (standard) | `8215 β†’ 8085`, `7778 β†’ 7878` | `services-standard` | +| `ac-authserver-playerbots` | Playerbots auth | `3784 β†’ 3724` | `services-playerbots` | +| `ac-worldserver-playerbots` | Playerbots world | `8215 β†’ 8085`, `7778 β†’ 7878` | `services-playerbots` | +| `ac-authserver-modules` | Custom build auth | `3784 β†’ 3724` | `services-modules` | +| `ac-worldserver-modules` | Custom build world | `8215 β†’ 8085`, `7778 β†’ 7878` | `services-modules` | +| `ac-client-data` | Client data fetcher | – | `client-data` | +| `ac-modules` | Module manager | – | `modules` | +| `ac-phpmyadmin` | Database admin UI | `8081 β†’ 80` | `tools` | +| `ac-keira3` | Game content editor | `4201 β†’ 8080` | `tools` | + +### Storage Structure +``` +storage/ +β”œβ”€β”€ config/ # Server configuration files +β”œβ”€β”€ data/ # Game client data (maps, DBC files) +β”œβ”€β”€ logs/ # Server log files +β”œβ”€β”€ modules/ # Module source code and configs +β”œβ”€β”€ mysql-data/ # Database files +└── backups/ # Automated database backups +``` + +--- + +## πŸ› οΈ Management Commands + +### Health Monitoring +```bash +# Check realm status +./status.sh + +# Watch services continuously +./status.sh --watch + +# View service logs +docker logs ac-worldserver -f +docker logs ac-authserver -f + +# Check module management +docker logs ac-modules --tail 50 +``` + +### Module Management +```bash +# Reconfigure modules via interactive setup +./setup.sh + +# Deploy with specific profile +./deploy.sh --profile standard # Standard AzerothCore +./deploy.sh --profile playerbots # Playerbots branch +./deploy.sh --profile modules # Custom modules build + +# Force source rebuild +./scripts/rebuild-with-modules.sh --yes + +# Stage services without full deployment +./scripts/stage-modules.sh + +# Launch management tooling (phpMyAdmin + Keira3) +./scripts/deploy-tools.sh +``` + +### Database Operations +```bash +# Access database via phpMyAdmin +open http://localhost:8081 + +# Direct MySQL access +docker exec -it ac-mysql mysql -u root -p + +# View available backups +ls -la storage/backups/ +``` + +### Deployment Verification +```bash +# Quick health check +./verify-deployment.sh --skip-deploy --quick + +# Full deployment verification +./verify-deployment.sh +``` + +--- + +## πŸ”§ Advanced Configuration + +### Module-Specific Requirements + +Some modules require additional manual configuration after deployment: + +#### mod-playerbots +- Requires playerbots-specific AzerothCore branch +- Automatically handled when `MODULE_PLAYERBOTS=1` is set in setup + +#### mod-individual-progression +- **Client patches required**: `patch-V.mpq` (found in module storage) +- **Server config**: Add `EnablePlayerSettings = 1` and `DBC.EnforceItemAttributes = 0` to worldserver.conf + +#### mod-transmog / mod-npc-* modules +- **NPC spawning required**: Use GM commands to spawn service NPCs +- Example: `.npc add 190010` for transmog NPC + +### Profile Selection + +The deployment system automatically selects profiles based on enabled modules: + +- **services-standard**: No special modules enabled +- **services-playerbots**: `MODULE_PLAYERBOTS=1` enabled +- **services-modules**: Any C++ modules enabled (requires source rebuild) + +### Custom Builds + +When C++ modules are enabled, the system automatically: +1. Clones/updates AzerothCore source +2. Syncs enabled modules into source tree +3. Rebuilds server images with modules compiled in +4. Tags custom images for deployment + +--- + +## πŸ”§ Troubleshooting + +### Common Issues + +**Containers failing to start** +```bash +# Check container logs +docker logs + +# Verify network connectivity +docker network ls | grep azerothcore + +# Check port conflicts +ss -tulpn | grep -E "(3784|8215|8081|4201)" +``` + +**Module not working** +```bash +# Check if module is enabled in environment +grep MODULE_NAME .env + +# Verify module installation +ls storage/modules/ + +# Check module-specific configuration +ls storage/config/mod_*.conf* +``` + +**Database connection issues** +```bash +# Verify MySQL is running and responsive +docker exec ac-mysql mysql -u root -p -e "SELECT 1;" + +# Check database initialization +docker logs ac-db-init +docker logs ac-db-import +``` + +**Source rebuild issues** +```bash +# Check rebuild logs +docker logs ac-modules | grep -A20 -B5 "rebuild" + +# Verify source path exists +ls -la ./source/azerothcore/ + +# Force source setup +./scripts/setup-source.sh +``` + +### Getting Help + +1. **Check service status**: `./status.sh --watch` +2. **Review logs**: `docker logs -f` +3. **Verify configuration**: Check `.env` file for proper module toggles +4. **Clean deployment**: Stop all services and redeploy with `./deploy.sh` + +--- + +## πŸ“š Advanced Deployment Options + +### Custom Environment Configuration +```bash +# Generate environment with custom settings +./setup.sh + +# Deploy with specific options +./deploy.sh --profile modules --no-watch --keep-running +``` + +### Source Management +```bash +# Setup/update AzerothCore source +./scripts/setup-source.sh + +# Rebuild with modules (manual) +./scripts/rebuild-with-modules.sh --yes --source ./custom/path +``` + +### Cleanup Operations +```bash +# Stop all services +docker compose --profile db --profile services-standard \ + --profile services-playerbots --profile services-modules \ + --profile client-data --profile modules --profile tools down + +# Clean rebuild (modules changed) +rm -f storage/modules/.requires_rebuild +./deploy.sh --profile modules +``` + +--- + +## 🎯 Next Steps After Installation + +1. **Test Client Connection** - Connect with WoW 3.3.5a client using configured realmlist +2. **Create Characters** - Test account creation and character creation +3. **Verify Modules** - Test enabled module functionality in-game +4. **Configure Optional Features** - Enable additional modules as needed +5. **Set Up Backups** - Configure automated backup retention policies + +--- + +## πŸ“„ Project Credits + +This project builds upon: +- **[AzerothCore](https://github.com/azerothcore/azerothcore-wotlk)** - Core server application +- **[AzerothCore Module Community](https://github.com/azerothcore)** - Enhanced gameplay modules + +### Key Features +- βœ… **Fully Automated Setup** - Interactive configuration and deployment +- βœ… **Intelligent Module System** - Automatic source builds and profile selection +- βœ… **Production Ready** - Health checks, backups, monitoring +- βœ… **Cross-Platform** - Docker and Podman support +- βœ… **Comprehensive Documentation** - Clear setup and troubleshooting guides diff --git a/cleanup.sh b/cleanup.sh index 5902a6d..3c745b2 100755 --- a/cleanup.sh +++ b/cleanup.sh @@ -101,6 +101,20 @@ if [ -f "$ENV_FILE" ]; then set -a; source "$ENV_FILE"; set +a fi STORAGE_PATH="${STORAGE_PATH:-$STORAGE_PATH_DEFAULT}" +PROJECT_NAME="${COMPOSE_PROJECT_NAME:-ac-compose}" + +remove_storage_dir(){ + local path="$1" + if [ -d "$path" ]; then + rm -rf "$path" 2>/dev/null || sudo rm -rf "$path" 2>/dev/null || true + fi +} + +remove_project_volumes(){ + docker volume ls --format '{{.Name}}' \ + | grep -E "^${PROJECT_NAME}|^azerothcore" \ + | xargs -r docker volume rm >/dev/null 2>&1 || true +} soft_cleanup() { print_status HEADER "SOFT CLEANUP - Stop runtime stack" @@ -133,6 +147,7 @@ hard_cleanup() { --profile db ) execute_command "Removing containers and networks" docker compose -f "$COMPOSE_FILE" "${profiles[@]}" down --remove-orphans + execute_command "Remove project volumes" remove_project_volumes # Remove straggler containers matching project name (defensive) execute_command "Remove stray project containers" "docker ps -a --format '{{.Names}}' | grep -E '^ac-' | xargs -r docker rm -f" # Remove project network if present and not automatically removed @@ -159,6 +174,7 @@ nuclear_cleanup() { --profile db ) execute_command "Removing containers, networks and volumes" docker compose -f "$COMPOSE_FILE" "${profiles[@]}" down --volumes --remove-orphans + execute_command "Remove leftover volumes" remove_project_volumes # Remove project images (server/tool images typical to this project) execute_command "Remove acore images" "docker images --format '{{.Repository}}:{{.Tag}}' | grep -E '^acore/' | xargs -r docker rmi" @@ -170,15 +186,15 @@ nuclear_cleanup() { print_status INFO "Preserving backups under ${STORAGE_PATH}/backups" TMP_PRESERVE="${PROJECT_DIR}/.preserve-backups" if [ -d "${STORAGE_PATH}/backups" ]; then - execute_command "Staging backups" "mkdir -p '${TMP_PRESERVE}' && cp -r '${STORAGE_PATH}/backups' '${TMP_PRESERVE}/'" + execute_command "Staging backups" "mkdir -p '${TMP_PRESERVE}' && cp -a '${STORAGE_PATH}/backups' '${TMP_PRESERVE}/'" fi - execute_command "Removing storage" "rm -rf '${STORAGE_PATH}' 2>/dev/null || true" + execute_command "Removing storage" "remove_storage_dir '${STORAGE_PATH}'" if [ -d "${TMP_PRESERVE}/backups" ]; then execute_command "Restoring backups" "mkdir -p '${STORAGE_PATH}' && mv '${TMP_PRESERVE}/backups' '${STORAGE_PATH}/backups' && rm -rf '${TMP_PRESERVE}'" print_status SUCCESS "Backups preserved at ${STORAGE_PATH}/backups" fi else - execute_command "Removing storage and local backups" "rm -rf '${STORAGE_PATH}' '${PROJECT_DIR}/backups' 2>/dev/null || true" + execute_command "Removing storage and local backups" "remove_storage_dir '${STORAGE_PATH}'; remove_storage_dir '${PROJECT_DIR}/backups'" fi # Optional system prune for project context diff --git a/compose.yml b/compose.yml index 242e2b7..af22816 100644 --- a/compose.yml +++ b/compose.yml @@ -558,6 +558,9 @@ services: - DB_AUTH_NAME=${DB_AUTH_NAME:-acore_auth} - DB_WORLD_NAME=${DB_WORLD_NAME:-acore_world} - DB_CHARACTERS_NAME=${DB_CHARACTERS_NAME:-acore_characters} + - DB_PLAYERBOTS_NAME=${DB_PLAYERBOTS_NAME:-acore_playerbots} + - MYSQL_CHARACTER_SET=${MYSQL_CHARACTER_SET:-utf8mb4} + - MYSQL_COLLATION=${MYSQL_COLLATION:-utf8mb4_unicode_ci} - CONTAINER_USER=${CONTAINER_USER:-0:0} entrypoint: ["/bin/sh"] command: @@ -587,6 +590,9 @@ services: DB_AUTH_NAME: ${DB_AUTH_NAME:-acore_auth} DB_WORLD_NAME: ${DB_WORLD_NAME:-acore_world} DB_CHARACTERS_NAME: ${DB_CHARACTERS_NAME:-acore_characters} + DB_PLAYERBOTS_NAME: ${DB_PLAYERBOTS_NAME:-acore_playerbots} + MYSQL_CHARACTER_SET: ${MYSQL_CHARACTER_SET:-utf8mb4} + MYSQL_COLLATION: ${MYSQL_COLLATION:-utf8mb4_unicode_ci} STORAGE_PATH: ${STORAGE_PATH:-./storage} SERVER_ADDRESS: ${SERVER_ADDRESS:-127.0.0.1} REALM_PORT: ${REALM_PORT:-8215} diff --git a/deploy.sh b/deploy.sh index 62d8a4a..5be26ed 100755 --- a/deploy.sh +++ b/deploy.sh @@ -22,6 +22,23 @@ ok(){ echo -e "${GREEN}βœ… $*${NC}"; } warn(){ echo -e "${YELLOW}⚠️ $*${NC}"; } err(){ echo -e "${RED}❌ $*${NC}"; } +show_deployment_header(){ + echo -e "\n${BLUE} βš”οΈ AZEROTHCORE REALM DEPLOYMENT βš”οΈ${NC}" + echo -e "${BLUE} ════════════════════════════════════${NC}" + echo -e "${BLUE} 🏰 Bringing Your Realm Online 🏰${NC}\n" +} + +show_step(){ + local step="$1" total="$2" message="$3" + echo -e "${YELLOW}πŸ”§ Step ${step}/${total}: ${message}...${NC}" +} + +show_realm_ready(){ + echo -e "\n${GREEN}βš”οΈ The realm has been forged! βš”οΈ${NC}" + echo -e "${GREEN}🏰 Adventurers may now enter your world${NC}" + echo -e "${GREEN}πŸ—‘οΈ May your server bring epic adventures!${NC}\n" +} + usage(){ cat </dev/null 2>&1; then + echo "βœ… Playerbots database ready" + else + echo "⚠️ Failed to guarantee playerbots database" + fi +} + +update_playerbots_conf(){ + local target="$1" + if [ ! -f "$target" ]; then + return 0 + fi + if sed -i "s|^PlayerbotsDatabaseInfo *=.*|PlayerbotsDatabaseInfo = \"${MYSQL_HOST};${MYSQL_PORT};${MYSQL_USER};${MYSQL_ROOT_PASSWORD};${DB_PLAYERBOTS_NAME}\"|" "$target"; then + echo " πŸ” Updated $(basename "$target")" + else + echo " ⚠️ Could not update $(basename "$target")" + fi + return 0 +} + # Create install markers directory mkdir -p /install-markers @@ -31,6 +63,7 @@ else for i in $(seq 1 120); do if mysql -h "${MYSQL_HOST}" -u"${MYSQL_USER}" -p"${MYSQL_ROOT_PASSWORD}" --skip-ssl-verify -e "SELECT 1;" >/dev/null 2>&1; then echo "βœ… MySQL is ready" + ensure_playerbots_db break fi echo " ⏳ Attempt $i/120..." @@ -62,6 +95,10 @@ else sed -i "s|^LoginDatabaseInfo *=.*|LoginDatabaseInfo = \"${MYSQL_HOST};${MYSQL_PORT};${MYSQL_USER};${MYSQL_ROOT_PASSWORD};${DB_AUTH_NAME}\"|" /azerothcore/config/worldserver.conf || true sed -i "s|^WorldDatabaseInfo *=.*|WorldDatabaseInfo = \"${MYSQL_HOST};${MYSQL_PORT};${MYSQL_USER};${MYSQL_ROOT_PASSWORD};${DB_WORLD_NAME}\"|" /azerothcore/config/worldserver.conf || true sed -i "s|^CharacterDatabaseInfo *=.*|CharacterDatabaseInfo = \"${MYSQL_HOST};${MYSQL_PORT};${MYSQL_USER};${MYSQL_ROOT_PASSWORD};${DB_CHARACTERS_NAME}\"|" /azerothcore/config/worldserver.conf || true + update_playerbots_conf /azerothcore/config/playerbots.conf + update_playerbots_conf /azerothcore/config/playerbots.conf.dist + update_playerbots_conf /azerothcore/config/modules/playerbots.conf + update_playerbots_conf /azerothcore/config/modules/playerbots.conf.dist echo "βœ… Configuration files updated" @@ -84,7 +121,9 @@ else echo "REALMLIST_UPDATED=true" >> /install-markers/post-install-completed echo "" - echo "πŸŽ‰ Auto post-install configuration completed successfully!" + echo -e "${GREEN}βš”οΈ Your realm has been blessed and configured! βš”οΈ${NC}" + echo -e "${GREEN}🏰 All post-installation rituals completed${NC}" + echo -e "${GREEN}πŸ—‘οΈ Your realm awaits brave adventurers!${NC}" echo "" tail -f /dev/null fi diff --git a/scripts/deploy-tools.sh b/scripts/deploy-tools.sh new file mode 100755 index 0000000..ec1db8f --- /dev/null +++ b/scripts/deploy-tools.sh @@ -0,0 +1,116 @@ +#!/bin/bash + +# ac-compose helper to deploy phpMyAdmin and Keira3 tooling. + +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/.." +COMPOSE_FILE="$ROOT_DIR/compose.yml" +ENV_FILE="$ROOT_DIR/.env" + +BLUE='\033[0;34m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +RED='\033[0;31m' +NC='\033[0m' + +info(){ echo -e "${BLUE}ℹ️ $*${NC}"; } +ok(){ echo -e "${GREEN}βœ… $*${NC}"; } +warn(){ echo -e "${YELLOW}⚠️ $*${NC}"; } +err(){ echo -e "${RED}❌ $*${NC}"; } + +read_env(){ + local key="$1" default="${2:-}" value="" + if [ -f "$ENV_FILE" ]; then + value="$(grep -E "^${key}=" "$ENV_FILE" 2>/dev/null | tail -n1 | cut -d'=' -f2- | tr -d '\r')" + fi + if [ -z "$value" ]; then + value="$default" + fi + echo "$value" +} + +resolve_project_name(){ + local raw_name sanitized + raw_name="$(read_env COMPOSE_PROJECT_NAME "acore-compose")" + sanitized="$(echo "$raw_name" | tr '[:upper:]' '[:lower:]')" + sanitized="${sanitized// /-}" + sanitized="$(echo "$sanitized" | tr -cd 'a-z0-9_-')" + if [[ -z "$sanitized" ]]; then + sanitized="acore-compose" + elif [[ ! "$sanitized" =~ ^[a-z0-9] ]]; then + sanitized="ac${sanitized}" + fi + echo "$sanitized" +} + +compose(){ + docker compose --project-name "$PROJECT_NAME" -f "$COMPOSE_FILE" "$@" +} + +show_header(){ + echo -e "\n${BLUE} πŸ› οΈ TOOLING DEPLOYMENT πŸ› οΈ${NC}" + echo -e "${BLUE} ═══════════════════════════${NC}" + echo -e "${BLUE} πŸ“Š Enabling Management UIs πŸ“Š${NC}\n" +} + +ensure_command(){ + if ! command -v "$1" >/dev/null 2>&1; then + err "Required command '$1' not found in PATH." + exit 1 + fi +} + +ensure_mysql_running(){ + local mysql_service="ac-mysql" + local mysql_container + mysql_container="$(read_env CONTAINER_MYSQL "ac-mysql")" + if docker ps --format '{{.Names}}' | grep -qx "$mysql_container"; then + info "MySQL container '$mysql_container' already running." + return + fi + info "Starting database service '$mysql_service'..." + compose --profile db up -d "$mysql_service" >/dev/null + ok "Database service ready." +} + +start_tools(){ + info "Starting phpMyAdmin and Keira3..." + compose --profile tools up --detach --quiet-pull >/dev/null + ok "Tooling services are online." +} + +show_endpoints(){ + local pma_port keira_port + pma_port="$(read_env PMA_EXTERNAL_PORT 8081)" + keira_port="$(read_env KEIRA3_EXTERNAL_PORT 4201)" + echo "" + echo -e "${GREEN}Accessible endpoints:${NC}" + echo " β€’ phpMyAdmin : http://localhost:${pma_port}" + echo " β€’ Keira3 : http://localhost:${keira_port}" + echo "" +} + +main(){ + if [[ "${1:-}" == "--help" ]]; then + cat </dev/null 2>&1 || { err "Docker daemon unavailable."; exit 1; } + + PROJECT_NAME="$(resolve_project_name)" + + show_header + ensure_mysql_running + start_tools + show_endpoints +} + +main "$@" diff --git a/scripts/manage-modules-sql.sh b/scripts/manage-modules-sql.sh index 859ff2e..fe01f53 100755 --- a/scripts/manage-modules-sql.sh +++ b/scripts/manage-modules-sql.sh @@ -6,9 +6,44 @@ set -e execute_module_sql() { local module_dir="$1" local module_name="$2" + local playerbots_db="${DB_PLAYERBOTS_NAME:-acore_playerbots}" + local character_set="${MYSQL_CHARACTER_SET:-utf8mb4}" + local collation="${MYSQL_COLLATION:-utf8mb4_unicode_ci}" + local run_sorted_sql + + run_sorted_sql() { + local dir="$1" + local target_db="$2" + local label="$3" + local skip_regex="${4:-}" + [ -d "$dir" ] || return + LC_ALL=C find "$dir" -type f -name "*.sql" | sort | while read -r sql_file; do + local base_name + base_name="$(basename "$sql_file")" + if [ -n "$skip_regex" ] && [[ "$base_name" =~ $skip_regex ]]; then + echo " Skipping ${label}: ${base_name}" + continue + fi + echo " Executing ${label}: ${base_name}" + if mariadb --ssl=false -h "${CONTAINER_MYSQL}" -P 3306 -u root -p"${MYSQL_ROOT_PASSWORD}" "${target_db}" < "$sql_file" >/dev/null 2>&1; then + echo " βœ… Successfully executed ${base_name}" + else + echo " ❌ Failed to execute $sql_file" + fi + done + } echo "Processing SQL scripts for $module_name..." + if [ "$module_name" = "Playerbots" ]; then + echo " Ensuring database ${playerbots_db} exists..." + if mariadb --ssl=false -h "${CONTAINER_MYSQL}" -P 3306 -u root -p"${MYSQL_ROOT_PASSWORD}" -e "CREATE DATABASE IF NOT EXISTS \`${playerbots_db}\` CHARACTER SET ${character_set} COLLATE ${collation};" >/dev/null 2>&1; then + echo " βœ… Playerbots database ready" + else + echo " ❌ Failed to ensure playerbots database" + fi + fi + # Find and execute SQL files in the module if [ -d "$module_dir/data/sql" ]; then # Execute world database scripts @@ -47,6 +82,16 @@ execute_module_sql() { done fi + # Execute playerbots database scripts + if [ "$module_name" = "Playerbots" ] && [ -d "$module_dir/data/sql/playerbots" ]; then + local pb_root="$module_dir/data/sql/playerbots" + run_sorted_sql "$pb_root/base" "$playerbots_db" "playerbots SQL" + run_sorted_sql "$pb_root/custom" "$playerbots_db" "playerbots SQL" + run_sorted_sql "$pb_root/updates" "$playerbots_db" "playerbots SQL" + run_sorted_sql "$pb_root/archive" "$playerbots_db" "playerbots SQL" + echo " Skipping playerbots create scripts (handled by automation)" + 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")" diff --git a/scripts/rebuild-with-modules.sh b/scripts/rebuild-with-modules.sh index df10ba7..de33e1b 100755 --- a/scripts/rebuild-with-modules.sh +++ b/scripts/rebuild-with-modules.sh @@ -8,6 +8,16 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_DIR="$(dirname "$SCRIPT_DIR")" ENV_FILE="$PROJECT_DIR/.env" +BLUE='\033[0;34m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' + +show_rebuild_step(){ + local step="$1" total="$2" message="$3" + echo -e "${YELLOW}πŸ”§ Step ${step}/${total}: ${message}...${NC}" +} + usage(){ cat </dev/null || true if command -v rsync >/dev/null 2>&1; then - rsync -a --delete "$MODULES_DIR"/ modules/ + rsync -a "$MODULES_DIR"/ modules/ else - rm -rf modules/* cp -R "$MODULES_DIR"/. modules/ fi else @@ -183,12 +185,32 @@ fi echo "πŸš€ Building AzerothCore with modules..." docker compose build --no-cache +show_rebuild_step 5 5 "Cleaning up build containers" echo "🧹 Cleaning up source build containers..." docker compose down --remove-orphans >/dev/null 2>&1 || true popd >/dev/null -rm -f "$SENTINEL_FILE" 2>/dev/null || true +if [ -n "$SENTINEL_FILE" ]; then + if ! rm -f "$SENTINEL_FILE" 2>/dev/null; then + if [ -f "$SENTINEL_FILE" ] && command -v docker >/dev/null 2>&1; then + DB_IMPORT_IMAGE="$(read_env AC_DB_IMPORT_IMAGE "acore/ac-wotlk-db-import:14.0.0-dev")" + if docker image inspect "$DB_IMPORT_IMAGE" >/dev/null 2>&1; then + docker run --rm \ + --entrypoint /bin/sh \ + --user 0:0 \ + -v "$MODULES_DIR":/modules \ + "$DB_IMPORT_IMAGE" \ + -c 'rm -f /modules/.requires_rebuild' >/dev/null 2>&1 || true + fi + fi + fi + if [ -f "$SENTINEL_FILE" ]; then + echo "⚠️ Unable to remove rebuild sentinel at $SENTINEL_FILE. Remove manually if rebuild detection persists." + fi +fi echo "" -echo "πŸŽ‰ SUCCESS! AzerothCore source build completed with modules." +echo -e "${GREEN}βš”οΈ Module build forged successfully! βš”οΈ${NC}" +echo -e "${GREEN}🏰 Your custom AzerothCore images are ready${NC}" +echo -e "${GREEN}πŸ—‘οΈ Time to stage your enhanced realm!${NC}" diff --git a/scripts/stage-modules.sh b/scripts/stage-modules.sh index ef7a12b..3d29ca9 100755 --- a/scripts/stage-modules.sh +++ b/scripts/stage-modules.sh @@ -4,6 +4,19 @@ set -e +BLUE='\033[0;34m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m' + +show_staging_header(){ + echo -e "\n${BLUE} βš”οΈ REALM STAGING SYSTEM βš”οΈ${NC}" + echo -e "${BLUE} ══════════════════════════════${NC}" + echo -e "${BLUE} 🎯 Configuring Your Realm 🎯${NC}\n" +} + +show_staging_step(){ + local step="$1" message="$2" + echo -e "${YELLOW}πŸ”§ ${step}: ${message}...${NC}" +} + SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_DIR="$(dirname "$SCRIPT_DIR")" ENV_FILE="$PROJECT_DIR/.env" @@ -117,6 +130,8 @@ declare -A MODULE_REPO_MAP=( [MODULE_LEVEL_GRANT]=mod-quest-count-level ) +show_staging_header + # Check for enabled C++ modules that require compilation compile_modules=() for key in "${!MODULE_REPO_MAP[@]}"; do @@ -131,7 +146,8 @@ MODULE_PLAYERBOTS="$(read_env MODULE_PLAYERBOTS "0")" # Determine target profile if not specified if [ -z "$TARGET_PROFILE" ]; then - if [ ${#compile_modules[@]} -gt 0 ]; then + show_staging_step "Profile Detection" "Analyzing enabled modules" +if [ ${#compile_modules[@]} -gt 0 ]; then echo "πŸ”§ Detected ${#compile_modules[@]} C++ modules requiring compilation:" for mod in "${compile_modules[@]}"; do echo " β€’ $mod" @@ -165,6 +181,7 @@ if [ "$TARGET_PROFILE" = "modules" ]; then fi if [ "$REBUILD_NEEDED" = "1" ]; then + show_staging_step "Source Rebuild" "Preparing custom build with modules" echo "πŸš€ Triggering source rebuild with modules..." if confirm "Proceed with source rebuild? (15-45 minutes)" n; then "$SCRIPT_DIR/rebuild-with-modules.sh" ${ASSUME_YES:+--yes} @@ -178,6 +195,7 @@ if [ "$TARGET_PROFILE" = "modules" ]; then fi # Stage the services +show_staging_step "Service Orchestration" "Preparing realm services" echo "🎬 Staging services with profile: services-$TARGET_PROFILE" # Stop any currently running services @@ -199,11 +217,14 @@ case "$TARGET_PROFILE" in esac # Start the target profile +show_staging_step "Realm Activation" "Bringing services online" echo "🟒 Starting services-$TARGET_PROFILE profile..." docker compose "${PROFILE_ARGS[@]}" up -d echo "" -echo "πŸŽ‰ SUCCESS! AzerothCore staged with profile: services-$TARGET_PROFILE" +echo -e "${GREEN}βš”οΈ Realm staging completed successfully! βš”οΈ${NC}" +echo -e "${GREEN}🏰 Profile: services-$TARGET_PROFILE${NC}" +echo -e "${GREEN}πŸ—‘οΈ Your realm is ready for adventure!${NC}" # Show status echo "" diff --git a/setup.sh b/setup.sh index 5aa1cb9..52424ba 100755 --- a/setup.sh +++ b/setup.sh @@ -36,6 +36,18 @@ ask_yn(){ local p="$1"; local d="$2"; local v; while true; do if [ "$d" = "y" ]; then read -p "$(echo -e "${YELLOW}πŸ”§ ${p} [Y/n]: ${NC}")" v; v=${v:-y}; else read -p "$(echo -e "${YELLOW}πŸ”§ ${p} [y/N]: ${NC}")" v; v=${v:-n}; fi case "$v" in [Yy]*) echo 1; return 0;; [Nn]*) echo 0; return 0;; esac; say ERROR "Please answer y or n"; done; } +show_wow_header(){ + echo -e "\n${BLUE} βš”οΈ AZEROTHCORE DEPLOYMENT SYSTEM βš”οΈ${NC}" + echo -e "${BLUE} ═══════════════════════════════════════${NC}" + echo -e "${BLUE} 🏰 Build Your Own WoW Server 🏰${NC}\n" +} + +show_realm_configured(){ + echo -e "\n${GREEN}βš”οΈ Your realm configuration has been forged! βš”οΈ${NC}" + echo -e "${GREEN}🏰 Ready to deploy your World of Warcraft server${NC}" + echo -e "${GREEN}πŸ—‘οΈ May your realm bring epic adventures!${NC}\n" +} + main(){ # Basic arg handling for help if [[ $# -gt 0 ]]; then @@ -63,14 +75,14 @@ EOF ;; esac fi - say HEADER "AZEROTHCORE PROFILES SETUP (.env generator)" + show_wow_header say INFO "This will create ac-compose/.env for compose profiles." # Deployment type say HEADER "DEPLOYMENT TYPE" - echo "1) Local Development (127.0.0.1, local storage)" - echo "2) LAN Server (local network IP)" - echo "3) Public Server (domain or public IP)" + echo "1) 🏠 Local Development (127.0.0.1, local storage)" + echo "2) 🌐 LAN Server (local network IP)" + echo "3) ☁️ Public Server (domain or public IP)" local DEPLOYMENT_TYPE while true; do read -p "$(echo -e "${YELLOW}πŸ”§ Select deployment type [1-3]: ${NC}")" x @@ -84,9 +96,9 @@ EOF # Permission scheme say HEADER "PERMISSION SCHEME" - echo "1) Local Dev (0:0)" - echo "2) NFS Server (1001:1000)" - echo "3) Custom" + echo "1) 🏠 Local Dev (0:0)" + echo "2) πŸ—‚οΈ NFS Server (1001:1000)" + echo "3) βš™οΈ Custom" local CONTAINER_USER while true; do read -p "$(echo -e "${YELLOW}πŸ”§ Select permission scheme [1-3]: ${NC}")" x @@ -126,9 +138,9 @@ EOF if [ "$DEPLOYMENT_TYPE" = "local" ]; then STORAGE_PATH=./storage else - echo "1) ./storage (local)" - echo "2) /nfs/azerothcore (NFS)" - echo "3) Custom" + echo "1) πŸ’Ύ ./storage (local)" + echo "2) 🌐 /nfs/azerothcore (NFS)" + echo "3) πŸ“ Custom" while true; do read -p "$(echo -e "${YELLOW}πŸ”§ Select storage option [1-3]: ${NC}")" s case "$s" in @@ -149,10 +161,10 @@ EOF # Module config say HEADER "MODULE PRESET" - echo "1) Suggested Modules" - echo "2) Playerbots + Suggested modules" - echo "3) Manual selection" - echo "4) No modules" + echo "1) ⭐ Suggested Modules" + echo "2) πŸ€– Playerbots + Suggested modules" + echo "3) βš™οΈ Manual selection" + echo "4) 🚫 No modules" local MODE; while true; do read -p "$(echo -e "${YELLOW}πŸ”§ Select module configuration [1-4]: ${NC}")" MODE case "$MODE" in 1|2|3|4) break;; *) say ERROR "Please select 1, 2, 3, or 4";; esac @@ -254,12 +266,8 @@ EOF AUTO_REBUILD_ON_DEPLOY=$(ask_yn "Enable automatic rebuild during future deploys?" n) if [ "$RUN_REBUILD_NOW" = "1" ] || [ "$AUTO_REBUILD_ON_DEPLOY" = "1" ]; then if [ -z "$MODULES_REBUILD_SOURCE_PATH_VALUE" ]; then - read -p "$(echo -e "${YELLOW}πŸ”§ Path to AzerothCore source compose (optional): ${NC}")" MODULES_REBUILD_SOURCE_PATH_VALUE - fi - if [ -z "$MODULES_REBUILD_SOURCE_PATH_VALUE" ]; then - say WARNING "No source path provided; skipping rebuild automation." - RUN_REBUILD_NOW=0 - AUTO_REBUILD_ON_DEPLOY=0 + MODULES_REBUILD_SOURCE_PATH_VALUE="./source/azerothcore" + say INFO "Using default source path: ${MODULES_REBUILD_SOURCE_PATH_VALUE}" fi fi fi @@ -271,6 +279,12 @@ EOF local cont; cont=$(ask_yn "Continue and overwrite?" n); [ "$cont" = "1" ] || { say ERROR "Aborted"; exit 1; } fi + if [ -z "$MODULES_REBUILD_SOURCE_PATH_VALUE" ]; then + MODULES_REBUILD_SOURCE_PATH_VALUE="./source/azerothcore" + fi + + DB_PLAYERBOTS_NAME=${DB_PLAYERBOTS_NAME:-acore_playerbots} + cat > "$ENV_OUT" </dev/null || echo "")" + if [ -z "$started_fmt" ]; then + started_fmt="$(echo "$started" | cut -c12-19)" + fi + [ -z "$started_fmt" ] && started_fmt="--:--:--" + else + started_fmt="--:--:--" + fi case "$status" in running) - local desc="running" colour="$GREEN" + local desc="running (since $started_fmt)" colour="$GREEN" if [ "$health" = "healthy" ]; then - desc="healthy" + desc="healthy (since $started_fmt)" elif [ "$health" = "none" ]; then - desc="running" + desc="running (since $started_fmt)" else - desc="$health"; colour="$YELLOW" + desc="$health (since $started_fmt)"; colour="$YELLOW" [ "$health" = "unhealthy" ] && colour="$RED" fi - echo -e "${colour}●${NC} ${desc} (since ${started%:*})" + echo "${colour}|● ${desc}" ;; exited) local colour="$YELLOW" [ "$exit_code" != "0" ] && colour="$RED" - echo -e "${colour}β—‹${NC} completed" + echo "${colour}|β—‹ exited (code $exit_code)" ;; restarting) - echo -e "${YELLOW}●${NC} restarting" + echo "${YELLOW}|● restarting" ;; created) - echo -e "${CYAN}β—‹${NC} created" + echo "${CYAN}|β—‹ created" ;; *) - echo -e "${RED}β—‹${NC} $status" + echo "${RED}|β—‹ $status" ;; esac } @@ -131,12 +141,16 @@ print_service(){ started="$(docker inspect --format='{{.State.StartedAt}}' "$container" 2>/dev/null | cut -c12-19 2>/dev/null || echo "--:--:--")" exit_code="$(docker inspect --format='{{.State.ExitCode}}' "$container" 2>/dev/null || echo "?")" image="$(docker inspect --format='{{.Config.Image}}' "$container" 2>/dev/null || echo "-")" - printf "%-20s %-28s %s\n" "$label" "$(format_state "$status" "$health" "$started" "$exit_code")" "$(short_image "$image")" + local state_info colour text + state_info="$(format_state "$status" "$health" "$started" "$exit_code")" + colour="${state_info%%|*}" + text="${state_info#*|}" + printf "%-20s %b%-30s%b %s\n" "$label" "$colour" "$text" "$NC" "$(short_image "$image")" if [ "$SHOW_LOGS" = true ]; then docker logs "$container" --tail "$LOG_LINES" 2>/dev/null | sed 's/^/ /' || printf " (no logs available)\n" fi else - printf "%-20s ${RED}β—‹${NC} missing -\n" "$label" + printf "%-20s %b%-30s%b %s\n" "$label" "$RED" "β—‹ missing" "$NC" "-" fi } @@ -166,9 +180,15 @@ module_summary(){ fi if container_running "ac-worldserver"; then - local ws_image="$(docker inspect --format='{{.Config.Image}}' ac-worldserver 2>/dev/null || echo "")" local playerbot="disabled" - [[ "$ws_image" == *playerbots* ]] && playerbot="running" + local module_playerbots + module_playerbots="$(read_env MODULE_PLAYERBOTS 0)" + if [ "$module_playerbots" = "1" ]; then + playerbot="enabled" + if docker inspect --format='{{.State.Status}}' ac-worldserver 2>/dev/null | grep -q "running"; then + playerbot="running" + fi + fi local eluna="disabled" [ "$ELUNA_ENABLED" = "1" ] && eluna="running" echo "RUNTIME: playerbots $playerbot | eluna $eluna" @@ -198,9 +218,15 @@ network_summary(){ fi } +show_realm_status_header(){ + echo -e "${BLUE}🏰 REALM STATUS DASHBOARD 🏰${NC}" + echo -e "${BLUE}═══════════════════════════${NC}" +} + print_status(){ clear 2>/dev/null || printf '\033[2J\033[H' - printf "TIME %s PROJECT %s\n\n" "$(date '+%Y-%m-%d %H:%M:%S')" "$PROJECT_NAME" + show_realm_status_header + printf "\nTIME %s PROJECT %s\n\n" "$(date '+%Y-%m-%d %H:%M:%S')" "$PROJECT_NAME" printf "%-20s %-28s %s\n" "SERVICE" "STATE" "IMAGE" printf "%-20s %-28s %s\n" "--------------------" "----------------------------" "------------------------------" print_service ac-mysql "MySQL"