-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.py
197 lines (156 loc) · 7.47 KB
/
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
import os
import re
import shutil
import subprocess
import json
from validate_paths import validate_paths_json
from locres_exporter import LocresExporter
CARDS_CONFIG = "cards_config.json"
UMODEL_EXPORT = r"/Game/Personalization/PlayerCards/*"
UMODEL_SAVE = r"/Game/Personalization/PlayerCards/*/*_UIData.uasset"
UMODEL_RELATIVE_EXPORT = os.path.normpath(".\\Exports\\Game\\Personalization\\PlayerCards\\")
UMODEL_RELATIVE_SAVE = os.path.normpath(".\\Saves\\Game\\Personalization\\PlayerCards\\")
DISPLAY_NAME_OFFSET = int("0x7A", base=16)
image_paths = {}
uidata_paths = []
display_names = {}
associated_names = {}
def read_paths_json():
if os.path.exists(CARDS_CONFIG):
try:
with open(CARDS_CONFIG, "rt") as paths_file:
return json.load(paths_file)
except OSError:
print("[ERROR] Could not open '" + CARDS_CONFIG + "'\n")
exit()
except ValueError:
print("[ERROR] '" + CARDS_CONFIG + "' has an invalid structure\n")
exit()
else:
paths_dict = {"valorant_path": "", "umodel_path": "", "aes_path": "",
"locres_path": "", "extract_path": "", "target_path": ""}
with open(CARDS_CONFIG, "xt") as paths_file:
json.dump(paths_dict, paths_file, indent=4)
print("[ERROR] Created '" + CARDS_CONFIG + "', fill out before running again\n")
exit()
def normalize_paths(paths_dict):
for path, value in paths_dict.items():
paths_dict[path] = os.path.normpath(os.path.abspath(value))
def locres_export(locres_path):
exporter = LocresExporter()
exporter.export_locres()
exporter.locres_to_csv()
exporter.csv_to_json(locres_path, force_overwrite=True)
def umodel_extract(paths_dict):
print("=== UModel extract ===")
umodel_filename = os.path.basename(paths_dict["umodel_path"])
os.chdir(os.path.dirname(paths_dict["umodel_path"]))
print("Extracting playercards...")
subprocess1 = subprocess.Popen([umodel_filename, "-path=\"" + paths_dict["valorant_path"] + "\"",
"-game=ue4.24", "-aes=@" + paths_dict["aes_path"], "-export", UMODEL_EXPORT],
stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
subprocess2 = subprocess.Popen([umodel_filename, "-path=\"" + paths_dict["valorant_path"] + "\"",
"-game=ue4.24", "-aes=@" + paths_dict["aes_path"], "-save", UMODEL_SAVE],
stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
subprocess1.wait()
subprocess2.wait()
print("Moving exports...")
subprocess1 = subprocess.Popen(["robocopy", UMODEL_RELATIVE_EXPORT,
paths_dict["extract_path"], "/E", "/IS", "/MOVE"],
stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
subprocess1.wait()
print("Moving saves...\n")
subprocess1 = subprocess.Popen(["robocopy", UMODEL_RELATIVE_SAVE,
paths_dict["extract_path"], "/E", "/IS", "/MOVE"],
stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
subprocess1.wait()
def index_cards(cards_path):
for entry in os.listdir(cards_path):
norm_entry = os.path.join(cards_path, entry)
if os.path.isdir(norm_entry):
index_cards(norm_entry)
elif entry.endswith("UIData.uexp"):
uidata_paths.append(norm_entry)
elif entry.endswith(".png"):
image_array = image_paths.get(cards_path, [])
image_array.append(entry)
image_paths[cards_path] = image_array
elif not entry.endswith(".uasset"):
print("[WARN] Unexpected file type:", norm_entry)
def get_display_name_from_uidata(uidata_path):
with open(uidata_path, 'rb') as hex_file:
hex_file.seek(DISPLAY_NAME_OFFSET)
display_name = ""
while (current_read := hex_file.read(1)) != b'\x00':
display_name += current_read.decode("utf-8")
return display_name.replace("/", "")
def find_card_display_names(locres_path):
with open(locres_path, "rt", encoding="utf-8") as csv_file:
locres = json.load(csv_file)
for outer_key, each_dict in locres.items():
for key, value in each_dict.items():
if "card" in key.lower():
display_names[key] = value
def print_uidata_name_associations():
print("UIData count: " + str(len(uidata_paths)) + "\n\n")
for index in range(len(uidata_paths)):
uidata = get_display_name_from_uidata(uidata_paths[index])
print("UIData path: " + uidata_paths[index])
print("UIData: " + uidata)
if uidata in display_names.keys():
print("Name: " + display_names[uidata] + "\n")
else:
print("Name: NOT FOUND\n")
def name_to_readable(image_name, card_name, display_new_name):
image_name = re.sub("_(L1|L2|L|large)\.", " - Large.", image_name)
image_name = re.sub("_(S1|S2|S|small)\.", " - Small.", image_name)
image_name = re.sub("_(W1|W2|W|wide)\.", " - Wide.", image_name)
sub_index = -4 if " - " not in image_name else image_name.index(" - ")
return display_new_name + image_name[sub_index:]
def name_clean_not_allowed(name):
return name.replace("/", "").replace("?", "").replace(":", "")
def copy_named_cards(cards_path, target_path):
for uidata_path in uidata_paths:
card_name = re.sub("(_1|_2|)_UIData.uexp", "", os.path.basename(uidata_path))
uidata = get_display_name_from_uidata(uidata_path)
display_name = display_names[uidata]
display_name = name_clean_not_allowed(display_name)
path = os.path.dirname(uidata_path)
relative_path = os.path.normpath(path.replace(cards_path, ""))
relative_path = os.path.join(os.path.dirname(relative_path), display_name)
images = image_paths[path]
os.makedirs(target_path + relative_path)
for image_name in images:
new_image_name = name_to_readable(image_name, card_name, display_name)
shutil.copyfile(os.path.join(path, image_name),
os.path.join(target_path + relative_path, new_image_name))
image_paths.pop(path)
def copy_unnamed_cards(cards_path, target_path):
for image_path, images in image_paths.items():
relative_path = os.path.normpath(image_path.replace(cards_path, ""))
os.makedirs(target_path + relative_path)
for image_name in images:
shutil.copyfile(os.path.join(image_path, image_name),
os.path.join(target_path + relative_path, image_name))
paths_json = read_paths_json()
normalize_paths(paths_json)
paths_validated = validate_paths_json(paths_json)
if paths_validated:
print(paths_validated)
exit()
print("Exporting locres file...\n")
locres_export(paths_json["locres_path"])
umodel_extract(paths_json)
print("Cleaning previous export...\n")
shutil.rmtree(paths_json["target_path"], ignore_errors=True)
os.mkdir(paths_json["target_path"])
print("Cataloguing cards...")
index_cards(paths_json["extract_path"])
print("\nExporting display names...\n")
find_card_display_names(paths_json["locres_path"])
print("Copying and renaming cards...\n")
print_uidata_name_associations()
copy_named_cards(paths_json["extract_path"], paths_json["target_path"])
copy_unnamed_cards(paths_json["extract_path"], paths_json["target_path"])
print("Cleaning export...")
shutil.rmtree(paths_json["extract_path"], ignore_errors=True)