X-Git-Url: https://plomlompom.com/repos/?a=blobdiff_plain;f=new2%2Fplomrogue%2Fio.py;h=8e0f9bf530548572eb7c07d389d7188e19af47d1;hb=b747db93005261dbf46c657099be0bf687ad2ce3;hp=908d7bf504b7c304c937729b1bb5cccb3f47538b;hpb=1d9e41e7df05336a6688382c9374c547979cf11e;p=plomrogue2-experiments diff --git a/new2/plomrogue/io.py b/new2/plomrogue/io.py index 908d7bf..8e0f9bf 100644 --- a/new2/plomrogue/io.py +++ b/new2/plomrogue/io.py @@ -1,4 +1,6 @@ import queue +import threading +import inspect @@ -6,10 +8,10 @@ class GameIO(): def __init__(self, game, save_file='savefile'): from plomrogue.parser import Parser - self.clients = {} self.parser = Parser(game) self.game = game self.save_file = save_file + self.servers = [] def loop(self, q): """Handle commands coming through queue q, run game, send results back.""" @@ -20,30 +22,27 @@ class GameIO(): except queue.Empty: self.game.run_tick() - def run_loop_with_server(self, port, server_class): - """Run connection of server talking to clients and game IO loop. + def start_loop(self): + """Start game loop, set up self.queue to communicate with it. - We have a server of self.server_class and we have the game IO loop, - a thread running self.loop. Both communicate with each other via a - queue.Queue. While the server may spawn parallel threads to many - clients, the IO loop works sequentially through game commands - received from the server's client connections. A processed command - may trigger messages to the commanding client or to all clients, - delivered from the IO loop to the server via the queue. + The game loop works sequentially through game commands received + via self.queue from connected servers' clients.""" + self.queue = queue.Queue() + c = threading.Thread(target=self.loop, args=(self.queue,)) + c.start() + + def start_server(self, port, server_class, certfile=None, keyfile=None): + """Start server of server_class in talk with game loop. + The server communicates with the game loop via self.queue. """ - import threading - q = queue.Queue() - c = threading.Thread(target=self.loop, daemon=True, args=(q,)) + if 'certfile' in list(inspect.signature(server_class.__init__).parameters): + server = server_class(self.queue, port, certfile=certfile, keyfile=keyfile) + else: + server = server_class(self.queue, port) + self.servers += [server] + c = threading.Thread(target=server.serve_forever) c.start() - self.server = server_class(q, port) - try: - self.server.serve_forever() - except KeyboardInterrupt: - pass - finally: - print('Killing server') - self.server.server_close() def handle_input(self, input_, connection_id=None, god_mode=False): """Process input_ to command grammar, call command handler if found. @@ -52,7 +51,6 @@ class GameIO(): signature will only be called if god_mode is set. """ - from inspect import signature from plomrogue.errors import GameError, ArgError, PlayError from plomrogue.misc import quote @@ -67,7 +65,7 @@ class GameIO(): if command is None: answer(connection_id, 'UNHANDLED_INPUT') else: - if 'connection_id' in list(signature(command).parameters): + if 'connection_id' in list(inspect.signature(command).parameters): command(*args, connection_id=connection_id) elif god_mode: command(*args) @@ -82,14 +80,21 @@ class GameIO(): answer(connection_id, 'GAME_ERROR ' + quote(str(e))) def send(self, msg, connection_id=None): - """Send message msg to server's client(s). + """Send message msg to servers' client(s). If a specific client is identified by connection_id, only - sends msg to that one. Else, sends it to all clients. + sends msg to that one. Else, sends it to all client sessions. """ if connection_id: - self.server.clients[connection_id].put(msg) + for server in self.servers: + if connection_id in server.clients: + client = server.clients[connection_id] + client.put(msg) else: - for c in self.server.clients.values(): - c.put(msg) + for c_id in self.game.sessions: + for server in self.servers: + if c_id in server.clients: + client = server.clients[c_id] + client.put(msg) + break