mirror of
https://github.com/uprightbass360/AzerothCore-RealmMaster.git
synced 2026-01-13 00:58:34 +00:00
Refactor module staging to use manifest/env defaults and tag build images from .env
This commit is contained in:
@@ -57,6 +57,12 @@ AC_WORLDSERVER_IMAGE_MODULES=acore-compose:worldserver-modules-latest
|
||||
# Client Data
|
||||
AC_CLIENT_DATA_IMAGE=acore/ac-wotlk-client-data:14.0.0-dev
|
||||
AC_CLIENT_DATA_IMAGE_PLAYERBOTS=uprightbass360/azerothcore-wotlk-playerbots:client-data-Playerbot
|
||||
# Build artifacts
|
||||
DOCKER_IMAGE_TAG=master
|
||||
AC_AUTHSERVER_IMAGE_BASE=acore/ac-wotlk-authserver
|
||||
AC_WORLDSERVER_IMAGE_BASE=acore/ac-wotlk-worldserver
|
||||
AC_DB_IMPORT_IMAGE_BASE=acore/ac-wotlk-db-import
|
||||
AC_CLIENT_DATA_IMAGE_BASE=acore/ac-wotlk-client-data
|
||||
# Helper images
|
||||
ALPINE_GIT_IMAGE=alpine/git:latest
|
||||
ALPINE_IMAGE=alpine:latest
|
||||
|
||||
@@ -591,61 +591,10 @@ services:
|
||||
- ${STORAGE_PATH}/config:/azerothcore/env/dist/etc
|
||||
- ./scripts:/tmp/scripts:ro
|
||||
- ./config:/tmp/config:ro
|
||||
env_file:
|
||||
- ./.env
|
||||
environment:
|
||||
- MODULES_MANIFEST_PATH=/tmp/config/modules.json
|
||||
- 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}
|
||||
- MODULE_AHBOT=${MODULE_AHBOT}
|
||||
- MODULE_AUTOBALANCE=${MODULE_AUTOBALANCE}
|
||||
- MODULE_TRANSMOG=${MODULE_TRANSMOG}
|
||||
- MODULE_NPC_BUFFER=${MODULE_NPC_BUFFER}
|
||||
- MODULE_DYNAMIC_XP=${MODULE_DYNAMIC_XP}
|
||||
- MODULE_SOLO_LFG=${MODULE_SOLO_LFG}
|
||||
- MODULE_1V1_ARENA=${MODULE_1V1_ARENA}
|
||||
- MODULE_PHASED_DUELS=${MODULE_PHASED_DUELS}
|
||||
- MODULE_BREAKING_NEWS=${MODULE_BREAKING_NEWS}
|
||||
- MODULE_BOSS_ANNOUNCER=${MODULE_BOSS_ANNOUNCER}
|
||||
- MODULE_ACCOUNT_ACHIEVEMENTS=${MODULE_ACCOUNT_ACHIEVEMENTS}
|
||||
- MODULE_AUTO_REVIVE=${MODULE_AUTO_REVIVE}
|
||||
- MODULE_GAIN_HONOR_GUARD=${MODULE_GAIN_HONOR_GUARD}
|
||||
- MODULE_ELUNA=${MODULE_ELUNA}
|
||||
- MODULE_ARAC=${MODULE_ARAC}
|
||||
- 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}
|
||||
- MODULE_ASSISTANT=${MODULE_ASSISTANT}
|
||||
- MODULE_REAGENT_BANK=${MODULE_REAGENT_BANK}
|
||||
- MODULE_BLACK_MARKET_AUCTION_HOUSE=${MODULE_BLACK_MARKET_AUCTION_HOUSE}
|
||||
- MODULE_CHALLENGE_MODES=${MODULE_CHALLENGE_MODES}
|
||||
- MODULE_OLLAMA_CHAT=${MODULE_OLLAMA_CHAT}
|
||||
- MODULE_PLAYER_BOT_LEVEL_BRACKETS=${MODULE_PLAYER_BOT_LEVEL_BRACKETS}
|
||||
- MODULE_STATBOOSTER=${MODULE_STATBOOSTER}
|
||||
- MODULE_DUNGEON_RESPAWN=${MODULE_DUNGEON_RESPAWN}
|
||||
- MODULE_SKELETON_MODULE=${MODULE_SKELETON_MODULE}
|
||||
- MODULE_BG_SLAVERYVALLEY=${MODULE_BG_SLAVERYVALLEY}
|
||||
- MODULE_AZEROTHSHARD=${MODULE_AZEROTHSHARD}
|
||||
- MODULE_WORGOBLIN=${MODULE_WORGOBLIN}
|
||||
- MODULE_ELUNA_TS=${MODULE_ELUNA_TS}
|
||||
- CONTAINER_MYSQL=${CONTAINER_MYSQL}
|
||||
- MYSQL_PORT=${MYSQL_PORT}
|
||||
- MYSQL_USER=${MYSQL_USER}
|
||||
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
|
||||
- DB_AUTH_NAME=${DB_AUTH_NAME}
|
||||
- DB_WORLD_NAME=${DB_WORLD_NAME}
|
||||
- DB_CHARACTERS_NAME=${DB_CHARACTERS_NAME}
|
||||
- DB_PLAYERBOTS_NAME=${DB_PLAYERBOTS_NAME}
|
||||
- MYSQL_CHARACTER_SET=${MYSQL_CHARACTER_SET}
|
||||
- MYSQL_COLLATION=${MYSQL_COLLATION}
|
||||
- CONTAINER_USER=${CONTAINER_USER}
|
||||
MODULES_MANIFEST_PATH: /tmp/config/modules.json
|
||||
entrypoint: ["/bin/sh"]
|
||||
command:
|
||||
- -c
|
||||
|
||||
@@ -119,7 +119,11 @@ run_post_install_hooks(){
|
||||
[ -n "$hooks_csv" ] || return 0
|
||||
|
||||
IFS=',' read -r -a hooks <<< "$hooks_csv"
|
||||
local hooks_dir="/tmp/scripts/hooks"
|
||||
local -a hook_search_paths=(
|
||||
"$SCRIPT_DIR/hooks"
|
||||
"/tmp/scripts/hooks"
|
||||
"/scripts/hooks"
|
||||
)
|
||||
|
||||
for hook in "${hooks[@]}"; do
|
||||
[ -n "$hook" ] || continue
|
||||
@@ -127,9 +131,16 @@ run_post_install_hooks(){
|
||||
# Trim whitespace
|
||||
hook="$(echo "$hook" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')"
|
||||
|
||||
local hook_script="$hooks_dir/$hook"
|
||||
local hook_script=""
|
||||
local candidate
|
||||
for candidate in "${hook_search_paths[@]}"; do
|
||||
if [ -x "$candidate/$hook" ]; then
|
||||
hook_script="$candidate/$hook"
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -x "$hook_script" ]; then
|
||||
if [ -n "$hook_script" ]; then
|
||||
info "Running post-install hook: $hook"
|
||||
|
||||
# Set hook environment variables
|
||||
@@ -153,7 +164,7 @@ run_post_install_hooks(){
|
||||
# Clean up environment
|
||||
unset MODULE_KEY MODULE_DIR MODULE_NAME MODULES_ROOT LUA_SCRIPTS_TARGET
|
||||
else
|
||||
err "Hook script not found: $hook_script"
|
||||
err "Hook script not found for ${hook} (searched: ${hook_search_paths[*]})"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
@@ -355,69 +355,97 @@ get_template_value() {
|
||||
fi
|
||||
}
|
||||
|
||||
strip_tag(){
|
||||
local image="$1"
|
||||
if [[ "$image" == *:* ]]; then
|
||||
echo "${image%:*}"
|
||||
else
|
||||
echo "$image"
|
||||
fi
|
||||
}
|
||||
|
||||
tag_if_exists(){
|
||||
local source_image="$1"
|
||||
local target_image="$2"
|
||||
local description="$3"
|
||||
if [ -z "$source_image" ] || [ -z "$target_image" ]; then
|
||||
return 1
|
||||
fi
|
||||
if docker image inspect "$source_image" >/dev/null 2>&1; then
|
||||
if docker tag "$source_image" "$target_image"; then
|
||||
echo "✅ Tagged ${description}: $target_image (from $source_image)"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
echo "⚠️ Warning: unable to tag ${description} from $source_image"
|
||||
return 1
|
||||
}
|
||||
|
||||
SOURCE_IMAGE_TAG="$(read_env DOCKER_IMAGE_TAG "$(get_template_value "DOCKER_IMAGE_TAG" "master")")"
|
||||
[ -z "$SOURCE_IMAGE_TAG" ] && SOURCE_IMAGE_TAG="master"
|
||||
|
||||
AUTHSERVER_BASE_REPO="$(strip_tag "$(read_env AC_AUTHSERVER_IMAGE_BASE "$(get_template_value "AC_AUTHSERVER_IMAGE_BASE" "acore/ac-wotlk-authserver")")")"
|
||||
WORLDSERVER_BASE_REPO="$(strip_tag "$(read_env AC_WORLDSERVER_IMAGE_BASE "$(get_template_value "AC_WORLDSERVER_IMAGE_BASE" "acore/ac-wotlk-worldserver")")")"
|
||||
DB_IMPORT_BASE_REPO="$(strip_tag "$(read_env AC_DB_IMPORT_IMAGE_BASE "$(get_template_value "AC_DB_IMPORT_IMAGE_BASE" "acore/ac-wotlk-db-import")")")"
|
||||
CLIENT_DATA_BASE_REPO="$(strip_tag "$(read_env AC_CLIENT_DATA_IMAGE_BASE "$(get_template_value "AC_CLIENT_DATA_IMAGE_BASE" "acore/ac-wotlk-client-data")")")"
|
||||
|
||||
BUILT_AUTHSERVER_IMAGE="$AUTHSERVER_BASE_REPO:$SOURCE_IMAGE_TAG"
|
||||
BUILT_WORLDSERVER_IMAGE="$WORLDSERVER_BASE_REPO:$SOURCE_IMAGE_TAG"
|
||||
BUILT_DB_IMPORT_IMAGE="$DB_IMPORT_BASE_REPO:$SOURCE_IMAGE_TAG"
|
||||
BUILT_CLIENT_DATA_IMAGE="$CLIENT_DATA_BASE_REPO:$SOURCE_IMAGE_TAG"
|
||||
|
||||
TARGET_AUTHSERVER_IMAGE="$(read_env AC_AUTHSERVER_IMAGE_MODULES "$(get_template_value "AC_AUTHSERVER_IMAGE_MODULES")")"
|
||||
TARGET_WORLDSERVER_IMAGE="$(read_env AC_WORLDSERVER_IMAGE_MODULES "$(get_template_value "AC_WORLDSERVER_IMAGE_MODULES")")"
|
||||
PLAYERBOTS_AUTHSERVER_IMAGE="$(read_env AC_AUTHSERVER_IMAGE_PLAYERBOTS "$(get_template_value "AC_AUTHSERVER_IMAGE_PLAYERBOTS")")"
|
||||
PLAYERBOTS_WORLDSERVER_IMAGE="$(read_env AC_WORLDSERVER_IMAGE_PLAYERBOTS "$(get_template_value "AC_WORLDSERVER_IMAGE_PLAYERBOTS")")"
|
||||
|
||||
[ -z "$TARGET_AUTHSERVER_IMAGE" ] && TARGET_AUTHSERVER_IMAGE="$(resolve_project_image "authserver-modules-latest")"
|
||||
[ -z "$TARGET_WORLDSERVER_IMAGE" ] && TARGET_WORLDSERVER_IMAGE="$(resolve_project_image "worldserver-modules-latest")"
|
||||
[ -z "$PLAYERBOTS_AUTHSERVER_IMAGE" ] && PLAYERBOTS_AUTHSERVER_IMAGE="$(resolve_project_image "authserver-playerbots")"
|
||||
[ -z "$PLAYERBOTS_WORLDSERVER_IMAGE" ] && PLAYERBOTS_WORLDSERVER_IMAGE="$(resolve_project_image "worldserver-playerbots")"
|
||||
|
||||
PLAYERBOTS_AUTHSERVER_IMAGE="$(ensure_project_image_tag "authserver-Playerbot" "$(resolve_project_image "authserver-playerbots")")"
|
||||
if [ -z "$PLAYERBOTS_AUTHSERVER_IMAGE" ]; then
|
||||
echo "⚠️ Warning: unable to ensure project tag for authserver playerbots image"
|
||||
else
|
||||
update_env_value "AC_AUTHSERVER_IMAGE_PLAYERBOTS" "$PLAYERBOTS_AUTHSERVER_IMAGE"
|
||||
if [ -z "$TARGET_AUTHSERVER_IMAGE" ]; then
|
||||
echo "❌ AC_AUTHSERVER_IMAGE_MODULES is not defined in .env"
|
||||
exit 1
|
||||
fi
|
||||
if [ -z "$TARGET_WORLDSERVER_IMAGE" ]; then
|
||||
echo "❌ AC_WORLDSERVER_IMAGE_MODULES is not defined in .env"
|
||||
exit 1
|
||||
fi
|
||||
if [ -z "$PLAYERBOTS_AUTHSERVER_IMAGE" ]; then
|
||||
echo "❌ AC_AUTHSERVER_IMAGE_PLAYERBOTS is not defined in .env"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
PLAYERBOTS_WORLDSERVER_IMAGE="$(ensure_project_image_tag "worldserver-Playerbot" "$(resolve_project_image "worldserver-playerbots")")"
|
||||
if [ -z "$PLAYERBOTS_WORLDSERVER_IMAGE" ]; then
|
||||
echo "⚠️ Warning: unable to ensure project tag for worldserver playerbots image"
|
||||
else
|
||||
update_env_value "AC_WORLDSERVER_IMAGE_PLAYERBOTS" "$PLAYERBOTS_WORLDSERVER_IMAGE"
|
||||
echo "❌ AC_WORLDSERVER_IMAGE_PLAYERBOTS is not defined in .env"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "🔁 Tagging modules images from playerbot build artifacts"
|
||||
if [ -n "$PLAYERBOTS_AUTHSERVER_IMAGE" ] && docker image inspect "$PLAYERBOTS_AUTHSERVER_IMAGE" >/dev/null 2>&1; then
|
||||
if docker tag "$PLAYERBOTS_AUTHSERVER_IMAGE" "$TARGET_AUTHSERVER_IMAGE"; then
|
||||
echo "✅ Tagged $TARGET_AUTHSERVER_IMAGE from $PLAYERBOTS_AUTHSERVER_IMAGE"
|
||||
update_env_value "AC_AUTHSERVER_IMAGE_PLAYERBOTS" "$PLAYERBOTS_AUTHSERVER_IMAGE"
|
||||
update_env_value "AC_AUTHSERVER_IMAGE_MODULES" "$TARGET_AUTHSERVER_IMAGE"
|
||||
else
|
||||
echo "⚠️ Failed to tag $TARGET_AUTHSERVER_IMAGE from $PLAYERBOTS_AUTHSERVER_IMAGE"
|
||||
fi
|
||||
else
|
||||
echo "⚠️ Warning: unable to locate project-tagged authserver playerbots image"
|
||||
if tag_if_exists "$BUILT_AUTHSERVER_IMAGE" "$PLAYERBOTS_AUTHSERVER_IMAGE" "playerbots authserver"; then
|
||||
update_env_value "AC_AUTHSERVER_IMAGE_PLAYERBOTS" "$PLAYERBOTS_AUTHSERVER_IMAGE"
|
||||
fi
|
||||
if tag_if_exists "$BUILT_WORLDSERVER_IMAGE" "$PLAYERBOTS_WORLDSERVER_IMAGE" "playerbots worldserver"; then
|
||||
update_env_value "AC_WORLDSERVER_IMAGE_PLAYERBOTS" "$PLAYERBOTS_WORLDSERVER_IMAGE"
|
||||
fi
|
||||
if tag_if_exists "$BUILT_AUTHSERVER_IMAGE" "$TARGET_AUTHSERVER_IMAGE" "modules authserver"; then
|
||||
update_env_value "AC_AUTHSERVER_IMAGE_MODULES" "$TARGET_AUTHSERVER_IMAGE"
|
||||
fi
|
||||
if tag_if_exists "$BUILT_WORLDSERVER_IMAGE" "$TARGET_WORLDSERVER_IMAGE" "modules worldserver"; then
|
||||
update_env_value "AC_WORLDSERVER_IMAGE_MODULES" "$TARGET_WORLDSERVER_IMAGE"
|
||||
fi
|
||||
|
||||
if [ -n "$PLAYERBOTS_WORLDSERVER_IMAGE" ] && docker image inspect "$PLAYERBOTS_WORLDSERVER_IMAGE" >/dev/null 2>&1; then
|
||||
if docker tag "$PLAYERBOTS_WORLDSERVER_IMAGE" "$TARGET_WORLDSERVER_IMAGE"; then
|
||||
echo "✅ Tagged $TARGET_WORLDSERVER_IMAGE from $PLAYERBOTS_WORLDSERVER_IMAGE"
|
||||
update_env_value "AC_WORLDSERVER_IMAGE_PLAYERBOTS" "$PLAYERBOTS_WORLDSERVER_IMAGE"
|
||||
update_env_value "AC_WORLDSERVER_IMAGE_MODULES" "$TARGET_WORLDSERVER_IMAGE"
|
||||
else
|
||||
echo "⚠️ Failed to tag $TARGET_WORLDSERVER_IMAGE from $PLAYERBOTS_WORLDSERVER_IMAGE"
|
||||
fi
|
||||
else
|
||||
echo "⚠️ Warning: unable to locate project-tagged worldserver playerbots image"
|
||||
TARGET_DB_IMPORT_IMAGE="$(read_env AC_DB_IMPORT_IMAGE "$(get_template_value "AC_DB_IMPORT_IMAGE")")"
|
||||
if [ -z "$TARGET_DB_IMPORT_IMAGE" ]; then
|
||||
echo "❌ AC_DB_IMPORT_IMAGE is not defined in .env"
|
||||
exit 1
|
||||
fi
|
||||
if tag_if_exists "$BUILT_DB_IMPORT_IMAGE" "$TARGET_DB_IMPORT_IMAGE" "playerbots db-import"; then
|
||||
update_env_value "AC_DB_IMPORT_IMAGE" "$TARGET_DB_IMPORT_IMAGE"
|
||||
fi
|
||||
|
||||
TARGET_DB_IMPORT_IMAGE="$(resolve_project_image "db-import-playerbots")"
|
||||
DB_IMPORT_IMAGE="$(ensure_project_image_tag "db-import-Playerbot" "$TARGET_DB_IMPORT_IMAGE")"
|
||||
if [ -n "$DB_IMPORT_IMAGE" ]; then
|
||||
update_env_value "AC_DB_IMPORT_IMAGE" "$DB_IMPORT_IMAGE"
|
||||
else
|
||||
echo "⚠️ Warning: unable to ensure project tag for db-import image"
|
||||
TARGET_CLIENT_DATA_IMAGE="$(read_env AC_CLIENT_DATA_IMAGE_PLAYERBOTS "$(get_template_value "AC_CLIENT_DATA_IMAGE_PLAYERBOTS")")"
|
||||
if [ -z "$TARGET_CLIENT_DATA_IMAGE" ]; then
|
||||
echo "❌ AC_CLIENT_DATA_IMAGE_PLAYERBOTS is not defined in .env"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
TARGET_CLIENT_DATA_IMAGE="$(resolve_project_image "client-data-playerbots")"
|
||||
CLIENT_DATA_IMAGE="$(ensure_project_image_tag "client-data-Playerbot" "$TARGET_CLIENT_DATA_IMAGE")"
|
||||
if [ -n "$CLIENT_DATA_IMAGE" ]; then
|
||||
update_env_value "AC_CLIENT_DATA_IMAGE_PLAYERBOTS" "$CLIENT_DATA_IMAGE"
|
||||
else
|
||||
echo "⚠️ Warning: unable to ensure project tag for client-data image"
|
||||
if tag_if_exists "$BUILT_CLIENT_DATA_IMAGE" "$TARGET_CLIENT_DATA_IMAGE" "playerbots client-data"; then
|
||||
update_env_value "AC_CLIENT_DATA_IMAGE_PLAYERBOTS" "$TARGET_CLIENT_DATA_IMAGE"
|
||||
fi
|
||||
|
||||
show_rebuild_step 5 5 "Cleaning up build containers"
|
||||
|
||||
484
setup.sh
484
setup.sh
@@ -88,6 +88,11 @@ declare -A TEMPLATE_VALUE_MAP=(
|
||||
[DEFAULT_AC_AUTHSERVER_IMAGE]=AC_AUTHSERVER_IMAGE
|
||||
[DEFAULT_AC_WORLDSERVER_IMAGE]=AC_WORLDSERVER_IMAGE
|
||||
[DEFAULT_AC_CLIENT_DATA_IMAGE]=AC_CLIENT_DATA_IMAGE
|
||||
[DEFAULT_DOCKER_IMAGE_TAG]=DOCKER_IMAGE_TAG
|
||||
[DEFAULT_AUTHSERVER_IMAGE_BASE]=AC_AUTHSERVER_IMAGE_BASE
|
||||
[DEFAULT_WORLDSERVER_IMAGE_BASE]=AC_WORLDSERVER_IMAGE_BASE
|
||||
[DEFAULT_DB_IMPORT_IMAGE_BASE]=AC_DB_IMPORT_IMAGE_BASE
|
||||
[DEFAULT_CLIENT_DATA_IMAGE_BASE]=AC_CLIENT_DATA_IMAGE_BASE
|
||||
[DEFAULT_AUTH_IMAGE_PLAYERBOTS]=AC_AUTHSERVER_IMAGE_PLAYERBOTS
|
||||
[DEFAULT_WORLD_IMAGE_PLAYERBOTS]=AC_WORLDSERVER_IMAGE_PLAYERBOTS
|
||||
[DEFAULT_CLIENT_DATA_IMAGE_PLAYERBOTS]=AC_CLIENT_DATA_IMAGE_PLAYERBOTS
|
||||
@@ -278,60 +283,15 @@ normalize_module_name(){
|
||||
|
||||
declare -A MODULE_ENABLE_SET=()
|
||||
|
||||
KNOWN_MODULE_VARS=(
|
||||
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_ARAC
|
||||
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
|
||||
MODULE_CHALLENGE_MODES
|
||||
MODULE_OLLAMA_CHAT
|
||||
MODULE_SKELETON_MODULE
|
||||
MODULE_BG_SLAVERYVALLEY
|
||||
MODULE_ELUNA_TS
|
||||
MODULE_PLAYER_BOT_LEVEL_BRACKETS
|
||||
MODULE_STATBOOSTER
|
||||
MODULE_DUNGEON_RESPAWN
|
||||
MODULE_AZEROTHSHARD
|
||||
MODULE_WORGOBLIN
|
||||
MODULE_ASSISTANT
|
||||
MODULE_REAGENT_BANK
|
||||
MODULE_BLACK_MARKET_AUCTION_HOUSE
|
||||
)
|
||||
|
||||
declare -A KNOWN_MODULE_LOOKUP=()
|
||||
for __mod in "${KNOWN_MODULE_VARS[@]}"; do
|
||||
KNOWN_MODULE_LOOKUP["$__mod"]=1
|
||||
done
|
||||
unset __mod
|
||||
|
||||
module_default(){
|
||||
local key="$1"
|
||||
if [ "${MODULE_ENABLE_SET[$key]}" = "1" ]; then
|
||||
if [ "${MODULE_ENABLE_SET[$key]:-0}" = "1" ]; then
|
||||
echo y
|
||||
return
|
||||
fi
|
||||
local current
|
||||
eval "current=\${$key:-${MODULE_DEFAULT_VALUES[$key]:-0}}"
|
||||
if [ "$current" = "1" ]; then
|
||||
echo y
|
||||
else
|
||||
echo n
|
||||
@@ -345,7 +305,7 @@ apply_module_preset(){
|
||||
local mod="${item//[[:space:]]/}"
|
||||
[ -z "$mod" ] && continue
|
||||
if [ -n "${KNOWN_MODULE_LOOKUP[$mod]:-}" ]; then
|
||||
eval "$mod=1"
|
||||
printf -v "$mod" '%s' "1"
|
||||
else
|
||||
say WARNING "Preset references unknown module $mod"
|
||||
fi
|
||||
@@ -383,6 +343,204 @@ EOF
|
||||
echo -e "${NC}"
|
||||
}
|
||||
|
||||
# ==============================
|
||||
# Module metadata / defaults
|
||||
# ==============================
|
||||
|
||||
MODULE_MANIFEST_PATH="$SCRIPT_DIR/config/modules.json"
|
||||
ENV_TEMPLATE_FILE="$SCRIPT_DIR/.env.template"
|
||||
|
||||
declare -a MODULE_KEYS=()
|
||||
declare -a MODULE_KEYS_SORTED=()
|
||||
declare -A MODULE_NAME_MAP=()
|
||||
declare -A MODULE_TYPE_MAP=()
|
||||
declare -A MODULE_STATUS_MAP=()
|
||||
declare -A MODULE_BLOCK_REASON_MAP=()
|
||||
declare -A MODULE_NEEDS_BUILD_MAP=()
|
||||
declare -A MODULE_REQUIRES_MAP=()
|
||||
declare -A MODULE_NOTES_MAP=()
|
||||
declare -A MODULE_DEFAULT_VALUES=()
|
||||
declare -A KNOWN_MODULE_LOOKUP=()
|
||||
declare -A ENV_TEMPLATE_VALUES=()
|
||||
MODULE_METADATA_INITIALIZED=0
|
||||
|
||||
load_env_template_values() {
|
||||
local template_file="$ENV_TEMPLATE_FILE"
|
||||
if [ ! -f "$template_file" ]; then
|
||||
echo "ERROR: .env.template file not found at $template_file" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
while IFS= read -r raw_line || [ -n "$raw_line" ]; do
|
||||
local line="${raw_line%%#*}"
|
||||
line="${line%%$'\r'}"
|
||||
line="$(echo "$line" | sed 's/[[:space:]]*$//')"
|
||||
[ -n "$line" ] || continue
|
||||
[[ "$line" == *=* ]] || continue
|
||||
local key="${line%%=*}"
|
||||
local value="${line#*=}"
|
||||
key="$(echo "$key" | sed 's/[[:space:]]//g')"
|
||||
value="$(echo "$value" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
|
||||
[ -n "$key" ] || continue
|
||||
ENV_TEMPLATE_VALUES["$key"]="$value"
|
||||
done < "$template_file"
|
||||
}
|
||||
|
||||
load_module_manifest_metadata() {
|
||||
if [ ! -f "$MODULE_MANIFEST_PATH" ]; then
|
||||
echo "ERROR: Module manifest not found at $MODULE_MANIFEST_PATH" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! command -v python3 >/dev/null 2>&1; then
|
||||
echo "ERROR: python3 is required to read $MODULE_MANIFEST_PATH" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mapfile -t MODULE_KEYS < <(
|
||||
python3 - "$MODULE_MANIFEST_PATH" <<'PY'
|
||||
import json, sys
|
||||
from pathlib import Path
|
||||
|
||||
manifest_path = Path(sys.argv[1])
|
||||
manifest = json.loads(manifest_path.read_text())
|
||||
modules = manifest.get("modules", [])
|
||||
for entry in modules:
|
||||
key = entry.get("key")
|
||||
if not key:
|
||||
continue
|
||||
print(key)
|
||||
PY
|
||||
)
|
||||
|
||||
if [ ${#MODULE_KEYS[@]} -eq 0 ]; then
|
||||
echo "ERROR: No modules defined in manifest $MODULE_MANIFEST_PATH" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
while IFS=$'\t' read -r key name needs_build module_type status block_reason requires notes; do
|
||||
[ -n "$key" ] || continue
|
||||
MODULE_NAME_MAP["$key"]="$name"
|
||||
MODULE_NEEDS_BUILD_MAP["$key"]="$needs_build"
|
||||
MODULE_TYPE_MAP["$key"]="$module_type"
|
||||
MODULE_STATUS_MAP["$key"]="$status"
|
||||
MODULE_BLOCK_REASON_MAP["$key"]="$block_reason"
|
||||
MODULE_REQUIRES_MAP["$key"]="$requires"
|
||||
MODULE_NOTES_MAP["$key"]="$notes"
|
||||
KNOWN_MODULE_LOOKUP["$key"]=1
|
||||
done < <(
|
||||
python3 - "$MODULE_MANIFEST_PATH" <<'PY'
|
||||
import json, sys
|
||||
from pathlib import Path
|
||||
|
||||
manifest_path = Path(sys.argv[1])
|
||||
manifest = json.loads(manifest_path.read_text())
|
||||
|
||||
def clean(value):
|
||||
if value is None:
|
||||
return ""
|
||||
return str(value).replace("\t", " ").replace("\n", " ").strip()
|
||||
|
||||
for entry in manifest.get("modules", []):
|
||||
key = entry.get("key")
|
||||
if not key:
|
||||
continue
|
||||
name = clean(entry.get("name", key))
|
||||
needs_build = "1" if entry.get("needs_build") else "0"
|
||||
module_type = clean(entry.get("type", ""))
|
||||
status = clean(entry.get("status", "active"))
|
||||
block_reason = clean(entry.get("block_reason", ""))
|
||||
requires = entry.get("requires") or []
|
||||
depends_on = entry.get("depends_on") or []
|
||||
ordered = []
|
||||
for dep in list(requires) + list(depends_on):
|
||||
if dep and dep not in ordered:
|
||||
ordered.append(dep)
|
||||
requires_csv = ",".join(ordered)
|
||||
notes = clean(entry.get("notes", ""))
|
||||
print("\t".join([key, name, needs_build, module_type, status or "active", block_reason, requires_csv, notes]))
|
||||
PY
|
||||
)
|
||||
|
||||
mapfile -t MODULE_KEYS_SORTED < <(
|
||||
python3 - "$MODULE_MANIFEST_PATH" <<'PY'
|
||||
import json, sys
|
||||
from pathlib import Path
|
||||
|
||||
manifest_path = Path(sys.argv[1])
|
||||
manifest = json.loads(manifest_path.read_text())
|
||||
modules = manifest.get("modules", [])
|
||||
sorted_keys = sorted(modules, key=lambda m: (str(m.get("type", "")), str(m.get("name", m.get("key"))).lower()))
|
||||
for entry in sorted_keys:
|
||||
key = entry.get("key")
|
||||
if key:
|
||||
print(key)
|
||||
PY
|
||||
)
|
||||
}
|
||||
|
||||
initialize_module_defaults() {
|
||||
if [ "$MODULE_METADATA_INITIALIZED" = "1" ]; then
|
||||
return
|
||||
fi
|
||||
load_env_template_values
|
||||
load_module_manifest_metadata
|
||||
|
||||
for key in "${MODULE_KEYS[@]}"; do
|
||||
if [ -z "${ENV_TEMPLATE_VALUES[$key]+_}" ]; then
|
||||
echo "ERROR: .env.template missing default value for ${key}" >&2
|
||||
exit 1
|
||||
fi
|
||||
local default="${ENV_TEMPLATE_VALUES[$key]}"
|
||||
MODULE_DEFAULT_VALUES["$key"]="$default"
|
||||
printf -v "$key" '%s' "$default"
|
||||
done
|
||||
MODULE_METADATA_INITIALIZED=1
|
||||
}
|
||||
|
||||
reset_modules_to_defaults() {
|
||||
for key in "${MODULE_KEYS[@]}"; do
|
||||
printf -v "$key" '%s' "${MODULE_DEFAULT_VALUES[$key]}"
|
||||
done
|
||||
}
|
||||
|
||||
module_display_name() {
|
||||
local key="$1"
|
||||
local name="${MODULE_NAME_MAP[$key]:-$key}"
|
||||
local note="${MODULE_NOTES_MAP[$key]}"
|
||||
if [ -n "$note" ]; then
|
||||
echo "${name} - ${note}"
|
||||
else
|
||||
echo "$name"
|
||||
fi
|
||||
}
|
||||
|
||||
auto_enable_module_dependencies() {
|
||||
local changed=1
|
||||
while [ "$changed" -eq 1 ]; do
|
||||
changed=0
|
||||
for key in "${MODULE_KEYS[@]}"; do
|
||||
local enabled
|
||||
eval "enabled=\${$key:-0}"
|
||||
[ "$enabled" = "1" ] || continue
|
||||
local requires_csv="${MODULE_REQUIRES_MAP[$key]}"
|
||||
IFS=',' read -r -a deps <<< "${requires_csv}"
|
||||
for dep in "${deps[@]}"; do
|
||||
dep="${dep//[[:space:]]/}"
|
||||
[ -n "$dep" ] || continue
|
||||
[ -n "${KNOWN_MODULE_LOOKUP[$dep]:-}" ] || continue
|
||||
local dep_value
|
||||
eval "dep_value=\${$dep:-0}"
|
||||
if [ "$dep_value" != "1" ]; then
|
||||
say INFO "Automatically enabling ${dep#MODULE_} (required by ${key#MODULE_})."
|
||||
printf -v "$dep" '%s' "1"
|
||||
MODULE_ENABLE_SET["$dep"]=1
|
||||
changed=1
|
||||
fi
|
||||
done
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
show_realm_configured(){
|
||||
echo -e "\n${GREEN}⚔️ Your realm configuration has been forged! ⚔️${NC}"
|
||||
@@ -414,6 +572,9 @@ main(){
|
||||
local FORCE_OVERWRITE=0
|
||||
local CLI_ENABLE_MODULES_RAW=()
|
||||
|
||||
initialize_module_defaults
|
||||
reset_modules_to_defaults
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
-h|--help)
|
||||
@@ -707,8 +868,14 @@ fi
|
||||
|
||||
# Permission scheme
|
||||
say HEADER "PERMISSION SCHEME"
|
||||
local CURRENT_UID CURRENT_GID CURRENT_USER_PAIR CURRENT_USER_NAME CURRENT_GROUP_NAME
|
||||
CURRENT_UID="$(id -u 2>/dev/null || echo 1000)"
|
||||
CURRENT_GID="$(id -g 2>/dev/null || echo 1000)"
|
||||
CURRENT_USER_NAME="$(id -un 2>/dev/null || echo user)"
|
||||
CURRENT_GROUP_NAME="$(id -gn 2>/dev/null || echo users)"
|
||||
CURRENT_USER_PAIR="${CURRENT_UID}:${CURRENT_GID}"
|
||||
echo "1) 🏠 Local Root (0:0)"
|
||||
echo "2) 🗂️ User (1001:1000)"
|
||||
echo "2) 🗂️ Current User (${CURRENT_USER_NAME}:${CURRENT_GROUP_NAME} → ${CURRENT_USER_PAIR})"
|
||||
echo "3) ⚙️ Custom"
|
||||
local PERMISSION_SCHEME_INPUT="${CLI_PERMISSION_SCHEME}"
|
||||
local PERMISSION_SCHEME_NAME=""
|
||||
@@ -725,9 +892,9 @@ fi
|
||||
CONTAINER_USER="$PERMISSION_LOCAL_USER"
|
||||
PERMISSION_SCHEME_NAME="local"
|
||||
;;
|
||||
2|nfs)
|
||||
CONTAINER_USER="$PERMISSION_NFS_USER"
|
||||
PERMISSION_SCHEME_NAME="nfs"
|
||||
2|nfs|user)
|
||||
CONTAINER_USER="$CURRENT_USER_PAIR"
|
||||
PERMISSION_SCHEME_NAME="user"
|
||||
;;
|
||||
3|custom)
|
||||
local uid gid
|
||||
@@ -911,15 +1078,6 @@ fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Initialize toggles
|
||||
local MODULE_PLAYERBOTS=0 MODULE_AOE_LOOT=0 MODULE_LEARN_SPELLS=0 MODULE_FIREWORKS=0 MODULE_INDIVIDUAL_PROGRESSION=0 \
|
||||
MODULE_AHBOT=0 MODULE_AUTOBALANCE=0 MODULE_TRANSMOG=0 MODULE_NPC_BUFFER=0 MODULE_DYNAMIC_XP=0 MODULE_SOLO_LFG=0 \
|
||||
MODULE_1V1_ARENA=0 MODULE_PHASED_DUELS=0 MODULE_BREAKING_NEWS=0 MODULE_BOSS_ANNOUNCER=0 MODULE_ACCOUNT_ACHIEVEMENTS=0 \
|
||||
MODULE_AUTO_REVIVE=0 MODULE_GAIN_HONOR_GUARD=0 MODULE_TIME_IS_TIME=0 MODULE_POCKET_PORTAL=0 \
|
||||
MODULE_RANDOM_ENCHANTS=0 MODULE_SOLOCRAFT=0 MODULE_PVP_TITLES=0 MODULE_NPC_BEASTMASTER=0 MODULE_NPC_ENCHANTER=0 \
|
||||
MODULE_INSTANCE_RESET=0 MODULE_LEVEL_GRANT=0 MODULE_ASSISTANT=0 MODULE_REAGENT_BANK=0 MODULE_BLACK_MARKET_AUCTION_HOUSE=0 MODULE_ARAC=0 MODULE_ELUNA=0 \
|
||||
MODULE_CHALLENGE_MODES=0 MODULE_OLLAMA_CHAT=0 MODULE_SKELETON_MODULE=0 MODULE_BG_SLAVERYVALLEY=0 MODULE_ELUNA_TS=0 \
|
||||
MODULE_PLAYER_BOT_LEVEL_BRACKETS=0 MODULE_STATBOOSTER=0 MODULE_DUNGEON_RESPAWN=0 MODULE_AZEROTHSHARD=0 MODULE_WORGOBLIN=0
|
||||
local AC_AUTHSERVER_IMAGE_PLAYERBOTS_VALUE="$DEFAULT_AUTH_IMAGE_PLAYERBOTS"
|
||||
local AC_WORLDSERVER_IMAGE_PLAYERBOTS_VALUE="$DEFAULT_WORLD_IMAGE_PLAYERBOTS"
|
||||
local AC_AUTHSERVER_IMAGE_MODULES_VALUE="$DEFAULT_AUTH_IMAGE_MODULES"
|
||||
@@ -929,17 +1087,17 @@ fi
|
||||
|
||||
local mod_var
|
||||
for mod_var in "${!MODULE_ENABLE_SET[@]}"; do
|
||||
if [ -n "${KNOWN_MODULE_LOOKUP[$mod_var]}" ]; then
|
||||
eval "$mod_var=1"
|
||||
if [ -n "${KNOWN_MODULE_LOOKUP[$mod_var]:-}" ]; then
|
||||
printf -v "$mod_var" '%s' "1"
|
||||
fi
|
||||
done
|
||||
|
||||
if { [ "${MODULE_PLAYER_BOT_LEVEL_BRACKETS}" = "1" ] || [ "${MODULE_OLLAMA_CHAT}" = "1" ]; } && [ "$MODULE_PLAYERBOTS" != "1" ]; then
|
||||
auto_enable_module_dependencies
|
||||
|
||||
if [ "${MODULE_OLLAMA_CHAT:-0}" = "1" ] && [ "${MODULE_PLAYERBOTS:-0}" != "1" ]; then
|
||||
say INFO "Automatically enabling MODULE_PLAYERBOTS for MODULE_OLLAMA_CHAT."
|
||||
MODULE_PLAYERBOTS=1
|
||||
MODULE_ENABLE_SET["MODULE_PLAYERBOTS"]=1
|
||||
if [ ${#MODULE_ENABLE_SET[@]} -gt 0 ]; then
|
||||
say INFO "Automatically enabling MODULE_PLAYERBOTS to satisfy playerbot-dependent modules."
|
||||
fi
|
||||
fi
|
||||
|
||||
declare -A DISABLED_MODULE_REASONS=(
|
||||
@@ -968,55 +1126,40 @@ fi
|
||||
for key in "${!DISABLED_MODULE_REASONS[@]}"; do
|
||||
say WARNING "${key#MODULE_}: ${DISABLED_MODULE_REASONS[$key]}"
|
||||
done
|
||||
# Core Gameplay
|
||||
MODULE_PLAYERBOTS=$(ask_yn "Playerbots - AI companions" "$(module_default MODULE_PLAYERBOTS)")
|
||||
MODULE_PLAYER_BOT_LEVEL_BRACKETS=$(ask_yn "Playerbot Level Brackets - Evenly distribute bot levels" "$(module_default MODULE_PLAYER_BOT_LEVEL_BRACKETS)")
|
||||
MODULE_OLLAMA_CHAT=$(ask_yn "Ollama Chat - LLM dialogue for playerbots (requires external Ollama API)" "$(module_default MODULE_OLLAMA_CHAT)")
|
||||
MODULE_SOLO_LFG=$(ask_yn "Solo LFG - Solo dungeon finder" "$(module_default MODULE_SOLO_LFG)")
|
||||
MODULE_SOLOCRAFT=$(ask_yn "Solocraft - Scale dungeons/raids for solo" "$(module_default MODULE_SOLOCRAFT)")
|
||||
MODULE_CHALLENGE_MODES=$(ask_yn "Challenge Modes - Timed dungeon keystones" "$(module_default MODULE_CHALLENGE_MODES)")
|
||||
MODULE_AUTOBALANCE=$(ask_yn "Autobalance - Dynamic difficulty" "$(module_default MODULE_AUTOBALANCE)")
|
||||
# QoL
|
||||
MODULE_TRANSMOG=$(ask_yn "Transmog - Appearance changes" "$(module_default MODULE_TRANSMOG)")
|
||||
MODULE_NPC_BUFFER=$(ask_yn "NPC Buffer - Buff NPCs" "$(module_default MODULE_NPC_BUFFER)")
|
||||
MODULE_LEARN_SPELLS=$(ask_yn "Learn Spells - Auto-learn" "$(module_default MODULE_LEARN_SPELLS)")
|
||||
MODULE_AOE_LOOT=$(ask_yn "AOE Loot - Multi-corpse loot" "$(module_default MODULE_AOE_LOOT)")
|
||||
MODULE_FIREWORKS=$(ask_yn "Fireworks - Level-up FX" "$(module_default MODULE_FIREWORKS)")
|
||||
MODULE_ASSISTANT=$(ask_yn "Assistant - Multi-service NPC" "$(module_default MODULE_ASSISTANT)")
|
||||
MODULE_STATBOOSTER=$(ask_yn "Stat Booster - Random enchant upgrades" "$(module_default MODULE_STATBOOSTER)")
|
||||
MODULE_DUNGEON_RESPAWN=$(ask_yn "Dungeon Respawn - Return to entrance on death" "$(module_default MODULE_DUNGEON_RESPAWN)")
|
||||
MODULE_SKELETON_MODULE=$(ask_yn "Skeleton Module - Blank module template" "$(module_default MODULE_SKELETON_MODULE)")
|
||||
# Economy
|
||||
MODULE_AHBOT=$(ask_yn "AH Bot - Auction automation" "$(module_default MODULE_AHBOT)")
|
||||
MODULE_REAGENT_BANK=$(ask_yn "Reagent Bank - Materials storage" "$(module_default MODULE_REAGENT_BANK)")
|
||||
MODULE_BLACK_MARKET_AUCTION_HOUSE=$(ask_yn "Black Market - MoP-style" "$(module_default MODULE_BLACK_MARKET_AUCTION_HOUSE)")
|
||||
# PvP
|
||||
MODULE_1V1_ARENA=$(ask_yn "1v1 Arena - Solo arena queue system" "$(module_default MODULE_1V1_ARENA)")
|
||||
MODULE_PHASED_DUELS=$(ask_yn "Phased Duels - Isolated duel instances" "$(module_default MODULE_PHASED_DUELS)")
|
||||
MODULE_PVP_TITLES=$(ask_yn "PvP Titles - Classic honor rank titles" "$(module_default MODULE_PVP_TITLES)")
|
||||
MODULE_BG_SLAVERYVALLEY=$(ask_yn "Slavery Valley - Custom battleground" "$(module_default MODULE_BG_SLAVERYVALLEY)")
|
||||
# Progression
|
||||
MODULE_INDIVIDUAL_PROGRESSION=$(ask_yn "Individual Progression (Vanilla→TBC→WotLK)" "$(module_default MODULE_INDIVIDUAL_PROGRESSION)")
|
||||
MODULE_DYNAMIC_XP=$(ask_yn "Dynamic XP - Adaptive experience rates" "$(module_default MODULE_DYNAMIC_XP)")
|
||||
MODULE_ACCOUNT_ACHIEVEMENTS=$(ask_yn "Account Achievements - Share progress across characters" "$(module_default MODULE_ACCOUNT_ACHIEVEMENTS)")
|
||||
MODULE_AZEROTHSHARD=$(ask_yn "AzerothShard - Blended custom features" "$(module_default MODULE_AZEROTHSHARD)")
|
||||
# Server Features
|
||||
MODULE_BREAKING_NEWS=$(ask_yn "Breaking News - Server announcement system" "$(module_default MODULE_BREAKING_NEWS)")
|
||||
MODULE_BOSS_ANNOUNCER=$(ask_yn "Boss Announcer - Broadcast boss kills" "$(module_default MODULE_BOSS_ANNOUNCER)")
|
||||
MODULE_AUTO_REVIVE=$(ask_yn "Auto Revive - Automatic resurrection system" "$(module_default MODULE_AUTO_REVIVE)")
|
||||
MODULE_ELUNA_TS=$(ask_yn "Eluna TS - TypeScript toolchain for Lua" "$(module_default MODULE_ELUNA_TS)")
|
||||
# Utility
|
||||
MODULE_NPC_BEASTMASTER=$(ask_yn "NPC Beastmaster - Rare pet vendor" "$(module_default MODULE_NPC_BEASTMASTER)")
|
||||
MODULE_NPC_ENCHANTER=$(ask_yn "NPC Enchanter - Gear enchanting service" "$(module_default MODULE_NPC_ENCHANTER)")
|
||||
MODULE_RANDOM_ENCHANTS=$(ask_yn "Random Enchants - Suffix property system" "$(module_default MODULE_RANDOM_ENCHANTS)")
|
||||
MODULE_POCKET_PORTAL=$(ask_yn "Pocket Portal - Personal teleportation device" "$(module_default MODULE_POCKET_PORTAL)")
|
||||
MODULE_INSTANCE_RESET=$(ask_yn "Instance Reset - Dungeon lockout management" "$(module_default MODULE_INSTANCE_RESET)")
|
||||
MODULE_TIME_IS_TIME=$(ask_yn "Time is Time - Real-time clock system" "$(module_default MODULE_TIME_IS_TIME)")
|
||||
MODULE_GAIN_HONOR_GUARD=$(ask_yn "Gain Honor Guard - Honor from guard kills" "$(module_default MODULE_GAIN_HONOR_GUARD)")
|
||||
MODULE_ARAC=$(ask_yn "All Races All Classes (requires client patch)" "$(module_default MODULE_ARAC)")
|
||||
MODULE_WORGOBLIN=$(ask_yn "Worgoblin - Worgen & Goblin races (client patch required)" "$(module_default MODULE_WORGOBLIN)")
|
||||
local -a selection_keys=("${MODULE_KEYS_SORTED[@]}")
|
||||
if [ ${#selection_keys[@]} -eq 0 ]; then
|
||||
selection_keys=("${MODULE_KEYS[@]}")
|
||||
fi
|
||||
local key
|
||||
for key in "${selection_keys[@]}"; do
|
||||
[ -n "${KNOWN_MODULE_LOOKUP[$key]:-}" ] || continue
|
||||
local status_lc="${MODULE_STATUS_MAP[$key],,}"
|
||||
if [ -n "$status_lc" ] && [ "$status_lc" != "active" ]; then
|
||||
local reason="${MODULE_BLOCK_REASON_MAP[$key]:-Blocked in manifest}"
|
||||
say WARNING "${key#MODULE_} is blocked: ${reason}"
|
||||
printf -v "$key" '%s' "0"
|
||||
continue
|
||||
fi
|
||||
local prompt_label
|
||||
prompt_label="$(module_display_name "$key")"
|
||||
if [ "${MODULE_NEEDS_BUILD_MAP[$key]}" = "1" ]; then
|
||||
prompt_label="${prompt_label} (requires build)"
|
||||
fi
|
||||
local default_answer
|
||||
default_answer="$(module_default "$key")"
|
||||
local response
|
||||
response=$(ask_yn "$prompt_label" "$default_answer")
|
||||
if [ "$response" = "1" ]; then
|
||||
printf -v "$key" '%s' "1"
|
||||
else
|
||||
printf -v "$key" '%s' "0"
|
||||
fi
|
||||
done
|
||||
module_mode_label="preset 3 (Manual)"
|
||||
elif [ "$MODE_SELECTION" = "4" ]; then
|
||||
for key in "${MODULE_KEYS[@]}"; do
|
||||
printf -v "$key" '%s' "0"
|
||||
done
|
||||
module_mode_label="preset 4 (No modules)"
|
||||
elif [ "$MODE_SELECTION" = "preset" ]; then
|
||||
local preset_modules="${MODULE_PRESET_CONFIGS[$MODE_PRESET_NAME]}"
|
||||
@@ -1029,6 +1172,8 @@ fi
|
||||
module_mode_label="preset (${MODE_PRESET_NAME})"
|
||||
fi
|
||||
|
||||
auto_enable_module_dependencies
|
||||
|
||||
if [ -n "$CLI_PLAYERBOT_ENABLED" ]; then
|
||||
if [[ "$CLI_PLAYERBOT_ENABLED" != "0" && "$CLI_PLAYERBOT_ENABLED" != "1" ]]; then
|
||||
say ERROR "--playerbot-enabled must be 0 or 1"
|
||||
@@ -1051,11 +1196,13 @@ fi
|
||||
PLAYERBOT_MAX_BOTS=$(ask "Maximum concurrent playerbots" "${CLI_PLAYERBOT_MAX:-$DEFAULT_PLAYERBOT_MAX}" validate_number)
|
||||
fi
|
||||
|
||||
for mod_var in 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_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 MODULE_ARAC MODULE_ASSISTANT MODULE_REAGENT_BANK MODULE_BLACK_MARKET_AUCTION_HOUSE MODULE_PLAYER_BOT_LEVEL_BRACKETS MODULE_OLLAMA_CHAT MODULE_CHALLENGE_MODES MODULE_STATBOOSTER MODULE_DUNGEON_RESPAWN MODULE_SKELETON_MODULE MODULE_BG_SLAVERYVALLEY MODULE_AZEROTHSHARD MODULE_WORGOBLIN; do
|
||||
eval "value=\$$mod_var"
|
||||
if [ "$value" = "1" ]; then
|
||||
NEEDS_CXX_REBUILD=1
|
||||
break
|
||||
for mod_var in "${MODULE_KEYS[@]}"; do
|
||||
if [ "${MODULE_NEEDS_BUILD_MAP[$mod_var]}" = "1" ]; then
|
||||
eval "value=\${$mod_var:-0}"
|
||||
if [ "$value" = "1" ]; then
|
||||
NEEDS_CXX_REBUILD=1
|
||||
break
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
@@ -1080,8 +1227,8 @@ fi
|
||||
printf " %-18s %s\n" "Playerbot Max Bots:" "$PLAYERBOT_MAX_BOTS"
|
||||
printf " %-18s" "Enabled Modules:"
|
||||
local enabled_modules=()
|
||||
for module_var in "${KNOWN_MODULE_VARS[@]}"; do
|
||||
eval "value=\$$module_var"
|
||||
for module_var in "${MODULE_KEYS[@]}"; do
|
||||
eval "value=\${$module_var:-0}"
|
||||
if [ "$value" = "1" ]; then
|
||||
enabled_modules+=("${module_var#MODULE_}")
|
||||
fi
|
||||
@@ -1111,7 +1258,7 @@ fi
|
||||
|
||||
export STORAGE_PATH STORAGE_PATH_LOCAL
|
||||
local module_export_var
|
||||
for module_export_var in "${KNOWN_MODULE_VARS[@]}"; do
|
||||
for module_export_var in "${MODULE_KEYS[@]}"; do
|
||||
export "$module_export_var"
|
||||
done
|
||||
|
||||
@@ -1227,11 +1374,10 @@ COMPOSE_PROJECT_NAME=$DEFAULT_COMPOSE_PROJECT_NAME
|
||||
STORAGE_PATH=$STORAGE_PATH
|
||||
STORAGE_PATH_LOCAL=$LOCAL_STORAGE_ROOT
|
||||
BACKUP_PATH=$BACKUP_PATH
|
||||
HOST_ZONEINFO_PATH=${HOST_ZONEINFO_PATH:-$DEFAULT_HOST_ZONEINFO_PATH}
|
||||
TZ=$DEFAULT_TZ
|
||||
|
||||
# Database
|
||||
MYSQL_IMAGE=$DEFAULT_MYSQL_IMAGE
|
||||
CONTAINER_MYSQL=$DEFAULT_CONTAINER_MYSQL
|
||||
MYSQL_ROOT_PASSWORD=$MYSQL_ROOT_PASSWORD
|
||||
MYSQL_ROOT_HOST=$DEFAULT_MYSQL_ROOT_HOST
|
||||
MYSQL_USER=$DEFAULT_MYSQL_USER
|
||||
@@ -1267,7 +1413,18 @@ AC_CLIENT_DATA_IMAGE_PLAYERBOTS=$AC_CLIENT_DATA_IMAGE_PLAYERBOTS_VALUE
|
||||
CLIENT_DATA_CACHE_PATH=$DEFAULT_CLIENT_DATA_CACHE_PATH
|
||||
CLIENT_DATA_VOLUME=${CLIENT_DATA_VOLUME:-$DEFAULT_CLIENT_DATA_VOLUME}
|
||||
|
||||
# Build artifacts
|
||||
DOCKER_IMAGE_TAG=$DEFAULT_DOCKER_IMAGE_TAG
|
||||
AC_AUTHSERVER_IMAGE_BASE=$DEFAULT_AUTHSERVER_IMAGE_BASE
|
||||
AC_WORLDSERVER_IMAGE_BASE=$DEFAULT_WORLDSERVER_IMAGE_BASE
|
||||
AC_DB_IMPORT_IMAGE_BASE=$DEFAULT_DB_IMPORT_IMAGE_BASE
|
||||
AC_CLIENT_DATA_IMAGE_BASE=$DEFAULT_CLIENT_DATA_IMAGE_BASE
|
||||
|
||||
# Container user
|
||||
CONTAINER_USER=$CONTAINER_USER
|
||||
|
||||
# Containers
|
||||
CONTAINER_MYSQL=$DEFAULT_CONTAINER_MYSQL
|
||||
CONTAINER_DB_IMPORT=$DEFAULT_CONTAINER_DB_IMPORT
|
||||
CONTAINER_DB_INIT=$DEFAULT_CONTAINER_DB_INIT
|
||||
CONTAINER_BACKUP=$DEFAULT_CONTAINER_BACKUP
|
||||
@@ -1293,52 +1450,13 @@ BACKUP_DAILY_TIME=$BACKUP_DAILY_TIME
|
||||
BACKUP_HEALTHCHECK_MAX_MINUTES=$BACKUP_HEALTHCHECK_MAX_MINUTES
|
||||
BACKUP_HEALTHCHECK_GRACE_SECONDS=$BACKUP_HEALTHCHECK_GRACE_SECONDS
|
||||
|
||||
# Container user
|
||||
CONTAINER_USER=$CONTAINER_USER
|
||||
|
||||
# Modules
|
||||
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
|
||||
MODULE_AHBOT=$MODULE_AHBOT
|
||||
MODULE_AUTOBALANCE=$MODULE_AUTOBALANCE
|
||||
MODULE_TRANSMOG=$MODULE_TRANSMOG
|
||||
MODULE_NPC_BUFFER=$MODULE_NPC_BUFFER
|
||||
MODULE_DYNAMIC_XP=$MODULE_DYNAMIC_XP
|
||||
MODULE_SOLO_LFG=$MODULE_SOLO_LFG
|
||||
MODULE_1V1_ARENA=$MODULE_1V1_ARENA
|
||||
MODULE_PHASED_DUELS=$MODULE_PHASED_DUELS
|
||||
MODULE_BREAKING_NEWS=$MODULE_BREAKING_NEWS
|
||||
MODULE_BOSS_ANNOUNCER=$MODULE_BOSS_ANNOUNCER
|
||||
MODULE_ACCOUNT_ACHIEVEMENTS=$MODULE_ACCOUNT_ACHIEVEMENTS
|
||||
MODULE_AUTO_REVIVE=$MODULE_AUTO_REVIVE
|
||||
MODULE_GAIN_HONOR_GUARD=$MODULE_GAIN_HONOR_GUARD
|
||||
MODULE_ARAC=$MODULE_ARAC
|
||||
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
|
||||
MODULE_CHALLENGE_MODES=$MODULE_CHALLENGE_MODES
|
||||
MODULE_OLLAMA_CHAT=$MODULE_OLLAMA_CHAT
|
||||
MODULE_SKELETON_MODULE=$MODULE_SKELETON_MODULE
|
||||
MODULE_BG_SLAVERYVALLEY=$MODULE_BG_SLAVERYVALLEY
|
||||
MODULE_ELUNA_TS=$MODULE_ELUNA_TS
|
||||
MODULE_PLAYER_BOT_LEVEL_BRACKETS=$MODULE_PLAYER_BOT_LEVEL_BRACKETS
|
||||
MODULE_STATBOOSTER=$MODULE_STATBOOSTER
|
||||
MODULE_DUNGEON_RESPAWN=$MODULE_DUNGEON_RESPAWN
|
||||
MODULE_AZEROTHSHARD=$MODULE_AZEROTHSHARD
|
||||
MODULE_WORGOBLIN=$MODULE_WORGOBLIN
|
||||
MODULE_ASSISTANT=$MODULE_ASSISTANT
|
||||
MODULE_REAGENT_BANK=$MODULE_REAGENT_BANK
|
||||
MODULE_BLACK_MARKET_AUCTION_HOUSE=$MODULE_BLACK_MARKET_AUCTION_HOUSE
|
||||
EOF
|
||||
echo
|
||||
echo "# Modules"
|
||||
for module_key in "${MODULE_KEYS[@]}"; do
|
||||
printf "%s=%s\n" "$module_key" "${!module_key:-0}"
|
||||
done
|
||||
cat <<EOF
|
||||
|
||||
# Client data
|
||||
CLIENT_DATA_VERSION=${CLIENT_DATA_VERSION:-$DEFAULT_CLIENT_DATA_VERSION}
|
||||
@@ -1387,6 +1505,9 @@ NETWORK_NAME=$DEFAULT_NETWORK_NAME
|
||||
NETWORK_SUBNET=$DEFAULT_NETWORK_SUBNET
|
||||
NETWORK_GATEWAY=$DEFAULT_NETWORK_GATEWAY
|
||||
|
||||
# Storage helpers
|
||||
HOST_ZONEINFO_PATH=${HOST_ZONEINFO_PATH:-$DEFAULT_HOST_ZONEINFO_PATH}
|
||||
|
||||
# Helper images
|
||||
ALPINE_GIT_IMAGE=$DEFAULT_ALPINE_GIT_IMAGE
|
||||
ALPINE_IMAGE=$DEFAULT_ALPINE_IMAGE
|
||||
@@ -1398,19 +1519,8 @@ EOF
|
||||
local local_mysql_data_dir="${LOCAL_STORAGE_ROOT_ABS}/mysql-data"
|
||||
mkdir -p "$local_mysql_data_dir"
|
||||
|
||||
local -a MODULE_STATE_VARS=(
|
||||
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 MODULE_ARAC MODULE_ASSISTANT MODULE_REAGENT_BANK
|
||||
MODULE_BLACK_MARKET_AUCTION_HOUSE MODULE_CHALLENGE_MODES MODULE_OLLAMA_CHAT MODULE_PLAYER_BOT_LEVEL_BRACKETS
|
||||
MODULE_STATBOOSTER MODULE_DUNGEON_RESPAWN MODULE_SKELETON_MODULE MODULE_BG_SLAVERYVALLEY MODULE_AZEROTHSHARD
|
||||
MODULE_WORGOBLIN MODULE_ELUNA_TS
|
||||
)
|
||||
local module_state_string=""
|
||||
for module_state_var in "${MODULE_STATE_VARS[@]}"; do
|
||||
for module_state_var in "${MODULE_KEYS[@]}"; do
|
||||
local module_value="${!module_state_var:-0}"
|
||||
module_state_string+="${module_state_var}=${module_value}|"
|
||||
done
|
||||
|
||||
Reference in New Issue
Block a user