|
5 | 5 | import shutil
|
6 | 6 | import threading
|
7 | 7 | import zipfile
|
8 |
| -from typing import Optional, TYPE_CHECKING |
| 8 | +from typing import Optional, TYPE_CHECKING, Any, List, Callable, Tuple |
9 | 9 |
|
10 | 10 | import jinja2
|
11 | 11 |
|
|
24 | 24 | data_final_template: Optional[jinja2.Template] = None
|
25 | 25 | locale_template: Optional[jinja2.Template] = None
|
26 | 26 | control_template: Optional[jinja2.Template] = None
|
| 27 | +settings_template: Optional[jinja2.Template] = None |
27 | 28 |
|
28 | 29 | template_load_lock = threading.Lock()
|
29 | 30 |
|
|
62 | 63 | class FactorioModFile(worlds.Files.APContainer):
|
63 | 64 | game = "Factorio"
|
64 | 65 | compression_method = zipfile.ZIP_DEFLATED # Factorio can't load LZMA archives
|
| 66 | + writing_tasks: List[Callable[[], Tuple[str, str]]] |
| 67 | + |
| 68 | + def __init__(self, *args: Any, **kwargs: Any): |
| 69 | + super().__init__(*args, **kwargs) |
| 70 | + self.writing_tasks = [] |
65 | 71 |
|
66 | 72 | def write_contents(self, opened_zipfile: zipfile.ZipFile):
|
67 | 73 | # directory containing Factorio mod has to come first, or Factorio won't recognize this file as a mod.
|
68 | 74 | mod_dir = self.path[:-4] # cut off .zip
|
69 | 75 | for root, dirs, files in os.walk(mod_dir):
|
70 | 76 | for file in files:
|
71 |
| - opened_zipfile.write(os.path.join(root, file), |
72 |
| - os.path.relpath(os.path.join(root, file), |
| 77 | + filename = os.path.join(root, file) |
| 78 | + opened_zipfile.write(filename, |
| 79 | + os.path.relpath(filename, |
73 | 80 | os.path.join(mod_dir, '..')))
|
| 81 | + for task in self.writing_tasks: |
| 82 | + target, content = task() |
| 83 | + opened_zipfile.writestr(target, content) |
74 | 84 | # now we can add extras.
|
75 | 85 | super(FactorioModFile, self).write_contents(opened_zipfile)
|
76 | 86 |
|
@@ -98,6 +108,7 @@ def load_template(name: str):
|
98 | 108 | locations = [(location, location.item)
|
99 | 109 | for location in world.science_locations]
|
100 | 110 | mod_name = f"AP-{multiworld.seed_name}-P{player}-{multiworld.get_file_safe_player_name(player)}"
|
| 111 | + versioned_mod_name = mod_name + "_" + Utils.__version__ |
101 | 112 |
|
102 | 113 | random = multiworld.per_slot_randoms[player]
|
103 | 114 |
|
@@ -153,48 +164,38 @@ def flop_random(low, high, base=None):
|
153 | 164 | template_data["free_sample_blacklist"].update({item: 1 for item in multiworld.free_sample_blacklist[player].value})
|
154 | 165 | template_data["free_sample_blacklist"].update({item: 0 for item in multiworld.free_sample_whitelist[player].value})
|
155 | 166 |
|
156 |
| - control_code = control_template.render(**template_data) |
157 |
| - data_template_code = data_template.render(**template_data) |
158 |
| - data_final_fixes_code = data_final_template.render(**template_data) |
159 |
| - settings_code = settings_template.render(**template_data) |
| 167 | + mod_dir = os.path.join(output_directory, versioned_mod_name) |
160 | 168 |
|
161 |
| - mod_dir = os.path.join(output_directory, mod_name + "_" + Utils.__version__) |
162 |
| - en_locale_dir = os.path.join(mod_dir, "locale", "en") |
163 |
| - os.makedirs(en_locale_dir, exist_ok=True) |
| 169 | + zf_path = os.path.join(mod_dir + ".zip") |
| 170 | + mod = FactorioModFile(zf_path, player=player, player_name=multiworld.player_name[player]) |
164 | 171 |
|
165 | 172 | if world.zip_path:
|
166 |
| - # Maybe investigate read from zip, write to zip, without temp file? |
167 | 173 | with zipfile.ZipFile(world.zip_path) as zf:
|
168 | 174 | for file in zf.infolist():
|
169 | 175 | if not file.is_dir() and "/data/mod/" in file.filename:
|
170 | 176 | path_part = Utils.get_text_after(file.filename, "/data/mod/")
|
171 |
| - target = os.path.join(mod_dir, path_part) |
172 |
| - os.makedirs(os.path.split(target)[0], exist_ok=True) |
173 |
| - |
174 |
| - with open(target, "wb") as f: |
175 |
| - f.write(zf.read(file)) |
| 177 | + mod.writing_tasks.append(lambda arcpath=versioned_mod_name+"/"+path_part, content=zf.read(file): |
| 178 | + (arcpath, content)) |
176 | 179 | else:
|
177 | 180 | shutil.copytree(os.path.join(os.path.dirname(__file__), "data", "mod"), mod_dir, dirs_exist_ok=True)
|
178 | 181 |
|
179 |
| - with open(os.path.join(mod_dir, "data.lua"), "wt") as f: |
180 |
| - f.write(data_template_code) |
181 |
| - with open(os.path.join(mod_dir, "data-final-fixes.lua"), "wt") as f: |
182 |
| - f.write(data_final_fixes_code) |
183 |
| - with open(os.path.join(mod_dir, "control.lua"), "wt") as f: |
184 |
| - f.write(control_code) |
185 |
| - with open(os.path.join(mod_dir, "settings.lua"), "wt") as f: |
186 |
| - f.write(settings_code) |
187 |
| - locale_content = locale_template.render(**template_data) |
188 |
| - with open(os.path.join(en_locale_dir, "locale.cfg"), "wt") as f: |
189 |
| - f.write(locale_content) |
| 182 | + mod.writing_tasks.append(lambda: (versioned_mod_name + "/data.lua", |
| 183 | + data_template.render(**template_data))) |
| 184 | + mod.writing_tasks.append(lambda: (versioned_mod_name + "/data-final-fixes.lua", |
| 185 | + data_final_template.render(**template_data))) |
| 186 | + mod.writing_tasks.append(lambda: (versioned_mod_name + "/control.lua", |
| 187 | + control_template.render(**template_data))) |
| 188 | + mod.writing_tasks.append(lambda: (versioned_mod_name + "/settings.lua", |
| 189 | + settings_template.render(**template_data))) |
| 190 | + mod.writing_tasks.append(lambda: (versioned_mod_name + "/locale/en/locale.cfg", |
| 191 | + locale_template.render(**template_data))) |
| 192 | + |
190 | 193 | info = base_info.copy()
|
191 | 194 | info["name"] = mod_name
|
192 |
| - with open(os.path.join(mod_dir, "info.json"), "wt") as f: |
193 |
| - json.dump(info, f, indent=4) |
| 195 | + mod.writing_tasks.append(lambda: (versioned_mod_name + "/info.json", |
| 196 | + json.dumps(info, indent=4))) |
194 | 197 |
|
195 |
| - # zip the result |
196 |
| - zf_path = os.path.join(mod_dir + ".zip") |
197 |
| - mod = FactorioModFile(zf_path, player=player, player_name=multiworld.player_name[player]) |
| 198 | + # write the mod file |
198 | 199 | mod.write()
|
199 |
| - |
| 200 | + # clean up |
200 | 201 | shutil.rmtree(mod_dir)
|
0 commit comments