27c9cd56 by Barry

Added wifi handler for web setup.

1 parent 2d5255ad
1 1
2 global_aliases = {
3 'n': 'north',
4 's': 'south',
5 'e': 'east',
6 'w': 'west',
7 'u': 'up',
8 'd': 'down',
9 'l': 'look',
10 }
11
2 class CommandHandler(object): 12 class CommandHandler(object):
3 13
4 def tokenize_params(self): 14 def tokenize_params(self):
...@@ -45,18 +55,89 @@ class CommandHandler(object): ...@@ -45,18 +55,89 @@ class CommandHandler(object):
45 55
46 return True 56 return True
47 57
48 def parse(self, id, cmd, params, room, mud, players): 58 def who(self):
59 self.mud.send_message(self.id, "")
60 self.mud.send_message(self.id, "-------- {} Players Currently Online --------".format(len(self.players)))
61 for pid, player in self.players.items():
62 self.mud.send_message(self.id, " " + player["name"])
63 self.mud.send_message(self.id, "---------------------------------------------".format(len(self.players)))
64 self.mud.send_message(self.id, "")
65 return True
66
67 def go(self):
68 # store the exit name
69 ex = self.params.lower().strip()
70
71 # if the specified exit is found in the room's exits list
72 if ex in self.room.get_exits():
73 # go through all the players in the game
74 for pid, pl in self.players.items():
75 # if player is in the same room and isn't the player
76 # sending the command
77 if self.players[pid]["room"] == self.players[self.id]["room"] \
78 and pid != self.id:
79 # send them a message telling them that the player
80 # left the room
81 self.mud.send_message(pid, "{} left via exit '{}'".format(
82 self.players[self.id]["name"], ex))
83
84 # update the player's current room to the one the exit leads to
85 loaded = self.load_room(self.room.get_exits()[ex])
86 if loaded == None:
87 self.mud.send_message(id, "An invisible force prevents you from going in that direction.")
88 return True
89 else:
90 self.players[self.id]["room"] = self.room.get_exits()[ex]
91 self.room = loaded
92
93 # go through all the players in the game
94 for pid, pl in self.players.items():
95 # if player is in the same (new) room and isn't the player
96 # sending the command
97 if self.players[pid]["room"] == self.players[self.id]["room"] \
98 and pid != self.id:
99 # send them a message telling them that the player
100 # entered the room
101 self.mud.send_message(pid,
102 "{} arrived via exit '{}'".format(
103 self.players[self.id]["name"], ex))
104
105 # send the player a message telling them where they are now
106 self.mud.send_message(id, "You arrive at '{}'".format(self.room.get_title()))
107
108 # the specified exit wasn't found in the current room
109 else:
110 # send back an 'unknown exit' message
111 self.mud.send_message(id, "Unknown exit '{}'".format(ex))
112 return True
113
114
115 def alias(self, command):
116 if command in global_aliases:
117 return global_aliases[command]
118 if 'aliases' not in self.players[self.id]:
119 self.players[self.id]["aliases"] = {}
120 if command in self.players[self.id]["aliases"]:
121 return self.players[self.id]["aliases"][command]
122 return command
123
124 def parse(self, id, cmd, params, room, mud, players, load_room):
49 self.id = id 125 self.id = id
50 self.cmd = cmd
51 self.params = params 126 self.params = params
52 self.tokenize_params() 127 self.tokenize_params()
53 self.room = room 128 self.room = room
54 self.mud = mud 129 self.mud = mud
55 self.players = players 130 self.players = players
131 self.load_room = load_room
132 self.cmd = self.alias(cmd)
56 133
57 try: 134 try:
58 method = getattr(self, cmd) 135 if self.cmd in self.room.get_exits():
136 self.params = self.cmd + " " + self.params
137 self.cmd = "go"
138 method = getattr(self, self.cmd)
59 return method() 139 return method()
60 except AttributeError: 140 except AttributeError:
141 mud.send_message(id, "Unknown command '{}'".format(self.cmd))
61 return False 142 return False
62 143
......
...@@ -2,5 +2,6 @@ Commands: ...@@ -2,5 +2,6 @@ Commands:
2 say <message> - Says something out loud, e.g. 'say Hello' 2 say <message> - Says something out loud, e.g. 'say Hello'
3 look - Examines the surroundings, e.g. 'look' 3 look - Examines the surroundings, e.g. 'look'
4 go <exit> - Moves through the exit specified, e.g. 'go outside' 4 go <exit> - Moves through the exit specified, e.g. 'go outside'
5 who - Lists all players currently connected
5 save - Saves your character 6 save - Saves your character
6 quit - Saves your character then closes the connection 7 quit - Saves your character then closes the connection
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -25,13 +25,15 @@ import time ...@@ -25,13 +25,15 @@ import time
25 # import datetime 25 # import datetime
26 #import io 26 #import io
27 import json 27 import json
28 28 import machine
29 # import the MUD server class 29 # import the MUD server class
30 from mudserver import MudServer 30 from mudserver import MudServer
31 from commands import CommandHandler 31 from commands import CommandHandler
32 32
33 print('STARTING MUD\r\n\r\n\r\n') 33 print('STARTING MUD\r\n\r\n\r\n')
34 34
35 flash_button = machine.Pin(0, machine.Pin.IN, machine.Pin.PULL_UP)
36
35 rooms = {} 37 rooms = {}
36 38
37 # stores the players in the game 39 # stores the players in the game
...@@ -62,7 +64,7 @@ def load_room(room_name): ...@@ -62,7 +64,7 @@ def load_room(room_name):
62 64
63 def save_object_to_file(obj, filename): 65 def save_object_to_file(obj, filename):
64 with open(filename, 'w', encoding='utf-8') as f: 66 with open(filename, 'w', encoding='utf-8') as f:
65 f.write(json.dumps(obj, ensure_ascii=False)) 67 f.write(json.dumps(obj))
66 68
67 def load_object_from_file(filename): 69 def load_object_from_file(filename):
68 try: 70 try:
...@@ -78,7 +80,9 @@ def prompt(pid): ...@@ -78,7 +80,9 @@ def prompt(pid):
78 80
79 # main game loop. We loop forever (i.e. until the program is terminated) 81 # main game loop. We loop forever (i.e. until the program is terminated)
80 while True: 82 while True:
81 83 gc.collect()
84 if flash_button.value() == 0:
85 break
82 # pause for 1/5 of a second on each loop, so that we don't constantly 86 # pause for 1/5 of a second on each loop, so that we don't constantly
83 # use 100% CPU time 87 # use 100% CPU time
84 time.sleep(0.001) 88 time.sleep(0.001)
...@@ -97,6 +101,8 @@ while True: ...@@ -97,6 +101,8 @@ while True:
97 # go through any newly connected players 101 # go through any newly connected players
98 for id in mud.get_new_players(): 102 for id in mud.get_new_players():
99 103
104
105
100 # add the new player to the dictionary, noting that they've not been 106 # add the new player to the dictionary, noting that they've not been
101 # named yet. 107 # named yet.
102 # The dictionary key is the player's id number. We set their room to 108 # The dictionary key is the player's id number. We set their room to
...@@ -105,8 +111,9 @@ while True: ...@@ -105,8 +111,9 @@ while True:
105 players[id] = { 111 players[id] = {
106 "name": None, 112 "name": None,
107 "room": None, 113 "room": None,
108 "inventory": None, 114 "inventory": {},
109 "prompt": "> ", 115 "prompt": "> ",
116 "aliases": {},
110 } 117 }
111 118
112 # send the new player a prompt for their name 119 # send the new player a prompt for their name
...@@ -124,8 +131,11 @@ while True: ...@@ -124,8 +131,11 @@ while True:
124 for pid, pl in players.items(): 131 for pid, pl in players.items():
125 # send each player a message to tell them about the diconnected 132 # send each player a message to tell them about the diconnected
126 # player 133 # player
127 mud.send_message(pid, "{} quit the game".format( 134 if players[id]["name"] != None:
135 mud.send_message(pid, "{} quit the game".format(
128 players[id]["name"])) 136 players[id]["name"]))
137 else:
138 save_object_to_file(players[id], "players/{}.json".format(players[id]["name"]))
129 139
130 # remove the player's entry in the player dictionary 140 # remove the player's entry in the player dictionary
131 del(players[id]) 141 del(players[id])
...@@ -143,7 +153,9 @@ while True: ...@@ -143,7 +153,9 @@ while True:
143 # if the player hasn't given their name yet, use this first command as 153 # if the player hasn't given their name yet, use this first command as
144 # their name and move them to the starting room. 154 # their name and move them to the starting room.
145 if players[id]["name"] is None: 155 if players[id]["name"] is None:
146 156 if command.strip() == '' or command is None:
157 mud.send_message(id, "Invalid Name")
158 continue
147 loaded_player = load_object_from_file("players/{}.json".format(command)) 159 loaded_player = load_object_from_file("players/{}.json".format(command))
148 if loaded_player is None: 160 if loaded_player is None:
149 players[id]["name"] = command 161 players[id]["name"] = command
...@@ -204,65 +216,12 @@ while True: ...@@ -204,65 +216,12 @@ while True:
204 players[id]["name"], params)) 216 players[id]["name"], params))
205 217
206 # 'look' command 218 # 'look' command
207 elif cmd_handler.parse(id, command, params, rm, mud, players): 219 else:
208
209 pass
210
211 # 'go' command
212 elif command == "go":
213
214 # store the exit name
215 ex = params.lower()
216
217 # store the player's current room
218 rm = load_room(players[id]["room"])
219
220 # if the specified exit is found in the room's exits list
221 if ex in rm.get_exits():
222
223 # go through all the players in the game
224 for pid, pl in players.items():
225 # if player is in the same room and isn't the player
226 # sending the command
227 if players[pid]["room"] == players[id]["room"] \
228 and pid != id:
229 # send them a message telling them that the player
230 # left the room
231 mud.send_message(pid, "{} left via exit '{}'".format(
232 players[id]["name"], ex))
233
234 # update the player's current room to the one the exit leads to
235 loaded = load_room(rm.get_exits()[ex])
236 if loaded == None:
237 mud.send_message(id, "An invisible force prevents you from going in that direction.")
238 continue
239 else:
240 players[id]["room"] = rm.get_exits()[ex]
241 rm = loaded
242
243 # go through all the players in the game
244 for pid, pl in players.items():
245 # if player is in the same (new) room and isn't the player
246 # sending the command
247 if players[pid]["room"] == players[id]["room"] \
248 and pid != id:
249 # send them a message telling them that the player
250 # entered the room
251 mud.send_message(pid,
252 "{} arrived via exit '{}'".format(
253 players[id]["name"], ex))
254
255 # send the player a message telling them where they are now
256 mud.send_message(id, "You arrive at '{}'".format(rm.get_title()))
257
258 # the specified exit wasn't found in the current room
259 else:
260 # send back an 'unknown exit' message
261 mud.send_message(id, "Unknown exit '{}'".format(ex))
262 220
221 handler_results = cmd_handler.parse(id, command, params, rm, mud, players, load_room)
263 222
264 # some other, unrecognised command
265 else:
266 # send back an 'unknown command' message
267 mud.send_message(id, "Unknown command '{}'".format(command))
268 prompt(id) 223 prompt(id)
224
225 # Start WIFI Setup
226 if flash_button.value() == 0:
227 import wifiweb
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -324,7 +324,8 @@ class MudServer(object): ...@@ -324,7 +324,8 @@ class MudServer(object):
324 324
325 # if there is a problem reading from the socket (e.g. the client 325 # if there is a problem reading from the socket (e.g. the client
326 # has disconnected) a socket error will be raised 326 # has disconnected) a socket error will be raised
327 except socket.error: 327 except Exception as e:
328 sys.print_exception(e)
328 self._handle_disconnect(id) 329 self._handle_disconnect(id)
329 330
330 def _handle_disconnect(self, clid): 331 def _handle_disconnect(self, clid):
......
1 from .baseroom import BaseRoom
2
3 class Outside(BaseRoom):
4
5 def __init__(self):
6
7 title = "Outside the Tavern"
8 description = "You are standing outside of a simple tavern made of pressed clay and shale roof. \r\nThe door becons you to come in and have a drink."
9 exits = {"tavern": "Tavern"}
10 look_items = {
11 "tavern": "A roughly constructed building.",
12 }
13
14 super(Outside, self).__init__(title, description, exits, look_items)
1
2 import network
3 import socket
4 import machine
5 import time
6
7 ap = network.WLAN(network.AP_IF)
8 ap.active(True)
9 ap.config(essid='MUD')
10 ap.config(authmode=1)
11
12 class DNSQuery:
13 def __init__(self, data):
14 self.data=data
15 self.dominio=''
16
17 print("Reading datagram data...")
18 m = data[2] # ord(data[2])
19 tipo = (m >> 3) & 15 # Opcode bits
20 if tipo == 0: # Standard query
21 ini=12
22 lon=data[ini] # ord(data[ini])
23 while lon != 0:
24 self.dominio+=data[ini+1:ini+lon+1].decode("utf-8") +'.'
25 ini+=lon+1
26 lon=data[ini] #ord(data[ini])
27
28 def respuesta(self, ip):
29 packet=b''
30 print("Resposta {} == {}".format(self.dominio, ip))
31 if self.dominio:
32 packet+=self.data[:2] + b"\x81\x80"
33 packet+=self.data[4:6] + self.data[4:6] + b'\x00\x00\x00\x00' # Questions and Answers Counts
34 packet+=self.data[12:] # Original Domain Name Question
35 packet+= b'\xc0\x0c' # Pointer to domain name
36 packet+= b'\x00\x01\x00\x01\x00\x00\x00\x3c\x00\x04' # Response type, ttl and resource data length -> 4 bytes
37 packet+=bytes(map(int,ip.split('.'))) # 4 bytes of IP
38 return packet
39
40 def accept_conn(listen_sock):
41 cl, addr = listen_sock.accept()
42 print('client connected from', addr)
43 print('Request:')
44 request = cl.recv(2048)
45 print(request)
46 if 'GET /?' in request:
47 #GET /?network=Volley&networkpass=test
48 request = str(request)
49 part = request.split(' ')[1]
50 params = part.split('?')[1].split('&')
51 network_param = params[0].split('=')[1]
52 network_pass_param = params[1].split('=')[1]
53
54 sta_if = network.WLAN(network.STA_IF)
55 sta_if.active(True)
56 sta_if.connect(network_param, network_pass_param)
57 while sta_if.isconnected() == False:
58 time.sleep(1)
59 cl.send('<html><body>Configuration Saved!<br><br>Network: {} <br>IP Address: {}<br>Password: {}<br><br><br>Restarting Device...</body></html>'.format(network_param, sta_if.ifconfig()[0], network_pass_param))
60 cl.close()
61 time.sleep(20)
62 machine.reset()
63 return
64 print('Getting Network STA_IF')
65 sta_if = network.WLAN(network.STA_IF)
66 print('Starting Network Scan...')
67 avail_networks = sta_if.scan()
68 print('Network Scan Complete')
69 endpoint_string = ""
70 for endpoint in avail_networks:
71 endpoint_string += "<option value={}>{}</option>".format(endpoint[0].decode('latin1'), endpoint[0].decode('latin1'))
72 response = """
73 <html>
74 <head>
75 <title>Mud Setup</title>
76 </head>
77 <body margin='10px'>
78 <h2>Configure Wifi Network</h2>
79 <form action='/' method='GET'>
80 Network: <select name='network' id='network'>
81 {}
82 </select><br><br>
83 Password: <input type='text' name='networkpass' id='networkpass'>
84 <input type="submit">
85 </form>
86 </body>
87 </html>
88 \n\n""".format(endpoint_string)
89 # rows = ['<tr><td>%s</td><td>%d</td></tr>' % (str(p), p.value()) for p in pins]
90 # response = html % '\n'.join(rows)
91 print('Sending Response')
92 cl.send(response)
93 print('Closing Socket')
94 time.sleep(0.001)
95 cl.close()
96
97 listen_s = None
98
99 port = 80
100
101 s = socket.socket()
102
103 ai = socket.getaddrinfo("0.0.0.0", port)
104 addr = ai[0][4]
105
106 s.bind(addr)
107 s.listen(1)
108 s.setsockopt(socket.SOL_SOCKET, 20, accept_conn)
109 iface = network.WLAN(network.AP_IF)
110 if iface.active():
111 print("Web Server daemon started on ws://%s:%d" % (iface.ifconfig()[0], port))
112
113
114 # def accept_dns(listen_sock):
115 # cl, addr = listen_sock.accept()
116 # print('DNS client connected from', addr)
117 # try:
118 # data, addr = udps.recvfrom(1024)
119 # print("incomming datagram...")
120 # p=DNSQuery(data)
121 # udps.sendto(p.respuesta(ip), addr)
122 # print('Replying: {:s} -> {:s}'.format(p.dominio, ip))
123 # except:
124 # print('No dgram')
125
126 # # SETUP DNS
127 # ip=ap.ifconfig()[0]
128 # print('DNS Server: dom.query. 60 IN A {:s}'.format(ip))
129
130 # udps = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
131 # udps.setblocking(False)
132 # udps.bind(('',53))
133 # udps.setsockopt(socket.SOL_SOCKET, 20, accept_dns)