justawriter

GZDoom Advanced macOS Launcher Script

Sep 5th, 2025 (edited)
199
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 9.54 KB | Gaming | 0 0
  1. #!/bin/bash
  2.  
  3. # ==============================================================
  4. # GZDoom Advanced macOS Launcher Script
  5. # ==============================================================
  6.  
  7. # PURPOSE:
  8. # Launch GZDoom with an ordered list of .pk3/.wad files, then back up
  9. # your saves and config. Supports pruning (by age OR by count) and
  10. # optional ZIP compression. All settings are below and can also be
  11. # overridden with runtime flags.
  12.  
  13. # FEATURES:
  14. # - Run multiple .pk3/.wad mods in a specific order
  15. # - Load mods, maps, etc from a single folder (MOD_BASE) OR full paths (layering)
  16. # - Per-mod save folder via -savedir
  17. # - Custom IWAD file
  18. # - Extra GZDoom CLI arguments (EXTRA_ARGS array)
  19. # - Backups are named with the MOD and include only this MOD's savedir
  20. # - Optional ZIP compression of each backup
  21. # - Pruning of old backups by AGE or by COUNT (or disabled)
  22.  
  23. # HOW TO USE:
  24. # 1) Edit the "USER SETTINGS" section.
  25. # 2) Save as: GZDoom_Launcher_Advanced.command
  26. # 3) Make executable: chmod +x GZDoom_Launcher_Advanced.command
  27. # 4) Double-click to run (or execute from Terminal).
  28.  
  29. # RUNTIME FLAGS (optional):
  30. # --mod="folder"             Override MOD name/folder (affects MOD_BASE and SAVE_DIR)
  31. # --iwad="file.wad"          Use a different IWAD filename
  32. # --backup=age|count|off     Choose pruning mode
  33. # --days=N                   Set PRUNE_DAYS (for backup=age)
  34. # --keep=N                   Set MAX_BACKUPS (for backup=count)
  35. # --backup-dir="/path"       Override backup destination
  36. # --zip=on|off               Enable/disable ZIP compression
  37. # --zipkeep=on|off           Keep/delete raw folder after ZIP
  38. # --help / --prune-help      Print detailed help and exit
  39.  
  40. # PRUNING MODES EXPLAINED:
  41. # - backup=age:
  42. #     Keeps all timestamped backups newer than PRUNE_DAYS days,
  43. #     deletes anything older. Best if you play frequently and want
  44. #     “last N days” retained regardless of how many sessions you ran.
  45. # - backup=count:
  46. #     Keeps only the newest MAX_BACKUPS backups (folders or .zip),
  47. #     deletes older ones. Best if you play irregularly and want your
  48. #     “last N sessions” retained regardless of calendar days.
  49. # - backup=off:
  50. #     No deletion is performed. Backups accumulate until you clean up.
  51.  
  52. # ==============================================================
  53.  
  54. set -u  # treat unset variables as errors
  55.  
  56. # =======================
  57. # USER SETTINGS
  58. # =======================
  59.  
  60. # Mod, Maps, Campaign, etc folder name (used for MOD_BASE and SAVE_DIR)
  61. MOD="final carnage"
  62.  
  63. # IWAD filename (must exist in your GZDoom support folder)
  64. IWAD_FILENAME="DOOM2.WAD"
  65.  
  66. # Base folder for relative mod entries
  67. MOD_BASE="$HOME/Library/Application Support/gzdoom/$MOD"
  68.  
  69. # Ordered list of mods to load.
  70. # - Relative entries are resolved under MOD_BASE.
  71. # - Full-path entries (starting with "/" or "~") are used as-is.
  72. MOD_FILES=(
  73.   "FinalCarnage.pk3"
  74.   "BRUTAL PACK V10 10.3.pk3"
  75.   "BrutalPack Neural Pack.pk3"
  76.   "BP-Glory-Kill-3.pk3"
  77.   "BrutalDoom_PB-Blade custom.pk3"
  78.   "autoautosave-v1.6.3.pk3"
  79.   "CorruptionCards-v6.3b.pk3"
  80.   "gearbox-0.7.3.pk3"
  81.   "GZ-WalkItOut.pk3"
  82.   "flashlight_plus_plus_v9_1.pk3"
  83.   "BrutalDoom_PB-Blade custom.pk3"
  84.   "GunBonsai-0.10.6.pk3"
  85.   "minimap_m.pk3"
  86.   "HXRTCHUD_BPV103b_v3.pk3"
  87.   # Example full-path mod (uncomment and edit):
  88.   # "$HOME/gzdoom_mods/visuals/hd_textures.pk3"
  89. )
  90.  
  91. # Optional extra GZDoom CLI arguments (leave empty if not needed)
  92. EXTRA_ARGS=(
  93.   # "+set vid_fps 1"
  94.   # "-width 1920" "-height 1080"
  95. )
  96.  
  97. # Backup destination (iCloud by default)
  98. BACKUP_BASE="$HOME/Library/Mobile Documents/com~apple~CloudDocs/gzdoom-backup"
  99.  
  100. # Pruning mode: "age", "count", or "off"
  101. BACKUP_MODE="count"
  102.  
  103. # Age-based pruning: delete backups older than PRUNE_DAYS days
  104. PRUNE_DAYS=30
  105.  
  106. # Count-based pruning: keep only the newest MAX_BACKUPS backups
  107. MAX_BACKUPS=30
  108.  
  109. # ZIP each backup after creation? "on" or "off"
  110. ZIP_BACKUPS="on"
  111.  
  112. # If zipping is on, delete the raw unzipped folder after successful ZIP?
  113. ZIP_DELETE_RAW="on"
  114.  
  115. # =======================
  116. # DERIVED PATHS
  117. # =======================
  118.  
  119. SAVE_DIR="$HOME/Documents/GZDoom/$MOD"
  120. IWAD_PATH="$HOME/Library/Application Support/gzdoom/$IWAD_FILENAME"
  121.  
  122. # Back up only this run's savedir (matches -savedir), not all mods
  123. SRC_DOCS="$SAVE_DIR"
  124. SRC_INI="$HOME/Library/Preferences/gzdoom.ini"
  125.  
  126. # =======================
  127. # FLAG PARSING
  128. # =======================
  129.  
  130. for arg in "$@"; do
  131.   case "$arg" in
  132.     --backup=*) BACKUP_MODE="${arg#*=}" ;;
  133.     --days=*) PRUNE_DAYS="${arg#*=}" ;;
  134.     --keep=*) MAX_BACKUPS="${arg#*=}" ;;
  135.     --mod=*)
  136.       MOD="${arg#*=}"
  137.       MOD_BASE="$HOME/Library/Application Support/gzdoom/$MOD"
  138.       SAVE_DIR="$HOME/Documents/GZDoom/$MOD"
  139.       SRC_DOCS="$SAVE_DIR"
  140.       ;;
  141.     --iwad=*)
  142.       IWAD_FILENAME="${arg#*=}"
  143.       IWAD_PATH="$HOME/Library/Application Support/gzdoom/$IWAD_FILENAME"
  144.       ;;
  145.     --zip=*) ZIP_BACKUPS="${arg#*=}" ;;
  146.     --zipkeep=*) ZIP_DELETE_RAW="${arg#*=}" ;;
  147.     --backup-dir=*) BACKUP_BASE="${arg#*=}" ;;
  148.     --help|--prune-help)
  149.       echo ""
  150.       echo "USAGE FLAGS"
  151.       echo "  --mod=FOLDER            Override MOD folder (affects MOD_BASE and SAVE_DIR)"
  152.       echo "  --iwad=FILENAME         Use a different IWAD (e.g., DOOM2.WAD)"
  153.       echo "  --backup=age|count|off  Pruning mode selection"
  154.       echo "  --days=N                PRUNE_DAYS for backup=age (delete older than N days)"
  155.       echo "  --keep=N                MAX_BACKUPS for backup=count (keep newest N)"
  156.       echo "  --backup-dir=PATH       Backup destination root"
  157.       echo "  --zip=on|off            ZIP each backup folder"
  158.       echo "  --zipkeep=on|off        If zipping, keep raw folder (on) or delete it (off)"
  159.       echo ""
  160.       echo "PRUNING EXPLANATION"
  161.       echo "  age   : Retain backups newer than PRUNE_DAYS days; delete older ones."
  162.       echo "  count : Retain only the newest MAX_BACKUPS; delete older ones."
  163.       echo "  off   : No deletion; backups accumulate until you clean up manually."
  164.       echo ""
  165.       echo "MOD LAYERING"
  166.       echo "  MOD_FILES entries starting with '/' or '~' are treated as full paths."
  167.       echo "  Other entries are resolved under MOD_BASE."
  168.       echo ""
  169.       exit 0
  170.       ;;
  171.     *)
  172.       echo "Ignoring unknown option: $arg"
  173.       ;;
  174.   esac
  175. done
  176.  
  177. # Ensure backup root exists
  178. mkdir -p "$BACKUP_BASE"
  179.  
  180. # =======================
  181. # BUILD MOD FILE ARGUMENTS
  182. # =======================
  183.  
  184. FILE_ARGS=()
  185. for f in "${MOD_FILES[@]}"; do
  186.   [ -n "$f" ] || continue
  187.   if [[ "$f" == /* || "$f" == ~* ]]; then
  188.     FILE_ARGS+=("${f/#\~/$HOME}")
  189.   else
  190.     FILE_ARGS+=("$MOD_BASE/$f")
  191.   fi
  192. done
  193.  
  194. # =======================
  195. # LAUNCH GZDOOM (robust command assembly)
  196. # =======================
  197.  
  198. CMD=(/Applications/GZDoom.app/Contents/MacOS/gzdoom -savedir "$SAVE_DIR")
  199.  
  200. if [ "${#FILE_ARGS[@]}" -gt 0 ]; then
  201.   CMD+=(-file "${FILE_ARGS[@]}")
  202. fi
  203.  
  204. CMD+=(-iwad "$IWAD_PATH")
  205.  
  206. # Append EXTRA_ARGS only if any exist (compatible with set -u)
  207. if [ "${#EXTRA_ARGS[@]:-0}" -gt 0 ]; then
  208.   CMD+=("${EXTRA_ARGS[@]}")
  209. fi
  210.  
  211. # Execute
  212. "${CMD[@]}"
  213.  
  214. # =======================
  215. # CREATE BACKUP (only this MOD's savedir)
  216. # =======================
  217.  
  218. echo "Backing up GZDoom save and config data..."
  219.  
  220. STAMP=$(date +"%Y-%m-%d_%H-%M-%S")
  221.  
  222. # Sanitize MOD for filesystem safety (spaces/special chars -> underscores)
  223. SAFE_MOD="$(echo "$MOD" | sed 's/[^A-Za-z0-9._-]/_/g')"
  224.  
  225. # Name backup folder with MOD included
  226. DEST="$BACKUP_BASE/${SAFE_MOD}_Backup_$STAMP"
  227. mkdir -p "$DEST"
  228.  
  229. # Back up only this mod’s savedir into a mod-named subfolder
  230. if [ -d "$SRC_DOCS" ]; then
  231.   rsync -av "$SRC_DOCS/" "$DEST/Savedir_${SAFE_MOD}/"
  232. fi
  233.  
  234. # Back up global config
  235. if [ -f "$SRC_INI" ]; then
  236.   rsync -av "$SRC_INI" "$DEST/"
  237. fi
  238.  
  239. # =======================
  240. # OPTIONAL ZIP COMPRESSION
  241. # =======================
  242.  
  243. if [ "$ZIP_BACKUPS" = "on" ]; then
  244.   echo "Zipping backup folder..."
  245.   (
  246.     cd "$BACKUP_BASE" && /usr/bin/zip -r -q "${SAFE_MOD}_Backup_${STAMP}.zip" "${SAFE_MOD}_Backup_${STAMP}"
  247.   )
  248.   ZIP_STATUS=$?
  249.   if [ $ZIP_STATUS -eq 0 ]; then
  250.     echo "Zip complete: $BACKUP_BASE/${SAFE_MOD}_Backup_${STAMP}.zip"
  251.     if [ "$ZIP_DELETE_RAW" = "on" ]; then
  252.       echo "Removing unzipped folder after successful zip..."
  253.       rm -rf "$DEST"
  254.     fi
  255.   else
  256.     echo "Zip failed. Leaving uncompressed folder: $DEST"
  257.   fi
  258. fi
  259.  
  260. # =======================
  261. # BACKUP PRUNING
  262. # =======================
  263.  
  264. case "$BACKUP_MODE" in
  265.   age)
  266.     if [ "$PRUNE_DAYS" -gt 0 ]; then
  267.       echo "Pruning backups older than $PRUNE_DAYS days..."
  268.       find "$BACKUP_BASE" -maxdepth 1 \
  269.         \( -type d \( -name 'Backup_*' -o -name '*_Backup_*' \) -o \
  270.            -type f \( -name 'Backup_*.zip' -o -name '*_Backup_*.zip' \) \) \
  271.         -mtime +"$PRUNE_DAYS" -exec rm -rf {} +
  272.     else
  273.       echo "Age-based pruning disabled (PRUNE_DAYS=0)."
  274.     fi
  275.     ;;
  276.   count)
  277.     if [ "$MAX_BACKUPS" -gt 0 ]; then
  278.       echo "Keeping only the newest $MAX_BACKUPS backups..."
  279.       IFS=$'\n' read -r -d '' -a BACKUPS < <(ls -1dt "$BACKUP_BASE"/Backup_* "$BACKUP_BASE"/*_Backup_* 2>/dev/null && printf '\0')
  280.       COUNT=0
  281.       for item in "${BACKUPS[@]}"; do
  282.         [ -e "$item" ] || continue
  283.         COUNT=$((COUNT+1))
  284.         if [ $COUNT -gt $MAX_BACKUPS ]; then
  285.           echo "Deleting old backup: $item"
  286.           rm -rf "$item"
  287.         fi
  288.       done
  289.       unset IFS
  290.     else
  291.       echo "Count-based pruning disabled (MAX_BACKUPS=0)."
  292.     fi
  293.     ;;
  294.   off|none|disable)
  295.     echo "Pruning disabled (backup=off)."
  296.     ;;
  297.   *)
  298.     echo "Unknown BACKUP_MODE: $BACKUP_MODE (use age|count|off)."
  299.     ;;
  300. esac
  301.  
  302. exit 0
Tags: macOS gzdoom
Advertisement
Add Comment
Please, Sign In to add comment