<gh_stars>0
import select
import sys
import asyncio
import websockets

import game.game as g

# checks whether sufficient arguments have been provided
if len(sys.argv) != 3:
    print("Correct usage: script.py, IP address, port number")
    exit()

print("Start-up successful")

# takes the first argument from command prompt as IP address
IP_address = str(sys.argv[1])

# takes second argument from command prompt as port number
Port = int(sys.argv[2])


class GameServer():

    def __init__(self):
        """
        Constructor for game server

        Asynch threadsafety via monitor pattern

        GameServer contains client connections and game instance
            clients are in dictionary, mapping username to websocket connection
        """
        self.lock = asyncio.Lock()
        self.client_connections = dict()
        self.game = g.Game()

    async def add_client(self, clientName, clientConnection):
        """
        Add the client connection object to the GameServer
        """
        async with self.lock:
            if clientName not in self.client_connections:
                print("Added: ", clientName)
                self.client_connections[clientName] = clientConnection
                return True
            else:
                print("Add rejected: ", clientName)
                return False

    async def remove_client(self, clientName):
        """
        Removes the client connection object from the GameServer
        """
        async with self.lock:
            if clientName in self.client_connections:
                print("Removed: ", clientName)
                del self.client_connections[clientName]

    async def input_to_game(self, clientName, message):
        """
        Send message to game, get immediate responses
        """
        async with self.lock:
            message_to_print = clientName + "> " + str(message)
            print(message_to_print)

            game_responses = self.game.input(clientName, message)

            await self.send_responses(game_responses)

    async def get_game_updates(self):
        """
        Get updates from game as responses
        """
        async with self.lock:
            game_responses = self.game.update()

            await self.send_responses(game_responses)

    async def send_responses(self, game_responses):
        """
        Takes list of game responses, sends response messages to respective clients

        For in class use only. Does not lock object so
        """
        for game_response in game_responses:
            for res_user, res_message in game_response:
                if res_user in self.client_connections:
                    await self.client_connections[res_user].send(res_message)


server = GameServer()

async def client_coroutine(client, path):
    """
    Takes client websocket connection and processes inputs
    """

    # Setup GameServer for client coroutine

    added_to_server = False
    username = None

    while not added_to_server:
        await client.send("What is your desired username?")

        try:
            message = await client.recv()
            if message:
                # Try to add connection as username to client
                username = str(message)
                added_to_server = await server.add_client(username, client)
                if added_to_server:
                    await client.send("Username accepted!")
                else:
                    await client.send("Username is taken...")

        except Exception as e:
            # Raised exception or connection closed:
            #   remove connection from list and end async thread
            print(e)
            return

    # Receive messages and send to GameServer
    while True:
        try:
            message = await client.recv()
            if message:
                # Calls broadcast function to send message to all
                #   broadcast(message_to_send, conn)
                await server.input_to_game(username, message)

        except Exception as e:
            # Raised exception or connection closed:
            #   remove connection from list and end async thread
            print(e)
            await server.remove_client(username)
            return

async def game_update_coroutine():
    """
    Calls updates for game
    """
    while True:
        try:
            await asyncio.sleep(0.1)
            await server.get_game_updates()

        except Exception as e:
            print(e)
            return

# Start websockets server with client coroutine
start_server = websockets.serve(client_coroutine, IP_address, Port)
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.gather(
    game_update_coroutine(),
    start_server
))
loop.run_forever()

import select
import sys
import asyncio
import websockets

import game.game as g

# checks whether sufficient arguments have been provided
if len(sys.argv) != 3:
    print("Correct usage: script.py, IP address, port number")
    exit()

print("Start-up successful")

# takes the first argument from command prompt as IP address
IP_address = str(sys.argv[1])

# takes second argument from command prompt as port number
Port = int(sys.argv[2])


class GameServer():

    def __init__(self):
        """
        Constructor for game server

        Asynch threadsafety via monitor pattern

        GameServer contains client connections and game instance
            clients are in dictionary, mapping username to websocket connection
        """
        self.lock = asyncio.Lock()
        self.client_connections = dict()
        self.game = g.Game()

    async def add_client(self, clientName, clientConnection):
        """
        Add the client connection object to the GameServer
        """
        async with self.lock:
            if clientName not in self.client_connections:
                print("Added: ", clientName)
                self.client_connections[clientName] = clientConnection
                return True
            else:
                print("Add rejected: ", clientName)
                return False

    async def remove_client(self, clientName):
        """
        Removes the client connection object from the GameServer
        """
        async with self.lock:
            if clientName in self.client_connections:
                print("Removed: ", clientName)
                del self.client_connections[clientName]

    async def input_to_game(self, clientName, message):
        """
        Send message to game, get immediate responses
        """
        async with self.lock:
            message_to_print = clientName + "> " + str(message)
            print(message_to_print)

            game_responses = self.game.input(clientName, message)

            await self.send_responses(game_responses)

    async def get_game_updates(self):
        """
        Get updates from game as responses
        """
        async with self.lock:
            game_responses = self.game.update()

            await self.send_responses(game_responses)

    async def send_responses(self, game_responses):
        """
        Takes list of game responses, sends response messages to respective clients

        For in class use only. Does not lock object so
        """
        for game_response in game_responses:
            for res_user, res_message in game_response:
                if res_user in self.client_connections:
                    await self.client_connections[res_user].send(res_message)


server = GameServer()

async def client_coroutine(client, path):
    """
    Takes client websocket connection and processes inputs
    """

    # Setup GameServer for client coroutine

    added_to_server = False
    username = None

    while not added_to_server:
        await client.send("What is your desired username?")

        try:
            message = await client.recv()
            if message:
                # Try to add connection as username to client
                username = str(message)
                added_to_server = await server.add_client(username, client)
                if added_to_server:
                    await client.send("Username accepted!")
                else:
                    await client.send("Username is taken...")

        except Exception as e:
            # Raised exception or connection closed:
            #   remove connection from list and end async thread
            print(e)
            return

    # Receive messages and send to GameServer
    while True:
        try:
            message = await client.recv()
            if message:
                # Calls broadcast function to send message to all
                #   broadcast(message_to_send, conn)
                await server.input_to_game(username, message)

        except Exception as e:
            # Raised exception or connection closed:
            #   remove connection from list and end async thread
            print(e)
            await server.remove_client(username)
            return

async def game_update_coroutine():
    """
    Calls updates for game
    """
    while True:
        try:
            await asyncio.sleep(0.1)
            await server.get_game_updates()

        except Exception as e:
            print(e)
            return

# Start websockets server with client coroutine
start_server = websockets.serve(client_coroutine, IP_address, Port)
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.gather(
    game_update_coroutine(),
    start_server
))
loop.run_forever()
# checks whether sufficient arguments have been provided # takes the first argument from command prompt as IP address # takes second argument from command prompt as port number Constructor for game server          Asynch threadsafety via monitor pattern          GameServer contains client connections and game instance             clients are in dictionary, mapping username to websocket connection Add the client connection object to the GameServer Removes the client connection object from the GameServer Send message to game, get immediate responses Get updates from game as responses Takes list of game responses, sends response messages to respective clients          For in class use only. Does not lock object so Takes client websocket connection and processes inputs # Setup GameServer for client coroutine # Try to add connection as username to client # Raised exception or connection closed: #   remove connection from list and end async thread # Receive messages and send to GameServer # Calls broadcast function to send message to all #   broadcast(message_to_send, conn) # Raised exception or connection closed: #   remove connection from list and end async thread Calls updates for game # Start websockets server with client coroutine