from atexit import register from sys import argv from threading import Thread from cheat import Cheat, sleep # type: ignore def do_on_exit(cheats: Cheat, running: list) -> None: """Called when the program end""" for fn in running: try: unloader = getattr(cheats, f"{fn}_unload") except: pass else: print(f"Unload {fn}...") unloader() if __name__ == "__main__": c_id = [] args = {} wanted_list = [] if len(argv) > 1: # User wanna use offline offsets if "--offline" in argv: args["offline"] = True # User gave a list of cheats # Will bypass the interactive selection wanted_list = [ j for j in [i for i in argv if i.startswith("--list=")][0][7:].split(",") ] # Load cheat class c = Cheat(**args) # Load user list c_id = [c.cheats_list.index(cheat) for cheat in wanted_list] # Interactive selection if c_id == []: # Cheat list print( "You can run multiples cheat at once, separate your choices with a space." ) print("Available cheats:") for idx, cheat in enumerate(c.cheats_list): print(f"#{idx + 1} - {cheat}") while c_id == []: try: response = [int(i) for i in input("Enter ID: ").split(" ")] for i in response: if i > len(c.cheats_list) or i <= 0: raise IndexError c_id.append(i - 1) except KeyboardInterrupt: print("Bye") exit(1) except: # noqa: E722 c_id = [] print("Invalid ID.") # Instanciate and run threads running = [] for fn in [c.cheats_list[i] for i in c_id]: # Set of incompatible cheat with fn incompatible = set(c.incompatible[fn]).intersection(running) if not len(incompatible): running.append(fn) print(f"Running {fn}...") t = Thread(target=getattr(c, fn)) t.daemon = True t.start() else: print(f"{fn} is incompatible with: {', '.join(incompatible)}") register(do_on_exit, c, running) # Don't close the main thread as cheats are daemons while True: sleep(1000000)