| 
									
										
										
										
											2021-04-01 11:40:58 +02:00
										 |  |  | """Outputs a Factorio Mod to facilitate integration with Archipelago""" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import os | 
					
						
							| 
									
										
										
										
											2021-04-03 15:06:32 +02:00
										 |  |  | import zipfile | 
					
						
							| 
									
										
										
										
											2021-04-01 11:40:58 +02:00
										 |  |  | from typing import Optional | 
					
						
							|  |  |  | import threading | 
					
						
							|  |  |  | import json | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import jinja2 | 
					
						
							|  |  |  | import Utils | 
					
						
							|  |  |  | import shutil | 
					
						
							| 
									
										
										
										
											2021-04-08 19:53:24 +02:00
										 |  |  | import Options | 
					
						
							| 
									
										
										
										
											2021-04-01 11:40:58 +02:00
										 |  |  | from BaseClasses import MultiWorld | 
					
						
							| 
									
										
										
										
											2021-06-06 21:11:58 +02:00
										 |  |  | from .Technologies import tech_table, rocket_recipes, recipes | 
					
						
							| 
									
										
										
										
											2021-05-22 10:06:21 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | template_env: Optional[jinja2.Environment] = None | 
					
						
							| 
									
										
										
										
											2021-04-01 11:40:58 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | template: Optional[jinja2.Template] = None | 
					
						
							|  |  |  | locale_template: Optional[jinja2.Template] = None | 
					
						
							| 
									
										
										
										
											2021-05-11 13:28:58 +02:00
										 |  |  | control_template: Optional[jinja2.Template] = None | 
					
						
							| 
									
										
										
										
											2021-04-01 11:40:58 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | template_load_lock = threading.Lock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | base_info = { | 
					
						
							|  |  |  |     "version": Utils.__version__, | 
					
						
							|  |  |  |     "title": "Archipelago", | 
					
						
							|  |  |  |     "author": "Berserker", | 
					
						
							|  |  |  |     "homepage": "https://archipelago.gg", | 
					
						
							|  |  |  |     "description": "Integration client for the Archipelago Randomizer", | 
					
						
							|  |  |  |     "factorio_version": "1.1" | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-06 21:38:53 +02:00
										 |  |  | recipe_time_scales = { | 
					
						
							|  |  |  |     # using random.triangular | 
					
						
							|  |  |  |     Options.RecipeTime.option_fast: (0.25, 1), | 
					
						
							|  |  |  |     Options.RecipeTime.option_normal: (0.5, 2, 1), | 
					
						
							|  |  |  |     Options.RecipeTime.option_slow: (1, 4), | 
					
						
							|  |  |  |     Options.RecipeTime.option_chaos: (0.25, 4, 1), | 
					
						
							|  |  |  |     Options.RecipeTime.option_vanilla: None | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-05-07 21:58:46 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-16 00:21:00 +02:00
										 |  |  | def generate_mod(world: MultiWorld, player: int): | 
					
						
							| 
									
										
										
										
											2021-05-11 13:28:58 +02:00
										 |  |  |     global template, locale_template, control_template | 
					
						
							| 
									
										
										
										
											2021-04-01 11:40:58 +02:00
										 |  |  |     with template_load_lock: | 
					
						
							|  |  |  |         if not template: | 
					
						
							| 
									
										
										
										
											2021-04-07 01:55:53 +02:00
										 |  |  |             mod_template_folder = Utils.local_path("data", "factorio", "mod_template") | 
					
						
							| 
									
										
										
										
											2021-05-22 10:06:21 +02:00
										 |  |  |             template_env: Optional[jinja2.Environment] = \ | 
					
						
							|  |  |  |                 jinja2.Environment(loader=jinja2.FileSystemLoader([mod_template_folder])) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             template = template_env.get_template("data-final-fixes.lua") | 
					
						
							|  |  |  |             locale_template = template_env.get_template(r"locale/en/locale.cfg") | 
					
						
							|  |  |  |             control_template = template_env.get_template("control.lua") | 
					
						
							| 
									
										
										
										
											2021-04-01 11:40:58 +02:00
										 |  |  |     # get data for templates | 
					
						
							|  |  |  |     player_names = {x: world.player_names[x][0] for x in world.player_ids} | 
					
						
							|  |  |  |     locations = [] | 
					
						
							|  |  |  |     for location in world.get_filled_locations(player): | 
					
						
							| 
									
										
										
										
											2021-05-22 07:54:12 +02:00
										 |  |  |         if location.address: | 
					
						
							| 
									
										
										
										
											2021-05-22 10:46:27 +02:00
										 |  |  |             locations.append((location.name, location.item.name, location.item.player, location.item.advancement)) | 
					
						
							| 
									
										
										
										
											2021-05-16 00:21:00 +02:00
										 |  |  |     mod_name = f"AP-{world.seed_name}-P{player}-{world.player_names[player][0]}" | 
					
						
							| 
									
										
										
										
											2021-04-03 14:47:49 +02:00
										 |  |  |     tech_cost = {0: 0.1, | 
					
						
							|  |  |  |                  1: 0.25, | 
					
						
							|  |  |  |                  2: 0.5, | 
					
						
							|  |  |  |                  3: 1, | 
					
						
							|  |  |  |                  4: 2, | 
					
						
							|  |  |  |                  5: 5, | 
					
						
							|  |  |  |                  6: 10}[world.tech_cost[player].value] | 
					
						
							| 
									
										
										
										
											2021-04-01 11:40:58 +02:00
										 |  |  |     template_data = {"locations": locations, "player_names" : player_names, "tech_table": tech_table, | 
					
						
							| 
									
										
										
										
											2021-04-03 14:47:49 +02:00
										 |  |  |                      "mod_name": mod_name, "allowed_science_packs": world.max_science_pack[player].get_allowed_packs(), | 
					
						
							| 
									
										
										
										
											2021-04-24 01:16:49 +02:00
										 |  |  |                      "tech_cost_scale": tech_cost, "custom_data": world.custom_data[player], | 
					
						
							| 
									
										
										
										
											2021-05-07 21:58:46 +02:00
										 |  |  |                      "tech_tree_layout_prerequisites": world.tech_tree_layout_prerequisites[player], | 
					
						
							| 
									
										
										
										
											2021-05-09 17:26:53 +02:00
										 |  |  |                      "rocket_recipe" : rocket_recipes[world.max_science_pack[player].value], | 
					
						
							| 
									
										
										
										
											2021-05-16 00:21:00 +02:00
										 |  |  |                      "slot_name": world.player_names[player][0], "seed_name": world.seed_name, | 
					
						
							| 
									
										
										
										
											2021-06-06 21:11:58 +02:00
										 |  |  |                      "starting_items": world.starting_items[player], "recipes": recipes, | 
					
						
							| 
									
										
										
										
											2021-06-06 21:38:53 +02:00
										 |  |  |                      "random": world.random, | 
					
						
							|  |  |  |                      "recipe_time_scale": recipe_time_scales[world.recipe_time[player].value]} | 
					
						
							| 
									
										
										
										
											2021-05-16 00:21:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-08 19:53:24 +02:00
										 |  |  |     for factorio_option in Options.factorio_options: | 
					
						
							|  |  |  |         template_data[factorio_option] = getattr(world, factorio_option)[player].value | 
					
						
							| 
									
										
										
										
											2021-05-16 00:21:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-07 01:55:53 +02:00
										 |  |  |     control_code = control_template.render(**template_data) | 
					
						
							|  |  |  |     data_final_fixes_code = template.render(**template_data) | 
					
						
							| 
									
										
										
										
											2021-04-01 11:40:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-03 15:06:32 +02:00
										 |  |  |     mod_dir = Utils.output_path(mod_name)+"_"+Utils.__version__ | 
					
						
							| 
									
										
										
										
											2021-04-01 11:40:58 +02:00
										 |  |  |     en_locale_dir = os.path.join(mod_dir, "locale", "en") | 
					
						
							|  |  |  |     os.makedirs(en_locale_dir, exist_ok=True) | 
					
						
							|  |  |  |     shutil.copytree(Utils.local_path("data", "factorio", "mod"), mod_dir, dirs_exist_ok=True) | 
					
						
							|  |  |  |     with open(os.path.join(mod_dir, "data-final-fixes.lua"), "wt") as f: | 
					
						
							| 
									
										
										
										
											2021-04-07 01:55:53 +02:00
										 |  |  |         f.write(data_final_fixes_code) | 
					
						
							|  |  |  |         with open(os.path.join(mod_dir, "control.lua"), "wt") as f: | 
					
						
							|  |  |  |             f.write(control_code) | 
					
						
							| 
									
										
										
										
											2021-04-01 11:40:58 +02:00
										 |  |  |     locale_content = locale_template.render(**template_data) | 
					
						
							|  |  |  |     with open(os.path.join(en_locale_dir, "locale.cfg"), "wt") as f: | 
					
						
							|  |  |  |         f.write(locale_content) | 
					
						
							|  |  |  |     info = base_info.copy() | 
					
						
							|  |  |  |     info["name"] = mod_name | 
					
						
							|  |  |  |     with open(os.path.join(mod_dir, "info.json"), "wt") as f: | 
					
						
							|  |  |  |         json.dump(info, f, indent=4) | 
					
						
							| 
									
										
										
										
											2021-04-03 15:06:32 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # zip the result | 
					
						
							|  |  |  |     zf_path = os.path.join(mod_dir+".zip") | 
					
						
							|  |  |  |     with zipfile.ZipFile(zf_path, compression=zipfile.ZIP_DEFLATED, mode='w') as zf: | 
					
						
							|  |  |  |         for root, dirs, files in os.walk(mod_dir): | 
					
						
							|  |  |  |             for file in files: | 
					
						
							|  |  |  |                 zf.write(os.path.join(root, file), | 
					
						
							|  |  |  |                            os.path.relpath(os.path.join(root, file), | 
					
						
							|  |  |  |                                            os.path.join(mod_dir, '..'))) | 
					
						
							|  |  |  |     shutil.rmtree(mod_dir) | 
					
						
							|  |  |  | 
 |