Skip to content

Instantly share code, notes, and snippets.

@RedFlames
Created September 21, 2023 14:59
Show Gist options
  • Save RedFlames/994443678d91a403d7aad24ab65b711e to your computer and use it in GitHub Desktop.
Save RedFlames/994443678d91a403d7aad24ab65b711e to your computer and use it in GitHub Desktop.
UE 5 mod package/copy/launch Python script
import os
import sys
import json
import time
import shutil
import subprocess
from pathlib import Path
import argparse
"""
I run this e.g. like this
$ cd "/c/Users/rf/Documents/mod_testing/" && python mod_testing.py -a
or
$ cd "/c/Users/rf/Documents/mod_testing/" && python mod_testing.py -c -l
"""
"""
----------------------- Argparser -----------------------
"""
parser = argparse.ArgumentParser()
parser.add_argument("-v", "--verbose", help="increase output verbosity",
action="store_true")
parser.add_argument("-b", "--build", help="package",
action="store_true")
parser.add_argument("-c", "--copy", help="copy paks",
action="store_true")
parser.add_argument("-a", "--all", help="all",
action="store_true")
parser.add_argument("-l", "--launch", help="launch game",
action="store_true")
args = parser.parse_args()
"""
----------------------- Map chunk IDs to mod name -----------------------
"""
chunks_to_mods = {
"2": "rebindMod_p",
"3": "upgradeUnlocker_p",
"4": "stateHistoryGUI_p",
"5": "customFX_p",
"13": "rfMod_p",
"1337": "levelMod_p"
}
"""
----------------------- get ENV vars -----------------------
"""
pr_game_root = os.environ['PR_GAME_ROOT']
pr_cook_dir = os.environ['PR_COOK_DIR']
pr_ue_base = os.environ['PR_UE_BASE']
pr_uproj = os.environ['PR_UPROJECT']
"""
Examples:
PR_GAME_ROOT = "C:/Program Files (x86)/Steam/steamapps/common/Pseudoregalia"
PR_COOK_DIR = "C:/Users/rf/Documents/COOK"
PR_UE_BASE = "H:/UnrealEngine/UE_5.1"
PR_UPROJECT = "C:/Users/rf/Documents/Unreal Projects/pseudoregalia/pseudoregalia.uproject"
"""
print(f"""
Running with:
PR_GAME_ROOT = {pr_game_root}
PR_COOK_DIR = {pr_cook_dir}
PR_UE_BASE = {pr_ue_base}
PR_UPROJECT = {pr_uproj}
""")
"""
----------------------- validate paths/files -----------------------
"""
if not os.path.isdir(pr_game_root):
print("Can't find path PR_GAME_ROOT")
sys.exit()
if not os.path.isdir(pr_cook_dir):
print("Can't find path PR_COOK_DIR")
sys.exit()
if not os.path.isdir(pr_ue_base):
print("Can't find path PR_UE_BASE")
sys.exit()
if not os.path.isfile(pr_uproj):
print("Can't find path PR_UPROJECT")
sys.exit()
game_exe = os.path.abspath(os.path.join(pr_game_root, "pseudoregalia/Binaries/Win64/pseudoregalia-Win64-Shipping.exe"))
target_pak_dir = os.path.abspath(os.path.join(pr_game_root, "pseudoregalia/Content/Paks/LogicMods"))
build_config = "Shipping"
print(f"""
game_exe = {game_exe}
target_pak_dir = {target_pak_dir}
build_config = {build_config}
""")
"""
----------------------- prepare UE build call -----------------------
"""
ue_run_bat = os.path.abspath(os.path.join(pr_ue_base, "Engine/Build/BatchFiles/RunUAT.bat"))
unreal_exe = os.path.abspath(os.path.join(pr_ue_base, "Engine/Binaries/Win64/UnrealEditor-Cmd.exe"))
command = [
ue_run_bat,
#f"-ScriptsForProject={pr_uproj}",
#Turnkey
#-command=VerifySdk
#"-platform=Win64",
#"-UpdateIfNeeded",
#"-project={pr_uproj}",
"BuildCookRun",
"-nop4",
"-utf8output",
"-nocompileeditor",
"-skipbuildeditor",
"-cook",
f"-project={pr_uproj}",
f"-unrealexe={unreal_exe}",
"-platform=Win64",
"-installed",
"-stage",
"-archive",
"-package",
"-build",
"-pak",
"-compressed",
"-prereqs",
f"-archivedirectory={pr_cook_dir}",
"-manifests",
f"-clientconfig={build_config}",
"-nodebuginfo",
]
"""
----------------------- Call build if applicable -----------------------
"""
if args.build or args.all:
try:
print(f"Will now run '{command}'")
subprocess.run(command, check=True)
print(f"Cooked {pr_uproj} ({build_config}) to {pr_cook_dir}.")
except subprocess.CalledProcessError as e:
print(f"Cook Error: {e}")
else:
print(f"SKIPPED build step...")
"""
----------------------- Copy paks if applicable -----------------------
"""
packed_chunks = os.path.abspath(os.path.join(pr_cook_dir, "Windows/pseudoregalia/Content/Paks"))
if args.copy or args.all:
for k, v in chunks_to_mods.items():
chunk_name = f"pakchunk{k}-Windows.pak"
chunk_abs = os.path.abspath(os.path.join(packed_chunks, chunk_name))
if not os.path.isfile(chunk_abs):
print(f"Cannot find chunk file {chunk_name} for mod {v}!")
continue
target_file = os.path.abspath(os.path.join(target_pak_dir, f"{v}.pak"))
print(f"""
Copying:
FROM {chunk_abs}
TO {target_file}
...
""")
shutil.copy2(chunk_abs, target_file)
else:
print(f"SKIPPED copy step...")
"""
----------------------- Launch game if applicable -----------------------
"""
command = [
"C:\Program Files (x86)\Steam\steam.exe",
"steam://rungameid/2365810"
]
if args.launch or args.all:
print("""
---------
Launching game...
---------
""")
subprocess.run(command)
else:
print(f"SKIPPED launch step...")
sys.exit()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment