From: Christian Heller Date: Wed, 26 May 2021 23:28:39 +0000 (+0200) Subject: Actually commit the previously forgotten rogue_chat curses client refactor. X-Git-Url: https://plomlompom.com/repos/%7B%7Bdb.prefix%7D%7D/static/%7B%7B%20web_path%20%7D%7D/decks/todo?a=commitdiff_plain;h=38a55f96dcd90f0f434b2fbcdc8a3dc943d737ed;p=plomrogue2 Actually commit the previously forgotten rogue_chat curses client refactor. --- diff --git a/rogue_chat_curses.py b/rogue_chat_curses.py index d2cc704..b4ac8e5 100755 --- a/rogue_chat_curses.py +++ b/rogue_chat_curses.py @@ -1,15 +1,15 @@ #!/usr/bin/env python3 import curses -import queue -import threading -import time import sys from plomrogue.game import GameBase from plomrogue.parser import Parser from plomrogue.mapping import YX, MapGeometrySquare, MapGeometryHex from plomrogue.things import ThingBase from plomrogue.misc import quote -from plomrogue.errors import BrokenSocketConnection, ArgError +from plomrogue.errors import ArgError +from plomrogue_client.socket import ClientSocket + + mode_helps = { 'play': { @@ -133,46 +133,6 @@ mode_helps = { } } -from ws4py.client import WebSocketBaseClient -class WebSocketClient(WebSocketBaseClient): - - def __init__(self, recv_handler, *args, **kwargs): - super().__init__(*args, **kwargs) - self.recv_handler = recv_handler - self.connect() - - def received_message(self, message): - if message.is_text: - message = str(message) - self.recv_handler(message) - - @property - def plom_closed(self): - return self.client_terminated - -from plomrogue.io_tcp import PlomSocket -class PlomSocketClient(PlomSocket): - - def __init__(self, recv_handler, url): - import socket - self.recv_handler = recv_handler - host, port = url.split(':') - super().__init__(socket.create_connection((host, port))) - - def close(self): - self.socket.close() - - def run(self): - import ssl - try: - for msg in self.recv(): - if msg == 'NEED_SSL': - self.socket = ssl.wrap_socket(self.socket) - continue - self.recv_handler(msg) - except BrokenSocketConnection: - pass # we assume socket will be known as dead by now - def cmd_TURN(game, n): game.turn_complete = False cmd_TURN.argtypes = 'int:nonneg' @@ -533,13 +493,12 @@ class TUI: self.mode_edit.available_actions = ["move", "flatten", "install", "toggle_map_mode"] self.mode = None - self.host = host + self.socket = ClientSocket(host, self.socket_log) self.game = Game() self.game.tui = self self.parser = Parser(self.game) self.log = [] self.do_refresh = True - self.queue = queue.Queue() self.login_name = None self.map_mode = 'terrain + things' self.password = 'foo' @@ -591,8 +550,6 @@ class TUI: for k in keys_conf: self.keys[k] = keys_conf[k] self.show_help = False - self.disconnected = True - self.force_instant_connect = True self.input_lines = [] self.fov = '' self.flash = False @@ -602,56 +559,30 @@ class TUI: self.offset = YX(0,0) curses.wrapper(self.loop) - def connect(self): - - def handle_recv(msg): - if msg == 'BYE': - self.socket.close() - else: - self.queue.put(msg) - - self.log_msg('@ attempting connect') - socket_client_class = PlomSocketClient - if self.host.startswith('ws://') or self.host.startswith('wss://'): - socket_client_class = WebSocketClient - try: - self.socket = socket_client_class(handle_recv, self.host) - self.socket_thread = threading.Thread(target=self.socket.run) - self.socket_thread.start() - self.disconnected = False - self.game.thing_types = {} - self.game.terrains = {} - self.is_admin = False - time.sleep(0.1) # give potential SSL negotation some time … - self.socket.send('TASKS') - self.socket.send('TERRAINS') - self.socket.send('THING_TYPES') - self.switch_mode('login') - except ConnectionRefusedError: - self.log_msg('@ server connect failure') - self.disconnected = True - self.switch_mode('waiting_for_server') - self.do_refresh = True + def update_on_connect(self): + self.socket.send('TASKS') + self.socket.send('TERRAINS') + self.socket.send('THING_TYPES') + self.switch_mode('login') def reconnect(self): + import time self.log_msg('@ attempting reconnect') - self.send('QUIT') + self.socket.send('QUIT') # necessitated by some strange SSL race conditions with ws4py time.sleep(0.1) # FIXME find out why exactly necessary self.switch_mode('waiting_for_server') - self.connect() + self.socket.connect() + self.update_on_connect() def send(self, msg): - try: - if hasattr(self.socket, 'plom_closed') and self.socket.plom_closed: - raise BrokenSocketConnection - self.socket.send(msg) - except (BrokenPipeError, BrokenSocketConnection): - self.log_msg('@ server disconnected :(') - self.disconnected = True - self.force_instant_connect = True + self.socket.send(msg) + if self.socket.disconnected: self.do_refresh = True + def socket_log(self, msg): + self.log_msg('@ ' + msg) + def log_msg(self, msg): self.log += [msg] if len(self.log) > 100: @@ -902,7 +833,6 @@ class TUI: return info def loop(self, stdscr): - import datetime def safe_addstr(y, x, line): if y < self.size.y - 1 or x + len(line) < self.size.x: @@ -1273,31 +1203,19 @@ class TUI: self.input_ = '' store_widechar = False input_prompt = '> ' - interval = datetime.timedelta(seconds=5) - last_ping = datetime.datetime.now() - interval while True: - if self.disconnected and self.force_instant_connect: - self.force_instant_connect = False - self.connect() - now = datetime.datetime.now() - if now - last_ping > interval: - if self.disconnected: - self.connect() - else: - self.send('PING') - last_ping = now + prev_disconnected = self.socket.disconnected + self.socket.keep_connection_alive() + if prev_disconnected and not self.socket.disconnected: + self.update_on_connect() if self.flash: curses.flash() self.flash = False if self.do_refresh: draw_screen() self.do_refresh = False - while True: - try: - msg = self.queue.get(block=False) - handle_input(msg) - except queue.Empty: - break + for msg in self.socket.get_message(): + handle_input(msg) try: key = stdscr.getkey() self.do_refresh = True @@ -1453,7 +1371,7 @@ class TUI: self.send('TASK:DANCE') elif key == self.keys['teleport']: if self.game.player.position in self.game.portals: - self.host = self.game.portals[self.game.player.position] + self.socket.host = self.game.portals[self.game.player.position] self.reconnect() else: self.flash = True