forked from xysun/pychat
-
Notifications
You must be signed in to change notification settings - Fork 0
/
pychat_util.py
132 lines (108 loc) · 4.67 KB
/
pychat_util.py
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# implementing 3-tier structure: Hall --> Room --> Clients;
# 14-Jun-2013
import socket, pdb
MAX_CLIENTS = 30
PORT = 22222
QUIT_STRING = '<$quit$>'
def create_socket(address):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.setblocking(0)
s.bind(address)
s.listen(MAX_CLIENTS)
print("Now listening at ", address)
return s
class Hall:
def __init__(self):
self.rooms = {} # {room_name: Room}
self.room_player_map = {} # {playerName: roomName}
def welcome_new(self, new_player):
new_player.socket.sendall(b'Welcome to pychat.\nPlease tell us your name:\n')
def list_rooms(self, player):
if len(self.rooms) == 0:
msg = 'Oops, no active rooms currently. Create your own!\n' \
+ 'Use [<join> room_name] to create a room.\n'
player.socket.sendall(msg.encode())
else:
msg = 'Listing current rooms...\n'
for room in self.rooms:
msg += room + ": " + str(len(self.rooms[room].players)) + " player(s)\n"
player.socket.sendall(msg.encode())
def handle_msg(self, player, msg):
instructions = b'Instructions:\n'\
+ b'[<list>] to list all rooms\n'\
+ b'[<join> room_name] to join/create/switch to a room\n' \
+ b'[<manual>] to show instructions\n' \
+ b'[<quit>] to quit\n' \
+ b'Otherwise start typing and enjoy!' \
+ b'\n'
print(player.name + " says: " + msg)
if "name:" in msg:
name = msg.split()[1]
player.name = name
print("New connection from:", player.name)
player.socket.sendall(instructions)
elif "<join>" in msg:
same_room = False
if len(msg.split()) >= 2: # error check
room_name = msg.split()[1]
if player.name in self.room_player_map: # switching?
if self.room_player_map[player.name] == room_name:
player.socket.sendall(b'You are already in room: ' + room_name.encode())
same_room = True
else: # switch
old_room = self.room_player_map[player.name]
self.rooms[old_room].remove_player(player)
if not same_room:
if not room_name in self.rooms: # new room:
new_room = Room(room_name)
self.rooms[room_name] = new_room
self.rooms[room_name].players.append(player)
self.rooms[room_name].welcome_new(player)
self.room_player_map[player.name] = room_name
else:
player.socket.sendall(instructions)
elif "<list>" in msg:
self.list_rooms(player)
elif "<manual>" in msg:
player.socket.sendall(instructions)
elif "<quit>" in msg:
player.socket.sendall(QUIT_STRING.encode())
self.remove_player(player)
else:
# check if in a room or not first
if player.name in self.room_player_map:
self.rooms[self.room_player_map[player.name]].broadcast(player, msg.encode())
else:
msg = 'You are currently not in any room! \n' \
+ 'Use [<list>] to see available rooms! \n' \
+ 'Use [<join> room_name] to join a room! \n'
player.socket.sendall(msg.encode())
def remove_player(self, player):
if player.name in self.room_player_map:
self.rooms[self.room_player_map[player.name]].remove_player(player)
del self.room_player_map[player.name]
print("Player: " + player.name + " has left\n")
class Room:
def __init__(self, name):
self.players = [] # a list of sockets
self.name = name
def welcome_new(self, from_player):
msg = self.name + " welcomes: " + from_player.name + '\n'
for player in self.players:
player.socket.sendall(msg.encode())
def broadcast(self, from_player, msg):
msg = from_player.name.encode() + b":" + msg
for player in self.players:
player.socket.sendall(msg)
def remove_player(self, player):
self.players.remove(player)
leave_msg = player.name.encode() + b"has left the room\n"
self.broadcast(player, leave_msg)
class Player:
def __init__(self, socket, name = "new"):
socket.setblocking(0)
self.socket = socket
self.name = name
def fileno(self):
return self.socket.fileno()