134 lines
4.0 KiB
Python
Executable File
134 lines
4.0 KiB
Python
Executable File
#! /usr/bin/python3
|
|
|
|
import sys
|
|
|
|
import curses
|
|
import threading
|
|
#import logging
|
|
import json
|
|
import getpass
|
|
import argparse
|
|
from connection import Connection
|
|
from screen import Screen
|
|
|
|
# todo: remove references to tron
|
|
|
|
#logging.basicConfig(filename="client.log", filemode='w', level=logging.DEBUG)
|
|
|
|
|
|
class Client:
|
|
|
|
def __init__(self, stdscr, name="___", address="/tmp/tron_socket", spectate=False):
|
|
self.stdscr = stdscr
|
|
self.screen = Screen(stdscr)
|
|
|
|
self.name = name
|
|
|
|
self.keepalive = True
|
|
|
|
self.connection = Connection()
|
|
self.connection.connect(address)
|
|
|
|
self.lastoutputstring = None
|
|
self.lastinfostring = None
|
|
|
|
if not spectate:
|
|
self.connection.send(json.dumps({"name":name}))
|
|
|
|
self.fieldWidth = 0
|
|
self.fieldHeight = 0
|
|
|
|
with open("client/characters.json") as f:
|
|
self.characters = json.load(f)['ascii']
|
|
|
|
threading.Thread(target=self.listen, daemon=True).start()
|
|
self.command_loop()
|
|
|
|
def listen(self):
|
|
self.connection.listen(self.update, self.close)
|
|
|
|
def close(self, err=None):
|
|
self.keepalive = False
|
|
sys.exit()
|
|
|
|
|
|
def update(self, databytes):
|
|
if not self.keepalive:
|
|
sys.exit()
|
|
datastr = databytes.decode('utf-8')
|
|
data = json.loads(datastr)
|
|
if 'error' in data:
|
|
if data['error'] == "nametaken":
|
|
print("error: name is already taken", file=sys.stderr)
|
|
self.close()
|
|
if 'field' in data:
|
|
self.fieldWidth = data['field']['width']
|
|
self.fieldHeight = data['field']['height']
|
|
fieldCells = data['field']['field']
|
|
mapping = data['field']['mapping']
|
|
#print(mapping['0'])
|
|
outputstring = '\n'.join(
|
|
''.join(
|
|
self.characters.get(mapping[fieldCells[x + y*self.fieldWidth]], '?') for x in range(self.fieldWidth)
|
|
) for y in range(self.fieldHeight)
|
|
)
|
|
if outputstring != self.lastoutputstring:
|
|
self.screen.put(outputstring, self.fieldWidth, self.fieldHeight)
|
|
self.lastoutputstring = outputstring
|
|
#else:
|
|
#self.screen.put('_'*100)
|
|
if 'info' in data:
|
|
infostring = json.dumps(data['info'], indent=2)
|
|
if infostring != self.lastinfostring:
|
|
self.screen.putPlayers(infostring, self.fieldWidth+2)
|
|
self.lastinfostring = infostring
|
|
self.screen.refresh()
|
|
|
|
def command_loop(self):
|
|
|
|
commands = {
|
|
ord("w"): "north",
|
|
curses.KEY_UP: "north",
|
|
ord("s"): "south",
|
|
curses.KEY_DOWN: "south",
|
|
ord("d"): "east",
|
|
curses.KEY_RIGHT: "east",
|
|
ord("a"): "west",
|
|
curses.KEY_LEFT: "west",
|
|
ord("e"): "take",
|
|
ord("q"): "drop",
|
|
ord("W"): "fastnorth",
|
|
ord("S"): "fastsouth",
|
|
ord("D"): "fasteast",
|
|
ord("A"): "fastwest"
|
|
}
|
|
|
|
while self.keepalive:
|
|
key = self.stdscr.getch()
|
|
if key == 27:
|
|
self.keepalive = False
|
|
if key in commands:
|
|
self.connection.send(json.dumps({"input":commands[key]}))
|
|
|
|
|
|
def main(name, socket, spectate=False):
|
|
|
|
|
|
def start(stdscr):
|
|
client = Client(stdscr, name, socket, spectate)
|
|
|
|
curses.wrapper(start)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument('-n', '--name', help='Your player name (must be unique!). Defaults to username', default=getpass.getuser())
|
|
parser.add_argument('-s', '--socket', help='The socket file to connect to. Defaults to /tmp/tron_socket', default="/tmp/tron_socket")
|
|
parser.add_argument('-p', '--spectate', help='Join as spectator', action="store_true")
|
|
args = parser.parse_args()
|
|
|
|
main(args.name, args.socket, args.spectate)
|
|
|
|
|