summaryrefslogtreecommitdiff
path: root/swiftstory/__main__.py
blob: 0b5d7c7a2020fd6d9914276a61fa9944f88c4881 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#!/usr/bin/env python3

""" Entry point to play the game. """

import argparse
import asyncio
import contextlib
import json
import logging
import websockets

import swiftstory.GameManager
from swiftstory.exception import WrongAction, JoinError
from swiftstory.Client import Client
from swiftstory.Status import error


game_manager = swiftstory.GameManager.GameManager()


def message_received_handler(client, message):
    def join_game():
        try:
            game_name = json_msg['game_name']
        except KeyError:
            return error('field `game_name\' is required')
        else:
            lang = json_msg.get('lang')
            return client.join_game(game_name, lang)

    def designate_card():
        card_id = None
        try:
            card_id = int(json_msg['card_id'])
        except (KeyError, TypeError):
            pass
        finally:
            return client.designate_card(card_id)

    def play_white_card():
        try:
            card_id = int(json_msg['card_id'])
        except KeyError:
            return error('field `card_id\' is required')
        else:
            return client.play_white_card(card_id)

    opcodes_map = {
        "join_game": join_game,
        "view_player_cards": lambda: client.view_player_cards(),
        "view_black_card": lambda: client.view_black_card(),
        "view_played_cards": lambda: client.view_played_cards(),
        "pick_black_card": lambda: client.pick_black_card(),
        "collect_cards": lambda: client.collect_cards(),
        "designate_card": designate_card,
        "play_white_card": play_white_card,
        }

    try:
        json_msg = json.loads(message)
    except json.JSONDecodeError:
        return error('badly formatted json')

    try:
        return opcodes_map[json_msg["op"]]()
    except (KeyError, TypeError):
        return error('invalid command')
    except WrongAction as e:
        return error(str(e))
    except JoinError as e:
        logging.warning("player could not join game: %s", e.__repr__())
        return error(str(e))


async def connection_handler(websocket, path):
    client = Client(websocket, game_manager)

    with contextlib.suppress(websockets.exceptions.ConnectionClosed):
        async for message in client.socket:
            await client.socket.send(message_received_handler(client, message))

    client.disconnect()


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('--listen', type=str, default='0.0.0.0')
    parser.add_argument('--port', type=int, default=1236)
    args = vars(parser.parse_args())

    logging.basicConfig(level=logging.INFO)

    start_server = websockets.serve(connection_handler, args['listen'], args['port'])

    asyncio.get_event_loop().run_until_complete(start_server)
    asyncio.get_event_loop().run_forever()


if __name__ == '__main__':
    main()