This commit is contained in:
uprightbass360
2025-11-05 00:31:49 -05:00
4 changed files with 198 additions and 37 deletions

View File

@@ -135,6 +135,7 @@ BACKUP_HEALTHCHECK_START_PERIOD=120s
# Playerbots runtime flags (used by worldserver env) # Playerbots runtime flags (used by worldserver env)
# ===================== # =====================
PLAYERBOT_ENABLED=0 PLAYERBOT_ENABLED=0
PLAYERBOT_MIN_BOTS=40
PLAYERBOT_MAX_BOTS=40 PLAYERBOT_MAX_BOTS=40
# ===================== # =====================

View File

@@ -140,8 +140,6 @@ 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|^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|^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 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
update_playerbots_conf /azerothcore/config/modules/playerbots.conf.dist update_playerbots_conf /azerothcore/config/modules/playerbots.conf.dist

View File

@@ -209,35 +209,158 @@ install_enabled_modules(){
update_playerbots_db_info(){ update_playerbots_db_info(){
local target="$1" local target="$1"
if [ ! -f "$target" ]; then if [ ! -f "$target" ] && [ ! -L "$target" ]; then
return 0 return 0
fi fi
local host local env_file="${ENV_PATH:-}"
host="$(read_env_value CONTAINER_MYSQL)" local resolved
if [ -z "$host" ]; then
host="$(read_env_value MYSQL_HOST)"
fi
host="${host:-ac-mysql}"
local port resolved="$(
port="$(read_env_value MYSQL_PORT "3306")" python3 - "$target" "${env_file}" <<'PY'
import os
import pathlib
import sys
import re
local user def load_env_file(path):
user="$(read_env_value MYSQL_USER "root")" data = {}
if not path:
return data
candidate = pathlib.Path(path)
if not candidate.is_file():
return data
for raw in candidate.read_text(encoding="utf-8", errors="ignore").splitlines():
if not raw or raw.lstrip().startswith("#"):
continue
if "=" not in raw:
continue
key, val = raw.split("=", 1)
key = key.strip()
val = val.strip()
if not key:
continue
if val and val[0] == val[-1] and val[0] in {"'", '"'}:
val = val[1:-1]
if "#" in val:
# Strip inline comments
val = val.split("#", 1)[0].rstrip()
data[key] = val
return data
local pass def resolve_key(env_map, key, default=""):
pass="$(read_env_value MYSQL_ROOT_PASSWORD)" value = os.environ.get(key)
if value:
return value
return env_map.get(key, default)
local db def parse_bool(value):
db="$(read_env_value DB_PLAYERBOTS_NAME "acore_playerbots")" if value is None:
local value="${host};${port};${user};${pass};${db}" return None
value = value.strip().lower()
if value == "":
return None
if value in {"1", "true", "yes", "on"}:
return True
if value in {"0", "false", "no", "off"}:
return False
return None
if grep -qE '^[[:space:]]*PlayerbotsDatabaseInfo[[:space:]]*=' "$target"; then def parse_int(value):
sed -i "s|^[[:space:]]*PlayerbotsDatabaseInfo[[:space:]]*=.*|PlayerbotsDatabaseInfo = \"${value}\"|" "$target" || return if value is None:
else return None
printf '\nPlayerbotsDatabaseInfo = "%s"\n' "$value" >> "$target" || return value = value.strip()
fi if not value:
return None
if re.fullmatch(r"[+-]?\d+", value):
return str(int(value))
return None
def update_config(path_in, settings):
if not (os.path.exists(path_in) or os.path.islink(path_in)):
return False
path = os.path.realpath(path_in)
try:
with open(path, "r", encoding="utf-8", errors="ignore") as fh:
lines = fh.read().splitlines()
except FileNotFoundError:
lines = []
changed = False
pending = dict(settings)
for idx, raw in enumerate(lines):
stripped = raw.strip()
for key, value in list(pending.items()):
if re.match(rf"^\s*{re.escape(key)}\s*=", stripped):
desired = f"{key} = {value}"
if stripped != desired:
leading = raw[: len(raw) - len(raw.lstrip())]
trailing = ""
if "#" in raw:
before, comment = raw.split("#", 1)
if before.strip():
trailing = f" # {comment.strip()}"
lines[idx] = f"{leading}{desired}{trailing}"
changed = True
pending.pop(key, None)
break
if pending:
if lines and lines[-1] and not lines[-1].endswith("\n"):
lines[-1] = lines[-1] + "\n"
if lines and lines[-1].strip():
lines.append("\n")
for key, value in pending.items():
lines.append(f"{key} = {value}\n")
changed = True
if changed:
output = "\n".join(lines)
if output and not output.endswith("\n"):
output += "\n"
with open(path, "w", encoding="utf-8") as fh:
fh.write(output)
return True
target_path, env_path = sys.argv[1:3]
env_map = load_env_file(env_path)
host = resolve_key(env_map, "CONTAINER_MYSQL") or resolve_key(env_map, "MYSQL_HOST", "ac-mysql") or "ac-mysql"
port = resolve_key(env_map, "MYSQL_PORT", "3306") or "3306"
user = resolve_key(env_map, "MYSQL_USER", "root") or "root"
password = resolve_key(env_map, "MYSQL_ROOT_PASSWORD", "")
database = resolve_key(env_map, "DB_PLAYERBOTS_NAME", "acore_playerbots") or "acore_playerbots"
value = ";".join([host, port, user, password, database])
settings = {"PlayerbotsDatabaseInfo": f'"{value}"'}
enabled_setting = parse_bool(resolve_key(env_map, "PLAYERBOT_ENABLED"))
if enabled_setting is not None:
settings["AiPlayerbot.Enabled"] = "1" if enabled_setting else "0"
max_bots = parse_int(resolve_key(env_map, "PLAYERBOT_MAX_BOTS"))
min_bots = parse_int(resolve_key(env_map, "PLAYERBOT_MIN_BOTS"))
if max_bots and not min_bots:
min_bots = max_bots
if min_bots:
settings["AiPlayerbot.MinRandomBots"] = min_bots
if max_bots:
settings["AiPlayerbot.MaxRandomBots"] = max_bots
update_config(target_path, settings)
print(value)
PY
)" || return 0
local host port
host="${resolved%%;*}"
port="${resolved#*;}"
port="${port%%;*}"
if [ "$PLAYERBOTS_DB_UPDATE_LOGGED" = "0" ]; then if [ "$PLAYERBOTS_DB_UPDATE_LOGGED" = "0" ]; then
info "Updated PlayerbotsDatabaseInfo to use host ${host}:${port}" info "Updated PlayerbotsDatabaseInfo to use host ${host}:${port}"
@@ -279,17 +402,12 @@ manage_configuration_files(){
unset patterns unset patterns
done done
local module_dir
for key in "${MODULE_KEYS[@]}"; do
module_dir="${MODULE_NAME[$key]:-}"
[ -n "$module_dir" ] || continue
[ -d "$module_dir" ] || continue
find "$module_dir" -name "*.conf.dist" -exec cp {} "$env_target"/ \; 2>/dev/null || true
done
local modules_conf_dir="${env_target%/}/modules" local modules_conf_dir="${env_target%/}/modules"
mkdir -p "$modules_conf_dir" mkdir -p "$modules_conf_dir"
rm -rf "${modules_conf_dir}.backup"
rm -f "$modules_conf_dir"/*.conf "$modules_conf_dir"/*.conf.dist 2>/dev/null || true rm -f "$modules_conf_dir"/*.conf "$modules_conf_dir"/*.conf.dist 2>/dev/null || true
local module_dir
for key in "${MODULE_KEYS[@]}"; do for key in "${MODULE_KEYS[@]}"; do
module_dir="${MODULE_NAME[$key]:-}" module_dir="${MODULE_NAME[$key]:-}"
[ -n "$module_dir" ] || continue [ -n "$module_dir" ] || continue
@@ -297,8 +415,26 @@ manage_configuration_files(){
while IFS= read -r conf_file; do while IFS= read -r conf_file; do
[ -n "$conf_file" ] || continue [ -n "$conf_file" ] || continue
base_name="$(basename "$conf_file")" base_name="$(basename "$conf_file")"
dest_name="${base_name%.dist}" # Ensure previous copies in root config are removed to keep modules/ canonical
cp "$conf_file" "$modules_conf_dir/$dest_name" main_conf_path="${env_target}/${base_name}"
if [ -f "$main_conf_path" ]; then
rm -f "$main_conf_path"
fi
if [[ "$base_name" == *.conf.dist ]]; then
root_conf="${env_target}/${base_name%.dist}"
if [ -f "$root_conf" ]; then
rm -f "$root_conf"
fi
fi
dest_path="${modules_conf_dir}/${base_name}"
cp "$conf_file" "$dest_path"
if [[ "$base_name" == *.conf.dist ]]; then
dest_conf="${modules_conf_dir}/${base_name%.dist}"
if [ ! -f "$dest_conf" ]; then
cp "$conf_file" "$dest_conf"
fi
fi
done < <(find "$module_dir" -path "*/conf/*" -type f \( -name "*.conf" -o -name "*.conf.dist" \) 2>/dev/null) done < <(find "$module_dir" -path "*/conf/*" -type f \( -name "*.conf" -o -name "*.conf.dist" \) 2>/dev/null)
done done
@@ -308,8 +444,6 @@ manage_configuration_files(){
fi fi
if [ "$playerbots_enabled" = "1" ]; then if [ "$playerbots_enabled" = "1" ]; then
update_playerbots_db_info "$env_target/playerbots.conf"
update_playerbots_db_info "$env_target/playerbots.conf.dist"
update_playerbots_db_info "$modules_conf_dir/playerbots.conf" update_playerbots_db_info "$modules_conf_dir/playerbots.conf"
update_playerbots_db_info "$modules_conf_dir/playerbots.conf.dist" update_playerbots_db_info "$modules_conf_dir/playerbots.conf.dist"
fi fi

View File

@@ -68,6 +68,7 @@ declare -A TEMPLATE_VALUE_MAP=(
[DEFAULT_AUTH_PORT]=AUTH_EXTERNAL_PORT [DEFAULT_AUTH_PORT]=AUTH_EXTERNAL_PORT
[DEFAULT_SOAP_PORT]=SOAP_EXTERNAL_PORT [DEFAULT_SOAP_PORT]=SOAP_EXTERNAL_PORT
[DEFAULT_MYSQL_PORT]=MYSQL_EXTERNAL_PORT [DEFAULT_MYSQL_PORT]=MYSQL_EXTERNAL_PORT
[DEFAULT_PLAYERBOT_MIN]=PLAYERBOT_MIN_BOTS
[DEFAULT_PLAYERBOT_MAX]=PLAYERBOT_MAX_BOTS [DEFAULT_PLAYERBOT_MAX]=PLAYERBOT_MAX_BOTS
[DEFAULT_LOCAL_STORAGE]=STORAGE_PATH [DEFAULT_LOCAL_STORAGE]=STORAGE_PATH
[DEFAULT_BACKUP_PATH]=BACKUP_PATH [DEFAULT_BACKUP_PATH]=BACKUP_PATH
@@ -577,6 +578,7 @@ main(){
local CLI_MODULE_MODE="" local CLI_MODULE_MODE=""
local CLI_MODULE_PRESET="" local CLI_MODULE_PRESET=""
local CLI_PLAYERBOT_ENABLED="" local CLI_PLAYERBOT_ENABLED=""
local CLI_PLAYERBOT_MIN=""
local CLI_PLAYERBOT_MAX="" local CLI_PLAYERBOT_MAX=""
local CLI_AUTO_REBUILD=0 local CLI_AUTO_REBUILD=0
local CLI_MODULES_SOURCE="" local CLI_MODULES_SOURCE=""
@@ -619,7 +621,8 @@ Options:
--module-config NAME Use preset NAME from profiles/<NAME>.conf --module-config NAME Use preset NAME from profiles/<NAME>.conf
--enable-modules LIST Comma-separated module list (MODULE_* or shorthand) --enable-modules LIST Comma-separated module list (MODULE_* or shorthand)
--playerbot-enabled 0|1 Override PLAYERBOT_ENABLED flag --playerbot-enabled 0|1 Override PLAYERBOT_ENABLED flag
--playerbot-max-bots N Override PLAYERBOT_MAX_BOTS value --playerbot-min-bots N Override PLAYERBOT_MIN_BOTS value
--playerbot-max-bots N Override PLAYERBOT_MAX_BOTS value
--auto-rebuild-on-deploy Enable automatic rebuild during deploys --auto-rebuild-on-deploy Enable automatic rebuild during deploys
--modules-rebuild-source PATH Source checkout used for module rebuilds --modules-rebuild-source PATH Source checkout used for module rebuilds
--deploy-after Run ./deploy.sh automatically after setup completes --deploy-after Run ./deploy.sh automatically after setup completes
@@ -759,6 +762,12 @@ EOF
;; ;;
--playerbot-max-bots) --playerbot-max-bots)
[[ $# -ge 2 ]] || { say ERROR "--playerbot-max-bots requires a value"; exit 1; } [[ $# -ge 2 ]] || { say ERROR "--playerbot-max-bots requires a value"; exit 1; }
CLI_PLAYERBOT_MIN="$2"; shift 2
;;
--playerbot-min-bots=*)
CLI_PLAYERBOT_MIN="${1#*=}"; shift
;;
--playerbot-max-bots)
CLI_PLAYERBOT_MAX="$2"; shift 2 CLI_PLAYERBOT_MAX="$2"; shift 2
;; ;;
--playerbot-max-bots=*) --playerbot-max-bots=*)
@@ -1116,7 +1125,9 @@ fi
[MODULE_LEVEL_GRANT]="QuestCountLevel module relies on removed ConfigMgr APIs and fails to build" [MODULE_LEVEL_GRANT]="QuestCountLevel module relies on removed ConfigMgr APIs and fails to build"
) )
local PLAYERBOT_ENABLED=0 PLAYERBOT_MAX_BOTS=40 local PLAYERBOT_ENABLED=0
local PLAYERBOT_MIN_BOTS="${DEFAULT_PLAYERBOT_MIN:-40}"
local PLAYERBOT_MAX_BOTS="${DEFAULT_PLAYERBOT_MAX:-40}"
local AUTO_REBUILD_ON_DEPLOY=$CLI_AUTO_REBUILD local AUTO_REBUILD_ON_DEPLOY=$CLI_AUTO_REBUILD
local MODULES_REBUILD_SOURCE_PATH_VALUE="${CLI_MODULES_SOURCE}" local MODULES_REBUILD_SOURCE_PATH_VALUE="${CLI_MODULES_SOURCE}"
@@ -1248,6 +1259,13 @@ fi
fi fi
PLAYERBOT_ENABLED="$CLI_PLAYERBOT_ENABLED" PLAYERBOT_ENABLED="$CLI_PLAYERBOT_ENABLED"
fi fi
if [ -n "$CLI_PLAYERBOT_MIN" ]; then
if ! [[ "$CLI_PLAYERBOT_MIN" =~ ^[0-9]+$ ]]; then
say ERROR "--playerbot-min-bots must be numeric"
exit 1
fi
PLAYERBOT_MIN_BOTS="$CLI_PLAYERBOT_MIN"
fi
if [ -n "$CLI_PLAYERBOT_MAX" ]; then if [ -n "$CLI_PLAYERBOT_MAX" ]; then
if ! [[ "$CLI_PLAYERBOT_MAX" =~ ^[0-9]+$ ]]; then if ! [[ "$CLI_PLAYERBOT_MAX" =~ ^[0-9]+$ ]]; then
say ERROR "--playerbot-max-bots must be numeric" say ERROR "--playerbot-max-bots must be numeric"
@@ -1260,9 +1278,17 @@ fi
if [ -z "$CLI_PLAYERBOT_ENABLED" ]; then if [ -z "$CLI_PLAYERBOT_ENABLED" ]; then
PLAYERBOT_ENABLED=1 PLAYERBOT_ENABLED=1
fi fi
PLAYERBOT_MIN_BOTS=$(ask "Minimum concurrent playerbots" "${CLI_PLAYERBOT_MIN:-$DEFAULT_PLAYERBOT_MIN}" validate_number)
PLAYERBOT_MAX_BOTS=$(ask "Maximum concurrent playerbots" "${CLI_PLAYERBOT_MAX:-$DEFAULT_PLAYERBOT_MAX}" validate_number) PLAYERBOT_MAX_BOTS=$(ask "Maximum concurrent playerbots" "${CLI_PLAYERBOT_MAX:-$DEFAULT_PLAYERBOT_MAX}" validate_number)
fi fi
if [ -n "$PLAYERBOT_MIN_BOTS" ] && [ -n "$PLAYERBOT_MAX_BOTS" ]; then
if [ "$PLAYERBOT_MAX_BOTS" -lt "$PLAYERBOT_MIN_BOTS" ]; then
say WARNING "Playerbot max bots ($PLAYERBOT_MAX_BOTS) lower than min ($PLAYERBOT_MIN_BOTS); adjusting max to match min."
PLAYERBOT_MAX_BOTS="$PLAYERBOT_MIN_BOTS"
fi
fi
for mod_var in "${MODULE_KEYS[@]}"; do for mod_var in "${MODULE_KEYS[@]}"; do
if [ "${MODULE_NEEDS_BUILD_MAP[$mod_var]}" = "1" ]; then if [ "${MODULE_NEEDS_BUILD_MAP[$mod_var]}" = "1" ]; then
eval "value=\${$mod_var:-0}" eval "value=\${$mod_var:-0}"
@@ -1291,6 +1317,7 @@ fi
printf " %-18s %s\n" "Modules images:" "$AC_AUTHSERVER_IMAGE_MODULES_VALUE | $AC_WORLDSERVER_IMAGE_MODULES_VALUE" printf " %-18s %s\n" "Modules images:" "$AC_AUTHSERVER_IMAGE_MODULES_VALUE | $AC_WORLDSERVER_IMAGE_MODULES_VALUE"
printf " %-18s %s\n" "Modules preset:" "$SUMMARY_MODE_TEXT" printf " %-18s %s\n" "Modules preset:" "$SUMMARY_MODE_TEXT"
printf " %-18s %s\n" "Playerbot Min Bots:" "$PLAYERBOT_MIN_BOTS"
printf " %-18s %s\n" "Playerbot Max Bots:" "$PLAYERBOT_MAX_BOTS" printf " %-18s %s\n" "Playerbot Max Bots:" "$PLAYERBOT_MAX_BOTS"
printf " %-18s" "Enabled Modules:" printf " %-18s" "Enabled Modules:"
local enabled_modules=() local enabled_modules=()
@@ -1530,6 +1557,7 @@ CLIENT_DATA_VERSION=${CLIENT_DATA_VERSION:-$DEFAULT_CLIENT_DATA_VERSION}
# Playerbot runtime # Playerbot runtime
PLAYERBOT_ENABLED=$PLAYERBOT_ENABLED PLAYERBOT_ENABLED=$PLAYERBOT_ENABLED
PLAYERBOT_MIN_BOTS=$PLAYERBOT_MIN_BOTS
PLAYERBOT_MAX_BOTS=$PLAYERBOT_MAX_BOTS PLAYERBOT_MAX_BOTS=$PLAYERBOT_MAX_BOTS
# Rebuild automation # Rebuild automation