Files
gtav-src/tools_ng/bin/audio/scripts/RPFs/create_audio_rpfs.py
T
2025-09-29 00:52:08 +02:00

323 lines
9.2 KiB
Python
Executable File

from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import datetime
import os
import smtplib
import sys
# *** SETTINGS ***
# SMTP email notification settings
SMTP_HOST = 'smtp.rockstar.t2.corp'
SMTP_PORT = 25
SMTP_USERNAME = ''
SMTP_PASSWORD = ''
SMTP_FROM = 'Audio RPFs Generator <rpf-generator@rockstarnorth.com>'
SMTP_TO = (
'Matt Hailey <matt.hailey@rockstarnorth.com>',
'Alastair MacGregor <alastair.macgregor@rockstarnorth.com>',
#'Matthew Smith <matthew.smith@rockstarnorth.com>',
)
# Logging
LOG_PATH = None
PRINT_LOG = True
warning_count = 0
error_count = 0
logger = ''
# Perforce
PERFORCE_EXE_NAME = r'p4'
# Environment
env_args_keys = (
'build',
'audio',
'platform',
'ragebuilder',
'package',
'RS_TOOLSROOT',
'RS_BUILDBRANCH',
)
env_args = {}
packlist_path = None
input_path = None
output_path = None
build_pack_path = None
working_path = None
# *** SETTINGS (END) ***
# *** TYPES ***
# LogSeverity enums
class LogSeverity:
INFO='INFO'
WARNING='WARNING'
ERROR='ERROR'
CRITICAL='CRITICAL'
# *** TYPES (END) ***
# *** MAIN PROCESS ***
def main():
# Run process
args = sys.argv
# Fetch required environment variables
if not init_env_vars(env_args_keys, env_args):
log("Failed to load all required environment variables", LogSeverity.ERROR)
return -1
# Initialise paths to required dirs and files
if not init_paths():
log("Failed to initialise paths", LogSeverity.ERROR)
return -1
set_working_path(env_args['build'])
# Mark packlist file for edit
if not run_p4_cmd('edit', packlist_path):
return -1
# Generate RPF files
rebuild = 'full' in args
if not generate_rpfs(rebuild):
return -1
# Execute RAGE builder
if not exec_rage_builder():
return -1
# Revert any unchanged files
platform = env_args['platform']
if platform.upper() == 'PC':
platform = 'x64'
path = os.path.join(env_args['build'], platform, 'audio')
args = '-a %s\\...' % path
if not run_p4_cmd('revert', args):
return
return 0
def init_paths():
global packlist_path
global input_path
global output_path
global build_pack_path
# Check build path exists
if not os.path.exists(env_args['build']):
log("Path does not exist: %s" % env_args['build'], LogSeverity.ERROR)
return False
log("Using build path: %s" % env_args['build'], LogSeverity.INFO)
# Init config dir
config_dir = os.path.join(env_args['audio'], env_args['platform'], 'config')
if not os.path.exists(config_dir):
log("Creating path: %s" % config_dir, LogSeverity.INFO)
os.makedirs(config_dir)
# Init packlist path (file may not exist locally)
packlist_path = os.path.join(config_dir, 'packlist.txt')
log("Using packlist path: %s" % packlist_path, LogSeverity.INFO)
# Init input path
input_path = os.path.join(env_args['audio'], env_args['platform'], 'sfx')
if not os.path.exists(input_path):
log("Path does not exist: %s" % input_path, LogSeverity.ERROR)
return False
log("Using input path: %s" % input_path, LogSeverity.INFO)
# Init output path
platform = env_args['platform']
if platform.upper() == 'PC':
platform = 'x64'
output_path = os.path.join(env_args['build'], platform, 'audio', 'sfx')
if not os.path.exists(output_path):
log("Path does not exist - creating directory: %s" % output_path, LogSeverity.INFO)
try:
os.makedirs(output_path)
except:
log("Failed to create directory: %s" % output_path, LogSeverity.ERROR)
return False
log("Using output path: %s" % output_path, LogSeverity.INFO)
# Init build pack path
build_pack_path = os.path.join(env_args['RS_TOOLSROOT'], 'bin', 'audio', 'scripts', 'RPFs', 'build_pack.bat')
if not os.path.exists(build_pack_path):
log("Path does not exist: %s" % build_pack_path, LogSeverity.ERROR)
return False
log("Using build pack path: %s" % build_pack_path, LogSeverity.INFO)
return True
def generate_rpfs(rebuild):
global input_path
global output_path
if rebuild:
log("Generating all audio RPF files..", LogSeverity.INFO)
else:
log("Generating latest audio RPF files..", LogSeverity.INFO)
# Open pack list file for writing and overwrite previous data
pack_list_file = open(packlist_path, 'w')
# Generate RPFs for files in each pack (ie sub-dir) in input_path
for path, packs, files in os.walk(input_path):
for pack in packs:
# Pack needs to be added to pack list file
pack_list_file.write("%s\n" % pack)
if not rebuild and not pack_requires_build(os.path.join(path, pack), pack):
# Skip current pack if build not required and
# process not marked for full rebuild
continue
# Init build params
log("Building pack %s..." % pack, LogSeverity.INFO)
input_pack_path = os.path.join(input_path, pack)
output_pack_path = os.path.join(output_path, pack)
# Run build command
cmd = r'%s %s\ %s.rpf %s' % (build_pack_path, input_pack_path, output_pack_path, pack)
log("Running cmd: %s" % cmd, LogSeverity.INFO)
if os.system(cmd) != 0:
log("Failed to successfully run command: %s" % cmd, LogSeverity.ERROR)
return False
pack_list_file.close()
return True
def pack_requires_build(pack_path, pack_name):
global output_path
rpf_path = '%s.rpf' % os.path.join(output_path, pack_name)
# If output file doesn't exist, it needs to be built
if not os.path.exists(rpf_path):
return True
for file in os.listdir(pack_path):
# Only interested in AWC files
if file.lower().endswith('.awc'):
awc_path = os.path.join(pack_path, file)
# If AWC file is newer than RPF file, it needs to be built
if os.stat(awc_path).st_mtime > os.stat(rpf_path).st_mtime:
return True
return False
def exec_rage_builder():
platform = env_args['platform']
if platform.upper() == 'PC':
platform = 'x64'
pack = os.path.join(env_args['build'], platform, 'audio', 'audio.rpf')
rootpath = os.path.join(env_args['audio'], env_args['platform'])
cmd = '%s %s -pack %s -rootpath %s\ -extignore .awc -nameheapshift=1' % \
(env_args['ragebuilder'], env_args['package'], pack, rootpath)
# Mark pack file for edit
if not run_p4_cmd('edit', pack):
return False
log("Running cmd: %s" % cmd, LogSeverity.INFO)
if os.system(cmd) != 0:
log("Failed to successfully run command: %s" % cmd, LogSeverity.ERROR)
return False
return True
# *** MAIN PROCESS (END) ***
# *** HELPER FUNCTIONS ***
def set_working_path(path):
global working_path
# Change working path if required
if working_path != path:
working_path = path
msg = "Setting working path as %s" % path
log(msg, LogSeverity.INFO)
os.chdir(path)
def init_env_vars(keys, output):
log("Loading environment variables...", LogSeverity.INFO)
successful = True
for key in keys:
try:
value = os.environ[key]
output[key] = value
log("Loaded environment variable: %s=%s" % (key, value), LogSeverity.INFO)
except:
log("Failed to load environment variable: %s" % key, LogSeverity.ERROR)
successful = False
return successful
def log(msg, severity):
global warning_count
global error_count
global logger
now = datetime.datetime.now()
now_str = now.strftime('%H:%M:%S')
full_msg = "[%s] %s: %s" % (now_str, severity, msg)
# Print to console if required
if PRINT_LOG:
print full_msg
# Increment warning/error counter
if severity == LogSeverity.WARNING:
warning_count += 1
elif severity in (LogSeverity.ERROR, LogSeverity.CRITICAL):
error_count += 1
# Store message in logger
logger += "%s\n" % full_msg
def save_log():
# Save log of current process to file
if LOG_PATH:
if not os.path.exists(LOG_PATH):
os.makedirs(LOG_PATH)
writer = open(LOG_PATH, 'w')
writer.write(logger)
writer.close()
def run_p4_cmd(action, args):
cmd = '%s %s %s' % (PERFORCE_EXE_NAME, action, args)
log("Running Perforce cmd: %s" % cmd, LogSeverity.INFO)
if os.system(cmd) != 0:
log("Failed to successfully run P4 command: %s" % cmd, LogSeverity.ERROR)
return False
return True
# *** HELPER FUNCTIONS (END) ***
if __name__ == '__main__':
main()