27c9cd56 by Barry

Added wifi handler for web setup.

1 parent 2d5255ad
global_aliases = {
'n': 'north',
's': 'south',
'e': 'east',
'w': 'west',
'u': 'up',
'd': 'down',
'l': 'look',
}
class CommandHandler(object):
def tokenize_params(self):
......@@ -45,18 +55,89 @@ class CommandHandler(object):
return True
def parse(self, id, cmd, params, room, mud, players):
def who(self):
self.mud.send_message(self.id, "")
self.mud.send_message(self.id, "-------- {} Players Currently Online --------".format(len(self.players)))
for pid, player in self.players.items():
self.mud.send_message(self.id, " " + player["name"])
self.mud.send_message(self.id, "---------------------------------------------".format(len(self.players)))
self.mud.send_message(self.id, "")
return True
def go(self):
# store the exit name
ex = self.params.lower().strip()
# if the specified exit is found in the room's exits list
if ex in self.room.get_exits():
# go through all the players in the game
for pid, pl in self.players.items():
# if player is in the same room and isn't the player
# sending the command
if self.players[pid]["room"] == self.players[self.id]["room"] \
and pid != self.id:
# send them a message telling them that the player
# left the room
self.mud.send_message(pid, "{} left via exit '{}'".format(
self.players[self.id]["name"], ex))
# update the player's current room to the one the exit leads to
loaded = self.load_room(self.room.get_exits()[ex])
if loaded == None:
self.mud.send_message(id, "An invisible force prevents you from going in that direction.")
return True
else:
self.players[self.id]["room"] = self.room.get_exits()[ex]
self.room = loaded
# go through all the players in the game
for pid, pl in self.players.items():
# if player is in the same (new) room and isn't the player
# sending the command
if self.players[pid]["room"] == self.players[self.id]["room"] \
and pid != self.id:
# send them a message telling them that the player
# entered the room
self.mud.send_message(pid,
"{} arrived via exit '{}'".format(
self.players[self.id]["name"], ex))
# send the player a message telling them where they are now
self.mud.send_message(id, "You arrive at '{}'".format(self.room.get_title()))
# the specified exit wasn't found in the current room
else:
# send back an 'unknown exit' message
self.mud.send_message(id, "Unknown exit '{}'".format(ex))
return True
def alias(self, command):
if command in global_aliases:
return global_aliases[command]
if 'aliases' not in self.players[self.id]:
self.players[self.id]["aliases"] = {}
if command in self.players[self.id]["aliases"]:
return self.players[self.id]["aliases"][command]
return command
def parse(self, id, cmd, params, room, mud, players, load_room):
self.id = id
self.cmd = cmd
self.params = params
self.tokenize_params()
self.room = room
self.mud = mud
self.players = players
self.load_room = load_room
self.cmd = self.alias(cmd)
try:
method = getattr(self, cmd)
if self.cmd in self.room.get_exits():
self.params = self.cmd + " " + self.params
self.cmd = "go"
method = getattr(self, self.cmd)
return method()
except AttributeError:
mud.send_message(id, "Unknown command '{}'".format(self.cmd))
return False
......
......@@ -2,5 +2,6 @@ Commands:
say <message> - Says something out loud, e.g. 'say Hello'
look - Examines the surroundings, e.g. 'look'
go <exit> - Moves through the exit specified, e.g. 'go outside'
who - Lists all players currently connected
save - Saves your character
quit - Saves your character then closes the connection
\ No newline at end of file
......
......@@ -25,13 +25,15 @@ import time
# import datetime
#import io
import json
import machine
# import the MUD server class
from mudserver import MudServer
from commands import CommandHandler
print('STARTING MUD\r\n\r\n\r\n')
flash_button = machine.Pin(0, machine.Pin.IN, machine.Pin.PULL_UP)
rooms = {}
# stores the players in the game
......@@ -62,7 +64,7 @@ def load_room(room_name):
def save_object_to_file(obj, filename):
with open(filename, 'w', encoding='utf-8') as f:
f.write(json.dumps(obj, ensure_ascii=False))
f.write(json.dumps(obj))
def load_object_from_file(filename):
try:
......@@ -78,7 +80,9 @@ def prompt(pid):
# main game loop. We loop forever (i.e. until the program is terminated)
while True:
gc.collect()
if flash_button.value() == 0:
break
# pause for 1/5 of a second on each loop, so that we don't constantly
# use 100% CPU time
time.sleep(0.001)
......@@ -97,6 +101,8 @@ while True:
# go through any newly connected players
for id in mud.get_new_players():
# add the new player to the dictionary, noting that they've not been
# named yet.
# The dictionary key is the player's id number. We set their room to
......@@ -105,8 +111,9 @@ while True:
players[id] = {
"name": None,
"room": None,
"inventory": None,
"inventory": {},
"prompt": "> ",
"aliases": {},
}
# send the new player a prompt for their name
......@@ -124,8 +131,11 @@ while True:
for pid, pl in players.items():
# send each player a message to tell them about the diconnected
# player
mud.send_message(pid, "{} quit the game".format(
if players[id]["name"] != None:
mud.send_message(pid, "{} quit the game".format(
players[id]["name"]))
else:
save_object_to_file(players[id], "players/{}.json".format(players[id]["name"]))
# remove the player's entry in the player dictionary
del(players[id])
......@@ -143,7 +153,9 @@ while True:
# if the player hasn't given their name yet, use this first command as
# their name and move them to the starting room.
if players[id]["name"] is None:
if command.strip() == '' or command is None:
mud.send_message(id, "Invalid Name")
continue
loaded_player = load_object_from_file("players/{}.json".format(command))
if loaded_player is None:
players[id]["name"] = command
......@@ -204,65 +216,12 @@ while True:
players[id]["name"], params))
# 'look' command
elif cmd_handler.parse(id, command, params, rm, mud, players):
pass
# 'go' command
elif command == "go":
# store the exit name
ex = params.lower()
# store the player's current room
rm = load_room(players[id]["room"])
# if the specified exit is found in the room's exits list
if ex in rm.get_exits():
# go through all the players in the game
for pid, pl in players.items():
# if player is in the same room and isn't the player
# sending the command
if players[pid]["room"] == players[id]["room"] \
and pid != id:
# send them a message telling them that the player
# left the room
mud.send_message(pid, "{} left via exit '{}'".format(
players[id]["name"], ex))
# update the player's current room to the one the exit leads to
loaded = load_room(rm.get_exits()[ex])
if loaded == None:
mud.send_message(id, "An invisible force prevents you from going in that direction.")
continue
else:
players[id]["room"] = rm.get_exits()[ex]
rm = loaded
# go through all the players in the game
for pid, pl in players.items():
# if player is in the same (new) room and isn't the player
# sending the command
if players[pid]["room"] == players[id]["room"] \
and pid != id:
# send them a message telling them that the player
# entered the room
mud.send_message(pid,
"{} arrived via exit '{}'".format(
players[id]["name"], ex))
# send the player a message telling them where they are now
mud.send_message(id, "You arrive at '{}'".format(rm.get_title()))
# the specified exit wasn't found in the current room
else:
# send back an 'unknown exit' message
mud.send_message(id, "Unknown exit '{}'".format(ex))
else:
handler_results = cmd_handler.parse(id, command, params, rm, mud, players, load_room)
# some other, unrecognised command
else:
# send back an 'unknown command' message
mud.send_message(id, "Unknown command '{}'".format(command))
prompt(id)
# Start WIFI Setup
if flash_button.value() == 0:
import wifiweb
\ No newline at end of file
......
......@@ -324,7 +324,8 @@ class MudServer(object):
# if there is a problem reading from the socket (e.g. the client
# has disconnected) a socket error will be raised
except socket.error:
except Exception as e:
sys.print_exception(e)
self._handle_disconnect(id)
def _handle_disconnect(self, clid):
......
from .baseroom import BaseRoom
class Outside(BaseRoom):
def __init__(self):
title = "Outside the Tavern"
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."
exits = {"tavern": "Tavern"}
look_items = {
"tavern": "A roughly constructed building.",
}
super(Outside, self).__init__(title, description, exits, look_items)
import network
import socket
import machine
import time
ap = network.WLAN(network.AP_IF)
ap.active(True)
ap.config(essid='MUD')
ap.config(authmode=1)
class DNSQuery:
def __init__(self, data):
self.data=data
self.dominio=''
print("Reading datagram data...")
m = data[2] # ord(data[2])
tipo = (m >> 3) & 15 # Opcode bits
if tipo == 0: # Standard query
ini=12
lon=data[ini] # ord(data[ini])
while lon != 0:
self.dominio+=data[ini+1:ini+lon+1].decode("utf-8") +'.'
ini+=lon+1
lon=data[ini] #ord(data[ini])
def respuesta(self, ip):
packet=b''
print("Resposta {} == {}".format(self.dominio, ip))
if self.dominio:
packet+=self.data[:2] + b"\x81\x80"
packet+=self.data[4:6] + self.data[4:6] + b'\x00\x00\x00\x00' # Questions and Answers Counts
packet+=self.data[12:] # Original Domain Name Question
packet+= b'\xc0\x0c' # Pointer to domain name
packet+= b'\x00\x01\x00\x01\x00\x00\x00\x3c\x00\x04' # Response type, ttl and resource data length -> 4 bytes
packet+=bytes(map(int,ip.split('.'))) # 4 bytes of IP
return packet
def accept_conn(listen_sock):
cl, addr = listen_sock.accept()
print('client connected from', addr)
print('Request:')
request = cl.recv(2048)
print(request)
if 'GET /?' in request:
#GET /?network=Volley&networkpass=test
request = str(request)
part = request.split(' ')[1]
params = part.split('?')[1].split('&')
network_param = params[0].split('=')[1]
network_pass_param = params[1].split('=')[1]
sta_if = network.WLAN(network.STA_IF)
sta_if.active(True)
sta_if.connect(network_param, network_pass_param)
while sta_if.isconnected() == False:
time.sleep(1)
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))
cl.close()
time.sleep(20)
machine.reset()
return
print('Getting Network STA_IF')
sta_if = network.WLAN(network.STA_IF)
print('Starting Network Scan...')
avail_networks = sta_if.scan()
print('Network Scan Complete')
endpoint_string = ""
for endpoint in avail_networks:
endpoint_string += "<option value={}>{}</option>".format(endpoint[0].decode('latin1'), endpoint[0].decode('latin1'))
response = """
<html>
<head>
<title>Mud Setup</title>
</head>
<body margin='10px'>
<h2>Configure Wifi Network</h2>
<form action='/' method='GET'>
Network: <select name='network' id='network'>
{}
</select><br><br>
Password: <input type='text' name='networkpass' id='networkpass'>
<input type="submit">
</form>
</body>
</html>
\n\n""".format(endpoint_string)
# rows = ['<tr><td>%s</td><td>%d</td></tr>' % (str(p), p.value()) for p in pins]
# response = html % '\n'.join(rows)
print('Sending Response')
cl.send(response)
print('Closing Socket')
time.sleep(0.001)
cl.close()
listen_s = None
port = 80
s = socket.socket()
ai = socket.getaddrinfo("0.0.0.0", port)
addr = ai[0][4]
s.bind(addr)
s.listen(1)
s.setsockopt(socket.SOL_SOCKET, 20, accept_conn)
iface = network.WLAN(network.AP_IF)
if iface.active():
print("Web Server daemon started on ws://%s:%d" % (iface.ifconfig()[0], port))
# def accept_dns(listen_sock):
# cl, addr = listen_sock.accept()
# print('DNS client connected from', addr)
# try:
# data, addr = udps.recvfrom(1024)
# print("incomming datagram...")
# p=DNSQuery(data)
# udps.sendto(p.respuesta(ip), addr)
# print('Replying: {:s} -> {:s}'.format(p.dominio, ip))
# except:
# print('No dgram')
# # SETUP DNS
# ip=ap.ifconfig()[0]
# print('DNS Server: dom.query. 60 IN A {:s}'.format(ip))
# udps = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# udps.setblocking(False)
# udps.bind(('',53))
# udps.setsockopt(socket.SOL_SOCKET, 20, accept_dns)