| 
									
										
										
										
											2022-03-31 05:08:15 +02:00
										 |  |  | """
 | 
					
						
							|  |  |  | Archipelago launcher for bundled app. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | * if run with APBP as argument, launch corresponding client. | 
					
						
							|  |  |  | * if run with executable as argument, run it passing argv[2:] as arguments | 
					
						
							|  |  |  | * if run without arguments, open launcher GUI | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Scroll down to components= to add components to the launcher as well as setup.py | 
					
						
							|  |  |  | """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import argparse | 
					
						
							|  |  |  | import itertools | 
					
						
							| 
									
										
										
										
											2023-06-20 01:01:18 +02:00
										 |  |  | import logging | 
					
						
							| 
									
										
										
										
											2023-05-05 00:53:57 +02:00
										 |  |  | import multiprocessing | 
					
						
							| 
									
										
										
										
											2022-03-31 05:08:15 +02:00
										 |  |  | import shlex | 
					
						
							| 
									
										
										
										
											2022-08-27 02:28:46 +02:00
										 |  |  | import subprocess | 
					
						
							|  |  |  | import sys | 
					
						
							| 
									
										
										
										
											2023-04-16 01:57:52 +02:00
										 |  |  | import webbrowser | 
					
						
							| 
									
										
										
										
											2022-08-27 02:28:46 +02:00
										 |  |  | from os.path import isfile | 
					
						
							|  |  |  | from shutil import which | 
					
						
							| 
									
										
										
										
											2023-03-20 21:24:47 +01:00
										 |  |  | from typing import Sequence, Union, Optional | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-16 01:57:52 +02:00
										 |  |  | import Utils | 
					
						
							| 
									
										
										
										
											2023-07-05 22:39:35 +02:00
										 |  |  | import settings | 
					
						
							| 
									
										
										
										
											2023-04-17 02:35:54 +02:00
										 |  |  | from worlds.LauncherComponents import Component, components, Type, SuffixIdentifier, icon_paths | 
					
						
							| 
									
										
										
										
											2022-08-27 02:28:46 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-04 23:43:03 +02:00
										 |  |  | if __name__ == "__main__": | 
					
						
							|  |  |  |     import ModuleUpdate | 
					
						
							|  |  |  |     ModuleUpdate.update() | 
					
						
							| 
									
										
										
										
											2022-08-27 02:28:46 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | from Utils import is_frozen, user_path, local_path, init_logging, open_filename, messagebox, \ | 
					
						
							|  |  |  |     is_windows, is_macos, is_linux | 
					
						
							| 
									
										
										
										
											2022-03-31 05:08:15 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def open_host_yaml(): | 
					
						
							| 
									
										
										
										
											2023-07-05 22:39:35 +02:00
										 |  |  |     file = settings.get_settings().filename | 
					
						
							|  |  |  |     assert file, "host.yaml missing" | 
					
						
							| 
									
										
										
										
											2022-03-31 05:08:15 +02:00
										 |  |  |     if is_linux: | 
					
						
							|  |  |  |         exe = which('sensible-editor') or which('gedit') or \ | 
					
						
							|  |  |  |               which('xdg-open') or which('gnome-open') or which('kde-open') | 
					
						
							|  |  |  |         subprocess.Popen([exe, file]) | 
					
						
							|  |  |  |     elif is_macos: | 
					
						
							|  |  |  |         exe = which("open") | 
					
						
							|  |  |  |         subprocess.Popen([exe, file]) | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         webbrowser.open(file) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def open_patch(): | 
					
						
							| 
									
										
										
										
											2022-06-04 18:36:50 +02:00
										 |  |  |     suffixes = [] | 
					
						
							|  |  |  |     for c in components: | 
					
						
							| 
									
										
										
										
											2023-10-02 11:52:00 -07:00
										 |  |  |         if c.type == Type.CLIENT and \ | 
					
						
							|  |  |  |                 isinstance(c.file_identifier, SuffixIdentifier) and \ | 
					
						
							|  |  |  |                 (c.script_name is None or isfile(get_exe(c)[-1])): | 
					
						
							|  |  |  |             suffixes += c.file_identifier.suffixes | 
					
						
							| 
									
										
										
										
											2022-03-31 05:08:15 +02:00
										 |  |  |     try: | 
					
						
							| 
									
										
										
										
											2023-10-02 11:52:00 -07:00
										 |  |  |         filename = open_filename("Select patch", (("Patches", suffixes),)) | 
					
						
							| 
									
										
										
										
											2022-03-31 05:08:15 +02:00
										 |  |  |     except Exception as e: | 
					
						
							| 
									
										
										
										
											2023-10-02 11:52:00 -07:00
										 |  |  |         messagebox("Error", str(e), error=True) | 
					
						
							| 
									
										
										
										
											2022-03-31 05:08:15 +02:00
										 |  |  |     else: | 
					
						
							| 
									
										
										
										
											2023-06-20 01:01:18 +02:00
										 |  |  |         file, component = identify(filename) | 
					
						
							| 
									
										
										
										
											2022-03-31 05:08:15 +02:00
										 |  |  |         if file and component: | 
					
						
							| 
									
										
										
										
											2023-10-02 11:52:00 -07:00
										 |  |  |             exe = get_exe(component) | 
					
						
							|  |  |  |             if exe is None or not isfile(exe[-1]): | 
					
						
							|  |  |  |                 exe = get_exe("Launcher") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             launch([*exe, file], component.cli) | 
					
						
							| 
									
										
										
										
											2022-03-31 05:08:15 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-16 01:57:52 +02:00
										 |  |  | def generate_yamls(): | 
					
						
							|  |  |  |     from Options import generate_yaml_templates | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     target = Utils.user_path("Players", "Templates") | 
					
						
							|  |  |  |     generate_yaml_templates(target, False) | 
					
						
							|  |  |  |     open_folder(target) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-31 05:08:15 +02:00
										 |  |  | def browse_files(): | 
					
						
							| 
									
										
										
										
											2023-04-16 01:57:52 +02:00
										 |  |  |     open_folder(user_path()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def open_folder(folder_path): | 
					
						
							| 
									
										
										
										
											2022-03-31 05:08:15 +02:00
										 |  |  |     if is_linux: | 
					
						
							|  |  |  |         exe = which('xdg-open') or which('gnome-open') or which('kde-open') | 
					
						
							| 
									
										
										
										
											2023-04-16 01:57:52 +02:00
										 |  |  |         subprocess.Popen([exe, folder_path]) | 
					
						
							| 
									
										
										
										
											2022-03-31 05:08:15 +02:00
										 |  |  |     elif is_macos: | 
					
						
							|  |  |  |         exe = which("open") | 
					
						
							| 
									
										
										
										
											2023-04-16 01:57:52 +02:00
										 |  |  |         subprocess.Popen([exe, folder_path]) | 
					
						
							| 
									
										
										
										
											2022-03-31 05:08:15 +02:00
										 |  |  |     else: | 
					
						
							| 
									
										
										
										
											2023-04-16 01:57:52 +02:00
										 |  |  |         webbrowser.open(folder_path) | 
					
						
							| 
									
										
										
										
											2022-03-31 05:08:15 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-05 22:39:35 +02:00
										 |  |  | def update_settings(): | 
					
						
							|  |  |  |     from settings import get_settings | 
					
						
							|  |  |  |     get_settings().save() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-20 21:24:47 +01:00
										 |  |  | components.extend([ | 
					
						
							| 
									
										
										
										
											2022-03-31 05:08:15 +02:00
										 |  |  |     # Functions | 
					
						
							| 
									
										
										
										
											2023-04-17 02:35:54 +02:00
										 |  |  |     Component("Open host.yaml", func=open_host_yaml), | 
					
						
							|  |  |  |     Component("Open Patch", func=open_patch), | 
					
						
							| 
									
										
										
										
											2024-03-28 10:00:10 -04:00
										 |  |  |     Component("Generate Template Options", func=generate_yamls), | 
					
						
							| 
									
										
										
										
											2023-04-17 02:35:54 +02:00
										 |  |  |     Component("Discord Server", icon="discord", func=lambda: webbrowser.open("https://discord.gg/8Z65BR2")), | 
					
						
							|  |  |  |     Component("18+ Discord Server", icon="discord", func=lambda: webbrowser.open("https://discord.gg/fqvNCCRsu4")), | 
					
						
							|  |  |  |     Component("Browse Files", func=browse_files), | 
					
						
							| 
									
										
										
										
											2023-03-20 21:24:47 +01:00
										 |  |  | ]) | 
					
						
							| 
									
										
										
										
											2022-03-31 05:08:15 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def identify(path: Union[None, str]): | 
					
						
							|  |  |  |     if path is None: | 
					
						
							| 
									
										
										
										
											2023-06-20 01:01:18 +02:00
										 |  |  |         return None, None | 
					
						
							| 
									
										
										
										
											2022-03-31 05:08:15 +02:00
										 |  |  |     for component in components: | 
					
						
							|  |  |  |         if component.handles_file(path): | 
					
						
							| 
									
										
										
										
											2023-10-02 11:52:00 -07:00
										 |  |  |             return path, component | 
					
						
							| 
									
										
										
										
											2023-06-20 01:01:18 +02:00
										 |  |  |         elif path == component.display_name or path == component.script_name: | 
					
						
							|  |  |  |             return None, component | 
					
						
							|  |  |  |     return None, None | 
					
						
							| 
									
										
										
										
											2022-03-31 05:08:15 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def get_exe(component: Union[str, Component]) -> Optional[Sequence[str]]: | 
					
						
							|  |  |  |     if isinstance(component, str): | 
					
						
							|  |  |  |         name = component | 
					
						
							|  |  |  |         component = None | 
					
						
							| 
									
										
										
										
											2023-10-02 11:52:00 -07:00
										 |  |  |         if name.startswith("Archipelago"): | 
					
						
							| 
									
										
										
										
											2022-03-31 05:08:15 +02:00
										 |  |  |             name = name[11:] | 
					
						
							| 
									
										
										
										
											2023-10-02 11:52:00 -07:00
										 |  |  |         if name.endswith(".exe"): | 
					
						
							| 
									
										
										
										
											2022-03-31 05:08:15 +02:00
										 |  |  |             name = name[:-4] | 
					
						
							| 
									
										
										
										
											2023-10-02 11:52:00 -07:00
										 |  |  |         if name.endswith(".py"): | 
					
						
							| 
									
										
										
										
											2022-03-31 05:08:15 +02:00
										 |  |  |             name = name[:-3] | 
					
						
							|  |  |  |         if not name: | 
					
						
							|  |  |  |             return None | 
					
						
							|  |  |  |         for c in components: | 
					
						
							| 
									
										
										
										
											2023-10-02 11:52:00 -07:00
										 |  |  |             if c.script_name == name or c.frozen_name == f"Archipelago{name}": | 
					
						
							| 
									
										
										
										
											2022-03-31 05:08:15 +02:00
										 |  |  |                 component = c | 
					
						
							|  |  |  |                 break | 
					
						
							|  |  |  |         if not component: | 
					
						
							|  |  |  |             return None | 
					
						
							|  |  |  |     if is_frozen(): | 
					
						
							| 
									
										
										
										
											2023-10-02 11:52:00 -07:00
										 |  |  |         suffix = ".exe" if is_windows else "" | 
					
						
							|  |  |  |         return [local_path(f"{component.frozen_name}{suffix}")] if component.frozen_name else None | 
					
						
							| 
									
										
										
										
											2022-03-31 05:08:15 +02:00
										 |  |  |     else: | 
					
						
							| 
									
										
										
										
											2023-10-02 11:52:00 -07:00
										 |  |  |         return [sys.executable, local_path(f"{component.script_name}.py")] if component.script_name else None | 
					
						
							| 
									
										
										
										
											2022-03-31 05:08:15 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def launch(exe, in_terminal=False): | 
					
						
							|  |  |  |     if in_terminal: | 
					
						
							|  |  |  |         if is_windows: | 
					
						
							|  |  |  |             subprocess.Popen(['start', *exe], shell=True) | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         elif is_linux: | 
					
						
							|  |  |  |             terminal = which('x-terminal-emulator') or which('gnome-terminal') or which('xterm') | 
					
						
							|  |  |  |             if terminal: | 
					
						
							|  |  |  |                 subprocess.Popen([terminal, '-e', shlex.join(exe)]) | 
					
						
							|  |  |  |                 return | 
					
						
							|  |  |  |         elif is_macos: | 
					
						
							|  |  |  |             terminal = [which('open'), '-W', '-a', 'Terminal.app'] | 
					
						
							|  |  |  |             subprocess.Popen([*terminal, *exe]) | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |     subprocess.Popen(exe) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def run_gui(): | 
					
						
							| 
									
										
										
										
											2024-03-02 23:32:58 -06:00
										 |  |  |     from kvui import App, ContainerLayout, GridLayout, Button, Label, ScrollBox, Widget | 
					
						
							| 
									
										
										
										
											2023-04-30 18:10:58 +02:00
										 |  |  |     from kivy.uix.image import AsyncImage | 
					
						
							| 
									
										
										
										
											2023-04-17 02:35:54 +02:00
										 |  |  |     from kivy.uix.relativelayout import RelativeLayout | 
					
						
							| 
									
										
										
										
											2022-03-31 05:08:15 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     class Launcher(App): | 
					
						
							|  |  |  |         base_title: str = "Archipelago Launcher" | 
					
						
							|  |  |  |         container: ContainerLayout | 
					
						
							|  |  |  |         grid: GridLayout | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-19 09:57:17 +02:00
										 |  |  |         _tools = {c.display_name: c for c in components if c.type == Type.TOOL} | 
					
						
							|  |  |  |         _clients = {c.display_name: c for c in components if c.type == Type.CLIENT} | 
					
						
							|  |  |  |         _adjusters = {c.display_name: c for c in components if c.type == Type.ADJUSTER} | 
					
						
							|  |  |  |         _miscs = {c.display_name: c for c in components if c.type == Type.MISC} | 
					
						
							| 
									
										
										
										
											2022-03-31 05:08:15 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         def __init__(self, ctx=None): | 
					
						
							|  |  |  |             self.title = self.base_title | 
					
						
							|  |  |  |             self.ctx = ctx | 
					
						
							|  |  |  |             self.icon = r"data/icon.png" | 
					
						
							|  |  |  |             super().__init__() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def build(self): | 
					
						
							|  |  |  |             self.container = ContainerLayout() | 
					
						
							|  |  |  |             self.grid = GridLayout(cols=2) | 
					
						
							|  |  |  |             self.container.add_widget(self.grid) | 
					
						
							| 
									
										
										
										
											2024-03-02 23:32:58 -06:00
										 |  |  |             self.grid.add_widget(Label(text="General", size_hint_y=None, height=40)) | 
					
						
							|  |  |  |             self.grid.add_widget(Label(text="Clients", size_hint_y=None, height=40)) | 
					
						
							|  |  |  |             tool_layout = ScrollBox() | 
					
						
							|  |  |  |             tool_layout.layout.orientation = "vertical" | 
					
						
							|  |  |  |             self.grid.add_widget(tool_layout) | 
					
						
							|  |  |  |             client_layout = ScrollBox() | 
					
						
							|  |  |  |             client_layout.layout.orientation = "vertical" | 
					
						
							|  |  |  |             self.grid.add_widget(client_layout) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             def build_button(component: Component) -> Widget: | 
					
						
							| 
									
										
										
										
											2023-04-17 02:35:54 +02:00
										 |  |  |                 """
 | 
					
						
							|  |  |  |                 Builds a button widget for a given component. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 Args: | 
					
						
							|  |  |  |                     component (Component): The component associated with the button. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 Returns: | 
					
						
							|  |  |  |                     None. The button is added to the parent grid layout. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 """
 | 
					
						
							| 
									
										
										
										
											2024-03-02 23:32:58 -06:00
										 |  |  |                 button = Button(text=component.display_name, size_hint_y=None, height=40) | 
					
						
							| 
									
										
										
										
											2023-04-17 02:35:54 +02:00
										 |  |  |                 button.component = component | 
					
						
							|  |  |  |                 button.bind(on_release=self.component_action) | 
					
						
							|  |  |  |                 if component.icon != "icon": | 
					
						
							| 
									
										
										
										
											2023-04-30 18:10:58 +02:00
										 |  |  |                     image = AsyncImage(source=icon_paths[component.icon], | 
					
						
							|  |  |  |                                        size=(38, 38), size_hint=(None, 1), pos=(5, 0)) | 
					
						
							| 
									
										
										
										
											2024-03-02 23:32:58 -06:00
										 |  |  |                     box_layout = RelativeLayout(size_hint_y=None, height=40) | 
					
						
							| 
									
										
										
										
											2023-04-17 02:35:54 +02:00
										 |  |  |                     box_layout.add_widget(button) | 
					
						
							|  |  |  |                     box_layout.add_widget(image) | 
					
						
							| 
									
										
										
										
											2024-03-02 23:32:58 -06:00
										 |  |  |                     return box_layout | 
					
						
							|  |  |  |                 return button | 
					
						
							| 
									
										
										
										
											2023-04-17 02:35:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-31 05:08:15 +02:00
										 |  |  |             for (tool, client) in itertools.zip_longest(itertools.chain( | 
					
						
							| 
									
										
										
										
											2023-06-19 09:57:17 +02:00
										 |  |  |                     self._tools.items(), self._miscs.items(), self._adjusters.items()), self._clients.items()): | 
					
						
							| 
									
										
										
										
											2022-03-31 05:08:15 +02:00
										 |  |  |                 # column 1 | 
					
						
							|  |  |  |                 if tool: | 
					
						
							| 
									
										
										
										
											2024-03-02 23:32:58 -06:00
										 |  |  |                     tool_layout.layout.add_widget(build_button(tool[1])) | 
					
						
							| 
									
										
										
										
											2022-03-31 05:08:15 +02:00
										 |  |  |                 # column 2 | 
					
						
							|  |  |  |                 if client: | 
					
						
							| 
									
										
										
										
											2024-03-02 23:32:58 -06:00
										 |  |  |                     client_layout.layout.add_widget(build_button(client[1])) | 
					
						
							| 
									
										
										
										
											2022-03-31 05:08:15 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             return self.container | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         @staticmethod | 
					
						
							|  |  |  |         def component_action(button): | 
					
						
							| 
									
										
										
										
											2023-06-19 09:57:17 +02:00
										 |  |  |             if button.component.func: | 
					
						
							| 
									
										
										
										
											2022-03-31 05:08:15 +02:00
										 |  |  |                 button.component.func() | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 launch(get_exe(button.component), button.component.cli) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-27 09:30:54 +02:00
										 |  |  |         def _stop(self, *largs): | 
					
						
							|  |  |  |             # ran into what appears to be https://groups.google.com/g/kivy-users/c/saWDLoYCSZ4 with PyCharm. | 
					
						
							|  |  |  |             # Closing the window explicitly cleans it up. | 
					
						
							|  |  |  |             self.root_window.close() | 
					
						
							|  |  |  |             super()._stop(*largs) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-31 05:08:15 +02:00
										 |  |  |     Launcher().run() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-20 01:01:18 +02:00
										 |  |  | def run_component(component: Component, *args): | 
					
						
							|  |  |  |     if component.func: | 
					
						
							|  |  |  |         component.func(*args) | 
					
						
							|  |  |  |     elif component.script_name: | 
					
						
							|  |  |  |         subprocess.run([*get_exe(component.script_name), *args]) | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         logging.warning(f"Component {component} does not appear to be executable.") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-31 05:08:15 +02:00
										 |  |  | def main(args: Optional[Union[argparse.Namespace, dict]] = None): | 
					
						
							|  |  |  |     if isinstance(args, argparse.Namespace): | 
					
						
							|  |  |  |         args = {k: v for k, v in args._get_kwargs()} | 
					
						
							|  |  |  |     elif not args: | 
					
						
							|  |  |  |         args = {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if "Patch|Game|Component" in args: | 
					
						
							| 
									
										
										
										
											2023-06-20 01:01:18 +02:00
										 |  |  |         file, component = identify(args["Patch|Game|Component"]) | 
					
						
							| 
									
										
										
										
											2022-03-31 05:08:15 +02:00
										 |  |  |         if file: | 
					
						
							|  |  |  |             args['file'] = file | 
					
						
							|  |  |  |         if component: | 
					
						
							|  |  |  |             args['component'] = component | 
					
						
							| 
									
										
										
										
											2023-06-20 01:01:18 +02:00
										 |  |  |         if not component: | 
					
						
							|  |  |  |             logging.warning(f"Could not identify Component responsible for {args['Patch|Game|Component']}") | 
					
						
							| 
									
										
										
										
											2022-03-31 05:08:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-05 22:39:35 +02:00
										 |  |  |     if args["update_settings"]: | 
					
						
							|  |  |  |         update_settings() | 
					
						
							| 
									
										
										
										
											2022-03-31 05:08:15 +02:00
										 |  |  |     if 'file' in args: | 
					
						
							| 
									
										
										
										
											2023-06-20 01:01:18 +02:00
										 |  |  |         run_component(args["component"], args["file"], *args["args"]) | 
					
						
							| 
									
										
										
										
											2022-03-31 05:08:15 +02:00
										 |  |  |     elif 'component' in args: | 
					
						
							| 
									
										
										
										
											2023-06-20 01:01:18 +02:00
										 |  |  |         run_component(args["component"], *args["args"]) | 
					
						
							| 
									
										
										
										
											2023-07-05 22:39:35 +02:00
										 |  |  |     elif not args["update_settings"]: | 
					
						
							| 
									
										
										
										
											2022-03-31 05:08:15 +02:00
										 |  |  |         run_gui() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if __name__ == '__main__': | 
					
						
							|  |  |  |     init_logging('Launcher') | 
					
						
							| 
									
										
										
										
											2023-06-25 02:24:43 +02:00
										 |  |  |     Utils.freeze_support() | 
					
						
							|  |  |  |     multiprocessing.set_start_method("spawn")  # if launched process uses kivy, fork won't work | 
					
						
							| 
									
										
										
										
											2022-03-31 05:08:15 +02:00
										 |  |  |     parser = argparse.ArgumentParser(description='Archipelago Launcher') | 
					
						
							| 
									
										
										
										
											2023-07-05 22:39:35 +02:00
										 |  |  |     run_group = parser.add_argument_group("Run") | 
					
						
							|  |  |  |     run_group.add_argument("--update_settings", action="store_true", | 
					
						
							|  |  |  |                            help="Update host.yaml and exit.") | 
					
						
							|  |  |  |     run_group.add_argument("Patch|Game|Component", type=str, nargs="?", | 
					
						
							|  |  |  |                            help="Pass either a patch file, a generated game or the name of a component to run.") | 
					
						
							|  |  |  |     run_group.add_argument("args", nargs="*", | 
					
						
							|  |  |  |                            help="Arguments to pass to component.") | 
					
						
							| 
									
										
										
										
											2022-03-31 05:08:15 +02:00
										 |  |  |     main(parser.parse_args()) | 
					
						
							| 
									
										
										
										
											2023-06-27 09:30:54 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     from worlds.LauncherComponents import processes | 
					
						
							|  |  |  |     for process in processes: | 
					
						
							|  |  |  |         # we await all child processes to close before we tear down the process host | 
					
						
							|  |  |  |         # this makes it feel like each one is its own program, as the Launcher is closed now | 
					
						
							|  |  |  |         process.join() |