diff --git a/LttPClient.py b/LttPClient.py index 6ddd5879..5113fae9 100644 --- a/LttPClient.py +++ b/LttPClient.py @@ -1,5 +1,6 @@ import argparse import atexit +exit_func = atexit.register(input, "Press enter to close.") import threading import time import sys @@ -12,7 +13,6 @@ from json import loads, dumps from Utils import get_item_name_from_id -exit_func = atexit.register(input, "Press enter to close.") import ModuleUpdate @@ -54,7 +54,8 @@ class LttPCommandProcessor(ClientCommandProcessor): @mark_raw def _cmd_snes(self, snes_address: str = "") -> bool: - """Connect to a snes. Optionally include network address of a snes to connect to, otherwise show available devices""" + """Connect to a snes. + Optionally include network address of a snes to connect to, otherwise show available devices""" self.ctx.snes_reconnect_address = None asyncio.create_task(snes_connect(self.ctx, snes_address if snes_address else self.ctx.snes_address)) return True @@ -436,7 +437,10 @@ def launch_sni(ctx: Context): if os.path.isfile(sni_path): snes_logger.info(f"Attempting to start {sni_path}") import subprocess - subprocess.Popen(sni_path, cwd=os.path.dirname(sni_path), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + if Utils.is_frozen(): # if it spawns a visible console, may as well populate it + subprocess.Popen(sni_path, cwd=os.path.dirname(sni_path)) + else: + subprocess.Popen(sni_path, cwd=os.path.dirname(sni_path), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) else: snes_logger.info( f"Attempt to start SNI was aborted as path {sni_path} was not found, " @@ -495,7 +499,10 @@ async def get_snes_devices(ctx: Context): async def snes_connect(ctx: Context, address): global SNES_RECONNECT_DELAY if ctx.snes_socket is not None and ctx.snes_state == SNESState.SNES_CONNECTED: - snes_logger.error('Already connected to snes') + if ctx.rom: + snes_logger.error('Already connected to SNES, with rom loaded.') + else: + snes_logger.error('Already connected to SNI, likely awaiting a device.') return recv_task = None @@ -531,6 +538,7 @@ async def snes_connect(ctx: Context, address): ctx.snes_reconnect_address = address recv_task = asyncio.create_task(snes_recv_loop(ctx)) SNES_RECONNECT_DELAY = ctx.starting_reconnect_delay + snes_logger.info(f"Attached to {device}") except Exception as e: if recv_task is not None: diff --git a/Utils.py b/Utils.py index 7b9bb9bd..ddcfabfe 100644 --- a/Utils.py +++ b/Utils.py @@ -137,6 +137,7 @@ def open_file(filename): parse_yaml = safe_load unsafe_parse_yaml = functools.partial(load, Loader=Loader) + @cache_argsless def get_public_ipv4() -> str: import socket @@ -153,6 +154,7 @@ def get_public_ipv4() -> str: pass # we could be offline, in a local game, so no point in erroring out return ip + @cache_argsless def get_public_ipv6() -> str: import socket @@ -166,6 +168,7 @@ def get_public_ipv6() -> str: pass # we could be offline, in a local game, or ipv6 may not be available return ip + @cache_argsless def get_default_options() -> dict: # Refer to host.yaml for comments as to what all these options mean. @@ -217,14 +220,6 @@ def get_default_options() -> dict: return options -blacklisted_options = {"multi_mystery_options.cpu_threads", - "multi_mystery_options.max_attempts", - "multi_mystery_options.take_first_working", - "multi_mystery_options.keep_all_seeds", - "multi_mystery_options.log_output_path", - "multi_mystery_options.log_level"} - - def update_options(src: dict, dest: dict, filename: str, keys: list) -> dict: import logging for key, value in src.items(): @@ -233,17 +228,18 @@ def update_options(src: dict, dest: dict, filename: str, keys: list) -> dict: option_name = '.'.join(new_keys) if key not in dest: dest[key] = value - if filename.endswith("options.yaml") and option_name not in blacklisted_options: + if filename.endswith("options.yaml"): logging.info(f"Warning: {filename} is missing {option_name}") elif isinstance(value, dict): if not isinstance(dest.get(key, None), dict): - if filename.endswith("options.yaml") and option_name not in blacklisted_options: + if filename.endswith("options.yaml"): logging.info(f"Warning: {filename} has {option_name}, but it is not a dictionary. overwriting.") dest[key] = value else: dest[key] = update_options(value, dest[key], filename, new_keys) return dest + @cache_argsless def get_options() -> dict: if not hasattr(get_options, "options"): diff --git a/inno_setup_38.iss b/inno_setup_38.iss index c6788b78..007b88e2 100644 --- a/inno_setup_38.iss +++ b/inno_setup_38.iss @@ -86,8 +86,8 @@ Type: dirifempty; Name: "{app}" Root: HKCR; Subkey: ".apbp"; ValueData: "{#MyAppName}patch"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""; Components: client/lttp Root: HKCR; Subkey: "{#MyAppName}patch"; ValueData: "Archipelago Binary Patch"; Flags: uninsdeletekey; ValueType: string; ValueName: ""; Components: client/lttp -Root: HKCR; Subkey: "{#MyAppName}patch\DefaultIcon"; ValueData: "{app}\{#MyAppExeName},0"; ValueType: string; ValueName: ""; Components: client/lttp -Root: HKCR; Subkey: "{#MyAppName}patch\shell\open\command"; ValueData: """{app}\{#MyAppExeName}"" ""%1"""; ValueType: string; ValueName: ""; Components: client/lttp +Root: HKCR; Subkey: "{#MyAppName}patch\DefaultIcon"; ValueData: "{app}\ArchipelagoLttPClient.exe,0"; ValueType: string; ValueName: ""; Components: client/lttp +Root: HKCR; Subkey: "{#MyAppName}patch\shell\open\command"; ValueData: """{app}\ArchipelagoLttPClient.exe"" ""%1"""; ValueType: string; ValueName: ""; Components: client/lttp Root: HKCR; Subkey: ".archipelago"; ValueData: "{#MyAppName}multidata"; Flags: uninsdeletevalue; ValueType: string; ValueName: ""; Components: server Root: HKCR; Subkey: "{#MyAppName}multidata"; ValueData: "Archipelago Server Data"; Flags: uninsdeletekey; ValueType: string; ValueName: ""; Components: server