From 33309e10b12f3405affe31b027588c8875e66fd6 Mon Sep 17 00:00:00 2001 From: biqqles Date: Fri, 19 Feb 2021 19:53:05 +0000 Subject: [PATCH] Dump string resources with flint --- requirements.txt | 1 + update.py | 50 +++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 42 insertions(+), 9 deletions(-) create mode 100644 requirements.txt diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 00000000..b140a6a5 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +fl-flint==0.8.1 diff --git a/update.py b/update.py index 0580d277..30792b83 100644 --- a/update.py +++ b/update.py @@ -9,13 +9,15 @@ from distutils.dir_util import copy_tree import fnmatch +import flint as fl + build = { # this is unused, it merely explains how build.json is structured # since JSON doesn't allow comments. # path and dest are relative to the root input and output directories "fl_path": "C:/Users/AUDUNVN/AppData/Local/Discovery Freelancer 4.88.1", - + # files to copy into the output folder "files": [ { @@ -70,12 +72,14 @@ build_input_dir = Path("update") + def get_freelancer_path(search_dir): output_path = "" for root, dirs, files in os.walk(search_dir): for dirname in fnmatch.filter(dirs, "Discovery Freelancer*"): output_path = os.path.join(root, dirname) - return(output_path) + return (output_path) + def copy_file(*args, **kwargs): dest_path = PurePath(args[1]) @@ -83,6 +87,7 @@ def copy_file(*args, **kwargs): src = args[0] shutil.copy2(src, new_path, **kwargs) + def lowercase_rename(dir): # renames all subfolders of dir, not including dir itself def rename_all(root, items): @@ -97,6 +102,7 @@ def rename_all(root, items): rename_all(root, dirs) rename_all(root, files) + def copy_into_existing_dir(src, dst): if not os.path.exists(dst): os.makedirs(dst) @@ -109,11 +115,13 @@ def copy_into_existing_dir(src, dst): if not os.path.exists(d) or os.stat(s).st_mtime - os.stat(d).st_mtime > 1: shutil.copy2(s, d) + def copy(src, dest): src_path = Path(src) if src_path.is_dir(): try: - shutil.copytree(src, dest, ignore=shutil.ignore_patterns('BASES', 'BASE_INTERIORS', 'MODELS', '*.txm'), copy_function=copy_file) + shutil.copytree(src, dest, ignore=shutil.ignore_patterns('BASES', 'BASE_INTERIORS', 'MODELS', '*.txm'), + copy_function=copy_file) except OSError as e: if e.errno == errno.EEXIST: copy_into_existing_dir(src, dest) @@ -124,6 +132,7 @@ def copy(src, dest): else: print("Could not copy " + str(src) + " to " + str(dest) + "!") + def format_infocards(out_dir): print("Formatting infocards.txt") @@ -131,13 +140,33 @@ def format_infocards(out_dir): out_name = out_dir / 'infocards.txt' with codecs.open(input_name, 'r', encoding='utf-8') as in_file, \ - codecs.open(out_name, 'w', encoding='utf-8') as out_file: + codecs.open(out_name, 'w', encoding='utf-8') as out_file: out_text = ''.join(in_file.readlines()[1:]) out_text = out_text.replace("\r\n\r\n", "\r\n") out_text = out_text.replace("\r\nNAME\r\n", "\r\n") out_text = out_text.replace("\r\nINFOCARD\r\n", "\r\n") out_file.write(out_text) + +def read_all_dlls(): + """Read all string resources from all DLLs. + This is a bit hacky since there's no built-in way to do this with flint. Look up the first resource in each + DLL to force flint to parse the file and add its contents to resource_table.""" + result = {} + for i in fl.paths.dlls: + fl.formats.dll.lookup(i * 65536) + result.update(fl.formats.dll.resource_table[i]) + return result + + +def dump_resources(filename: str): + """Dump all string resources to a text file.""" + resources = read_all_dlls() + pairs = (f'{id_}\n{text.strip()}\n' for id_, text in resources.items()) + with open(filename, 'w') as f: + f.writelines(pairs) + + def build_update(): config = build @@ -152,24 +181,26 @@ def build_update(): print("Discovery install directory not found, aborting") sys.exit() fl_path = Path(found_fl_path) + + fl.set_install_path(str(fl_path)) + print("Freelancer directory set to \"" + str(fl_path) + "\"") out_dir = Path(input("Set output directory: ")) os.mkdir(out_dir) - print("Run FL Path Generator (in the utils folder) on the FL installation in the \"" + str(fl_path) + "\" folder") - print("Run FLInfocardIE. Save infocards.txt into the \"" + str(build_input_dir) + "\" folder") - input("Press Enter to continue once you're done...") + print("Dumping resources") + dump_resources('update/infocards.txt') format_infocards(out_dir) - + print("Copying directories") for directory in config["directories"]: src_path = fl_path / directory["path"] out_path = out_dir / directory["dest"] print("Copying " + str(src_path) + " to " + str(out_path)) copy(src_path, out_path) - + print("Copying files") for file in config["files"]: src_path = fl_path / file["path"] @@ -185,4 +216,5 @@ def build_update(): print("Done! Now open index.html and set the dataRootPath variable to the \"" + str(out_dir) + "\" folder") + build_update()