From 2a05b9cd729ee3cbb81aa0ef9bcc9065485579c6 Mon Sep 17 00:00:00 2001 From: Fabian Dill Date: Fri, 13 Mar 2020 03:53:20 +0100 Subject: [PATCH] move to promp_toolkit --- MultiClient.py | 119 ++++++++++++++++++++++++----------------------- MultiServer.py | 14 ++++-- Regions.py | 27 +++++++---- requirements.txt | 4 +- 4 files changed, 90 insertions(+), 74 deletions(-) diff --git a/MultiClient.py b/MultiClient.py index f96bf63a..a81e6cab 100644 --- a/MultiClient.py +++ b/MultiClient.py @@ -19,12 +19,8 @@ ModuleUpdate.update() import colorama import websockets -import aioconsole - -try: - import tqdm -except: - tqdm = None +import prompt_toolkit +from prompt_toolkit.patch_stdout import patch_stdout import Items import Regions @@ -439,12 +435,13 @@ async def snes_connect(ctx : Context, address): logging.error(f"Error connecting to snes, attempt again in {RECONNECT_DELAY}s") asyncio.create_task(snes_autoreconnect(ctx)) + async def snes_autoreconnect(ctx: Context): - if tqdm: - for _ in tqdm.trange(100, unit='%', leave=False): - await asyncio.sleep(RECONNECT_DELAY/100) - else: - await asyncio.sleep(RECONNECT_DELAY) + # unfortunately currently broken. See: https://github.com/prompt-toolkit/python-prompt-toolkit/issues/1033 + # with prompt_toolkit.shortcuts.ProgressBar() as pb: + # for _ in pb(range(100)): + # await asyncio.sleep(RECONNECT_DELAY/100) + await asyncio.sleep(RECONNECT_DELAY) if ctx.snes_reconnect_address and ctx.snes_socket is None: await snes_connect(ctx, ctx.snes_reconnect_address) @@ -629,12 +626,13 @@ async def server_loop(ctx : Context, address = None): logging.info(f"... reconnecting in {RECONNECT_DELAY}s") asyncio.create_task(server_autoreconnect(ctx)) + async def server_autoreconnect(ctx: Context): - if tqdm: - for _ in tqdm.trange(100, unit='%', leave=False): - await asyncio.sleep(RECONNECT_DELAY/100) - else: - await asyncio.sleep(RECONNECT_DELAY) + # unfortunately currently broken. See: https://github.com/prompt-toolkit/python-prompt-toolkit/issues/1033 + # with prompt_toolkit.shortcuts.ProgressBar() as pb: + # for _ in pb(range(100)): + # await asyncio.sleep(RECONNECT_DELAY/100) + await asyncio.sleep(RECONNECT_DELAY) if ctx.server_address and ctx.server_task is None: ctx.server_task = asyncio.create_task(server_loop(ctx)) @@ -764,63 +762,68 @@ async def connect(ctx: Context, address=None): await disconnect(ctx) ctx.server_task = asyncio.create_task(server_loop(ctx, address)) + async def console_loop(ctx : Context): + session = prompt_toolkit.PromptSession() while not ctx.exit_event.is_set(): - input = await aioconsole.ainput() + try: + with patch_stdout(): + input_text = await session.prompt_async() - if ctx.input_requests > 0: - ctx.input_requests -= 1 - ctx.input_queue.put_nowait(input) - continue + if ctx.input_requests > 0: + ctx.input_requests -= 1 + ctx.input_queue.put_nowait(input_text) + continue - command = input.split() - if not command: - continue + command = input_text.split() + if not command: + continue - if command[0][:1] != '/': - asyncio.create_task(send_msgs(ctx.socket, [['Say', input]])) - continue + if command[0][:1] != '/': + asyncio.create_task(send_msgs(ctx.socket, [['Say', input_text]])) + continue - precommand = command[0][1:] + precommand = command[0][1:] - if precommand == 'exit': - ctx.exit_event.set() + if precommand == 'exit': + ctx.exit_event.set() - elif precommand == 'snes': - ctx.snes_reconnect_address = None - asyncio.create_task(snes_connect(ctx, command[1] if len(command) > 1 else ctx.snes_address)) + elif precommand == 'snes': + ctx.snes_reconnect_address = None + asyncio.create_task(snes_connect(ctx, command[1] if len(command) > 1 else ctx.snes_address)) - elif precommand in {'snes_close', 'snes_quit'}: - ctx.snes_reconnect_address = None - if ctx.snes_socket is not None and not ctx.snes_socket.closed: - await ctx.snes_socket.close() + elif precommand in {'snes_close', 'snes_quit'}: + ctx.snes_reconnect_address = None + if ctx.snes_socket is not None and not ctx.snes_socket.closed: + await ctx.snes_socket.close() - elif precommand in {'connect', 'reconnect'}: - ctx.server_address = None - asyncio.create_task(connect(ctx, command[1] if len(command) > 1 else None)) + elif precommand in {'connect', 'reconnect'}: + ctx.server_address = None + asyncio.create_task(connect(ctx, command[1] if len(command) > 1 else None)) - elif precommand == 'disconnect': - ctx.server_address = None - asyncio.create_task(disconnect(ctx)) + elif precommand == 'disconnect': + ctx.server_address = None + asyncio.create_task(disconnect(ctx)) - elif precommand == 'received': - logging.info('Received items:') - for index, item in enumerate(ctx.items_received, 1): - logging.info('%s from %s (%s) (%d/%d in list)' % ( - color(get_item_name_from_id(item.item), 'red', 'bold'), - color(ctx.player_names[item.player], 'yellow'), - get_location_name_from_address(item.location), index, len(ctx.items_received))) + elif precommand == 'received': + logging.info('Received items:') + for index, item in enumerate(ctx.items_received, 1): + logging.info('%s from %s (%s) (%d/%d in list)' % ( + color(get_item_name_from_id(item.item), 'red', 'bold'), + color(ctx.player_names[item.player], 'yellow'), + get_location_name_from_address(item.location), index, len(ctx.items_received))) - elif precommand == 'missing': - for location in [k for k, v in Regions.location_table.items() if type(v[0]) is int]: - if location not in ctx.locations_checked: - logging.info('Missing: ' + location) - - elif precommand == "license": - with open("LICENSE") as f: - logging.info(f.read()) + elif precommand == 'missing': + for location in [k for k, v in Regions.location_table.items() if type(v[0]) is int]: + if location not in ctx.locations_checked: + logging.info('Missing: ' + location) + elif precommand == "license": + with open("LICENSE") as f: + logging.info(f.read()) + except Exception as e: + logging.exception(e) await snes_flush_writes(ctx) def get_item_name_from_id(code): diff --git a/MultiServer.py b/MultiServer.py index e6ee3b8b..17e30280 100644 --- a/MultiServer.py +++ b/MultiServer.py @@ -9,10 +9,12 @@ import typing import os import ModuleUpdate + ModuleUpdate.update() import websockets -import aioconsole +import prompt_toolkit +from prompt_toolkit.patch_stdout import patch_stdout from fuzzywuzzy import process as fuzzy_process import Items @@ -488,12 +490,14 @@ def set_password(ctx : Context, password): async def console(ctx: Context): + session = prompt_toolkit.PromptSession() running = True while running: - input = await aioconsole.ainput() + with patch_stdout(): + input_text = await session.prompt_async() try: - command = input.split() + command = input_text.split() if not command: continue @@ -536,7 +540,7 @@ async def console(ctx: Context): if usable: for client in ctx.clients: if client.name == seeked_player: - new_item = ReceivedItem(Items.item_table[item][3], "cheat console", client.slot) + new_item = ReceivedItem(Items.item_table[item][3], -1, client.slot) get_received_items(ctx, client.team, client.slot).append(new_item) notify_all(ctx, 'Cheat console: sending "' + item + '" to ' + client.name) send_new_items(ctx) @@ -567,7 +571,7 @@ async def console(ctx: Context): logging.warning(response) if command[0][0] != '/': - notify_all(ctx, '[Server]: ' + input) + notify_all(ctx, '[Server]: ' + input_text) except: import traceback traceback.print_exc() diff --git a/Regions.py b/Regions.py index 5011b85c..8ad5716b 100644 --- a/Regions.py +++ b/Regions.py @@ -612,13 +612,22 @@ location_table = {'Mushroom': (0x180013, 0x186338, False, 'in the woods'), 'Dark Blacksmith Ruins': (None, None, False, None), 'Eastern Palace - Prize': ([0x1209D, 0x53EF8, 0x53EF9, 0x180052, 0x18007C, 0xC6FE], None, True, 'Eastern Palace'), 'Desert Palace - Prize': ([0x1209E, 0x53F1C, 0x53F1D, 0x180053, 0x180078, 0xC6FF], None, True, 'Desert Palace'), - 'Tower of Hera - Prize': ([0x120A5, 0x53F0A, 0x53F0B, 0x18005A, 0x18007A, 0xC706], None, True, 'Tower of Hera'), - 'Palace of Darkness - Prize': ([0x120A1, 0x53F00, 0x53F01, 0x180056, 0x18007D, 0xC702], None, True, 'Palace of Darkness'), - 'Swamp Palace - Prize': ([0x120A0, 0x53F6C, 0x53F6D, 0x180055, 0x180071, 0xC701], None, True, 'Swamp Palace'), - 'Thieves\' Town - Prize': ([0x120A6, 0x53F36, 0x53F37, 0x18005B, 0x180077, 0xC707], None, True, 'Thieves\' Town'), - 'Skull Woods - Prize': ([0x120A3, 0x53F12, 0x53F13, 0x180058, 0x18007B, 0xC704], None, True, 'Skull Woods'), - 'Ice Palace - Prize': ([0x120A4, 0x53F5A, 0x53F5B, 0x180059, 0x180073, 0xC705], None, True, 'Ice Palace'), - 'Misery Mire - Prize': ([0x120A2, 0x53F48, 0x53F49, 0x180057, 0x180075, 0xC703], None, True, 'Misery Mire'), - 'Turtle Rock - Prize': ([0x120A7, 0x53F24, 0x53F25, 0x18005C, 0x180079, 0xC708], None, True, 'Turtle Rock')} + 'Tower of Hera - Prize': ( + [0x120A5, 0x53F0A, 0x53F0B, 0x18005A, 0x18007A, 0xC706], None, True, 'Tower of Hera'), + 'Palace of Darkness - Prize': ( + [0x120A1, 0x53F00, 0x53F01, 0x180056, 0x18007D, 0xC702], None, True, 'Palace of Darkness'), + 'Swamp Palace - Prize': ( + [0x120A0, 0x53F6C, 0x53F6D, 0x180055, 0x180071, 0xC701], None, True, 'Swamp Palace'), + 'Thieves\' Town - Prize': ( + [0x120A6, 0x53F36, 0x53F37, 0x18005B, 0x180077, 0xC707], None, True, 'Thieves\' Town'), + 'Skull Woods - Prize': ( + [0x120A3, 0x53F12, 0x53F13, 0x180058, 0x18007B, 0xC704], None, True, 'Skull Woods'), + 'Ice Palace - Prize': ( + [0x120A4, 0x53F5A, 0x53F5B, 0x180059, 0x180073, 0xC705], None, True, 'Ice Palace'), + 'Misery Mire - Prize': ( + [0x120A2, 0x53F48, 0x53F49, 0x180057, 0x180075, 0xC703], None, True, 'Misery Mire'), + 'Turtle Rock - Prize': ( + [0x120A7, 0x53F24, 0x53F25, 0x18005C, 0x180079, 0xC708], None, True, 'Turtle Rock')} -lookup_id_to_name = {data[0] : name for name, data in location_table.items() if type(data[0]) == int} \ No newline at end of file +lookup_id_to_name = {data[0]: name for name, data in location_table.items() if type(data[0]) == int} +lookup_id_to_name[-1] = "cheat console" diff --git a/requirements.txt b/requirements.txt index c0524216..a2e16cbe 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ -aioconsole>=0.1.15 colorama>=0.4.3 websockets>=8.1 PyYAML>=5.3 fuzzywuzzy>=0.18.0 bsdiff4>=1.1.9 -upnpy>=1.1.5 \ No newline at end of file +upnpy>=1.1.5 +prompt_toolkit>=3.0.4 \ No newline at end of file