home · contact · privacy
Allow serving different protocols on different ports at the same time.
[plomrogue2-experiments] / new2 / plomrogue / io.py
index acf58d4adf177b2e5ce779d4a58a8c5f9b4c8b00..5450c343a031a721c64ae70289719f40729b1a7f 100644 (file)
@@ -1,4 +1,5 @@
 import queue
+import threading
 
 
 
@@ -6,10 +7,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 +21,24 @@ 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):
+        """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,))
+        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.
@@ -82,15 +77,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_id in self.game.sessions:
-                client = self.server.clients[c_id]
-                client.put(msg)
+                for server in self.servers:
+                    if c_id in server.clients:
+                        client = server.clients[c_id]
+                        client.put(msg)
+                        break