equipment messages are now list of pairs, not dict; server gets address on creation
This commit is contained in:
parent
84d899aa45
commit
7c33c47f9b
|
@ -134,12 +134,10 @@ class Display:
|
|||
|
||||
|
||||
def setEquipment(self, slots):
|
||||
self.equipment.setItems(
|
||||
sorted([
|
||||
slot + ": " + (item if item else "")
|
||||
for slot, item in slots.items()
|
||||
])
|
||||
)
|
||||
self.equipment.setItems([
|
||||
slot + ": " + (item if item else "")
|
||||
for slot, item in slots
|
||||
])
|
||||
|
||||
def setGround(self, items):
|
||||
self.ground.setItems(items)
|
||||
|
|
|
@ -15,9 +15,9 @@ saveExt = ".save.json"
|
|||
|
||||
class Game:
|
||||
|
||||
def __init__(self, socketType, worldFile=None, saveDir=None, saveInterval=1):
|
||||
def __init__(self, socketType, address, worldFile=None, saveDir=None, saveInterval=1):
|
||||
|
||||
self.server = gameserver.GameServer(socketType)
|
||||
self.server = gameserver.GameServer(socketType, address)
|
||||
|
||||
worldLoader = worldloader.WorldLoader(saveDir)
|
||||
roomLoader = roomloader.RoomLoader(worldFile, os.path.join(saveDir, "rooms"))
|
||||
|
@ -31,9 +31,9 @@ class Game:
|
|||
self.counter = 0
|
||||
|
||||
|
||||
def start(self, address):
|
||||
def start(self):
|
||||
|
||||
self.server.start(address)
|
||||
self.server.start()
|
||||
|
||||
try:
|
||||
self.game_loop()
|
||||
|
|
|
@ -18,20 +18,17 @@ nameRegex = re.compile("(~|\w)\w*")
|
|||
class GameServer:
|
||||
|
||||
|
||||
def __init__(self, socketType):
|
||||
def __init__(self, socketType, address):
|
||||
|
||||
self.serv = server.Server(socketType, self.newConnection, self.receive, self.close)
|
||||
self.serv = server.Server(socketType, address, self.newConnection, self.receive, self.close)
|
||||
|
||||
self.connections = {}
|
||||
|
||||
self.players = {}
|
||||
|
||||
|
||||
self.messages = queue.Queue()
|
||||
|
||||
def start(self, address):
|
||||
def start(self):
|
||||
|
||||
self.listener = threading.Thread(target=self.serv.listen, daemon=True, args=(address,))
|
||||
self.listener = threading.Thread(target=self.serv.listen, daemon=True)
|
||||
self.listener.start()
|
||||
|
||||
def sendState(self, view):
|
||||
|
@ -69,7 +66,7 @@ class GameServer:
|
|||
self.error(n, "invalidname", "name may not be longer than 256 utf8 bytes")
|
||||
return
|
||||
if nameRegex.match(name) is None:
|
||||
self.error(n, "invalidname", "Name must match the regex: {}".format(nameRegex.pattern))
|
||||
self.error(n, "invalidname", "Name must match the following regex: {}".format(nameRegex.pattern))
|
||||
return
|
||||
if name[0] == "~" and name[1:] != self.serv.getUsername(n):
|
||||
self.error(n, "invalidname", "tildenames are only available on unix sockets and when the rest of the name equals the username")
|
||||
|
|
|
@ -39,4 +39,4 @@ def main(argv=None):
|
|||
hostname, sep, port = address.partition(':')
|
||||
address = (hostname, int(port))
|
||||
|
||||
game.Game(args.socket, args.world, args.savedir, 300).start(address)
|
||||
game.Game(args.socket, address, args.world, args.savedir, 300).start()
|
||||
|
|
|
@ -40,7 +40,7 @@ class _BytesBuffer:
|
|||
class Server:
|
||||
|
||||
|
||||
def __init__(self, socketType, onConnection=(lambda *_:None), onMessage=(lambda *_:None), onConnectionClose=(lambda *_:None)):
|
||||
def __init__(self, socketType, address, onConnection=(lambda *_:None), onMessage=(lambda *_:None), onConnectionClose=(lambda *_:None)):
|
||||
|
||||
if socketType == "abstract" or socketType == "unix":
|
||||
self.sockType = socket.AF_UNIX
|
||||
|
@ -53,13 +53,14 @@ class Server:
|
|||
self.onConnection = onConnection
|
||||
self.onMessage = onMessage
|
||||
self.onConnectionClose = onConnectionClose
|
||||
self.sel = selectors.DefaultSelector()
|
||||
self.address = address
|
||||
self.selector = None
|
||||
|
||||
|
||||
def listen(self, address):
|
||||
print("starting {} socket server on address {}".format(self.socketType, address))
|
||||
def listen(self, selector=None):
|
||||
print("starting {} socket server on address {}".format(self.socketType, self.address))
|
||||
try:
|
||||
self.sock.bind(address)
|
||||
self.sock.bind(self.address)
|
||||
except PermissionError:
|
||||
print("You don't have permission to use this socket file.\nRun the server with the '-s' option to specify another socket file path.\nWARNING: if an existing file is given, it will be overwritten.")
|
||||
sys.exit(-1)
|
||||
|
@ -71,51 +72,49 @@ class Server:
|
|||
|
||||
self.sock.setblocking(False)
|
||||
|
||||
self.sel.register(self.sock, selectors.EVENT_READ, "ACCEPT")
|
||||
if selector is None:
|
||||
selector = selectors.DefaultSelector()
|
||||
self.selector = selector
|
||||
|
||||
selector.register(self.sock, selectors.EVENT_READ, self._accept)
|
||||
|
||||
self.connections = {}
|
||||
print("listening")
|
||||
while True:
|
||||
events = self.sel.select()
|
||||
events = selector.select()
|
||||
for key, mask in events:
|
||||
if key.data == "ACCEPT":
|
||||
sock = key.fileobj
|
||||
connection, client_address = sock.accept()
|
||||
connection.setblocking(False)
|
||||
self.sel.register(connection, selectors.EVENT_READ, "RECEIVE")
|
||||
self.connections[connection] = _BytesBuffer()
|
||||
self.onConnection(connection)
|
||||
elif key.data == "RECEIVE":
|
||||
connection = key.fileobj
|
||||
data = connection.recv(4096)
|
||||
if data:
|
||||
buff = self.connections[connection]
|
||||
buff.addBytes(data)
|
||||
for message in buff.readMessages():
|
||||
self.onMessage(connection, message)
|
||||
else:
|
||||
del self.connections[connection]
|
||||
self.onConnectionClose(connection)
|
||||
|
||||
#listener = threading.Thread(target=self._listenCon, args=(connection,), daemon=True)
|
||||
#listener.start()
|
||||
|
||||
sock = key.fileobj
|
||||
callback = key.data
|
||||
callback(sock)
|
||||
|
||||
#def _listenCon(self, connection):
|
||||
#self.connections.add(connection)
|
||||
#self.onConnection(connection)
|
||||
#data = receive(connection)
|
||||
#while data:
|
||||
#self.onMessage(connection, data)
|
||||
#try:
|
||||
#data = receive(connection)
|
||||
#except socket.error:
|
||||
#break
|
||||
#if not len(data):
|
||||
#break
|
||||
#self.connections.discard(connection)
|
||||
#self.onConnectionClose(connection)
|
||||
def _accept(self, sock):
|
||||
connection, client_address = sock.accept()
|
||||
connection.setblocking(False)
|
||||
self.selector.register(connection, selectors.EVENT_READ, self._receive)
|
||||
self.connections[connection] = _BytesBuffer()
|
||||
self.onConnection(connection)
|
||||
|
||||
def _receive(self, connection):
|
||||
try:
|
||||
data = connection.recv(4096)
|
||||
except ConnectionResetError:
|
||||
data = None
|
||||
if data:
|
||||
buff = self.connections[connection]
|
||||
buff.addBytes(data)
|
||||
for message in buff.readMessages():
|
||||
self.onMessage(connection, message)
|
||||
else:
|
||||
self.closeConnection(connection)
|
||||
|
||||
def closeConnection(self, connection):
|
||||
try:
|
||||
del self.connections[connection]
|
||||
except KeyError:
|
||||
return
|
||||
connection.close()
|
||||
self.selector.unregister(connection)
|
||||
self.onConnectionClose(connection)
|
||||
|
||||
def getUsername(self, connection):
|
||||
|
||||
|
@ -129,14 +128,13 @@ class Server:
|
|||
|
||||
|
||||
def send(self, connection, msg):
|
||||
try:
|
||||
if connection in self.connections:
|
||||
length = len(msg)
|
||||
header = length.to_bytes(4, byteorder="big")
|
||||
connection.sendall(header + msg)
|
||||
except Exception:
|
||||
del self.connections[connection]
|
||||
self.onConnectionClose(connection)
|
||||
print("failed to send to client")
|
||||
try:
|
||||
connection.sendall(header + msg)
|
||||
except BrokenPipeError:
|
||||
self.closeConnection(connection)
|
||||
|
||||
def broadcast(self, msg):
|
||||
for connection in frozenset(self.connections):
|
||||
|
|
|
@ -16,7 +16,7 @@ def onSelectionChange(p):
|
|||
changeActions = {
|
||||
"health": lambda p: ["health", p.getHealthPair()],
|
||||
"inventory": lambda p: ["inventory", [obj.getName() for obj in p.getInventory()]],
|
||||
"equipment": lambda p: ["equipment", {slot: (item.getName() if item else None) for slot, item in p.getEquipment().items()}],
|
||||
"equipment": lambda p: ["equipment", sorted([(slot, (item.getName() if item else None)) for slot, item in p.getEquipment().items()])],
|
||||
"ground": lambda p: ["ground", [obj.getName() for obj in p.getGroundObjs() if obj.getName()]],
|
||||
"pos": lambda p: ["playerpos", p.getPos()],
|
||||
"selection": onSelectionChange
|
||||
|
|
Loading…
Reference in New Issue