From a8fd6fc77a3c5af06727a68684e61c63553679a8 Mon Sep 17 00:00:00 2001 From: troido Date: Sat, 28 Oct 2017 12:31:42 +0200 Subject: better use of __main__ and __init__ --- asciifarm/client/__init__.py | 84 +++++++++++++++++++++---------- asciifarm/client/__main__.py | 75 ++-------------------------- asciifarm/client/client.py | 110 ----------------------------------------- asciifarm/client/gameclient.py | 110 +++++++++++++++++++++++++++++++++++++++++ asciifarm/client/start.py | 41 +++++++++++++++ 5 files changed, 212 insertions(+), 208 deletions(-) mode change 100644 => 100755 asciifarm/client/__init__.py mode change 100755 => 100644 asciifarm/client/__main__.py delete mode 100644 asciifarm/client/client.py create mode 100644 asciifarm/client/gameclient.py create mode 100644 asciifarm/client/start.py diff --git a/asciifarm/client/__init__.py b/asciifarm/client/__init__.py old mode 100644 new mode 100755 index f2814d7..92e1648 --- a/asciifarm/client/__init__.py +++ b/asciifarm/client/__init__.py @@ -1,12 +1,22 @@ +#! /usr/bin/python3 -import curses + +import argparse +import getpass import json import os -import getpass -import sys -from .connection import Connection -from .client import Client -from .display import Display +import os.path + +from .start import main as clientmain + +thisPath = os.path.dirname(__file__) +farmsPath = os.path.join(thisPath, "..") +charMapPath = os.path.join(farmsPath, "charmaps") +keybindingsPath = os.path.join(farmsPath, "keybindings") + +standardCharFiles = [name[:-5] for name in os.listdir(charMapPath) if name[-5:] == ".json"] +standardKeyFiles = [name[:-5] for name in os.listdir(keybindingsPath) if name[-5:] == ".json"] + defaultAdresses = { "abstract": "asciifarm", @@ -14,28 +24,50 @@ defaultAdresses = { "inet": "localhost:9021", } -def main(name, socketType, address, keybindings, characters, colours=False): +def main(): + + parser = argparse.ArgumentParser(description="The client to AsciiFarm. Run this to connect to to the server.", epilog=""" + Gameplay information: + Walk around and explore the rooms. + Kill the goblins and plant the seeds. + + ~troido""", formatter_class=argparse.RawDescriptionHelpFormatter) + parser.add_argument('-n', '--name', help='Your player name (must be unique!). Defaults to username', default=getpass.getuser()) + parser.add_argument("-a", "--address", help="The address of the socket. When the socket type is 'abstract' this is just a name. When it is 'unix' this is a filename. When it is 'inet' is should be in the format 'address:port', eg 'localhost:8080'. Defaults depends on the socket type") + parser.add_argument("-s", "--socket", help="the socket type. 'unix' is unix domain sockets, 'abstract' is abstract unix domain sockets and 'inet' is inet sockets. ", choices=["abstract", "unix", "inet"], default="abstract") + parser.add_argument('-k', '--keybindings', help='The file with the keybindings. If it is either of these names: {} it will be loaded from the keybindings directory.'.format(standardKeyFiles), default="default") + parser.add_argument('-c', '--characters', help='The file with the character mappings for the graphics. If it is either of these names: {} it will be loaded from the charmaps directory.'.format(standardCharFiles), default="default") - connection = Connection(socketType) - try: - connection.connect(address) - except ConnectionRefusedError: - print("ERROR: Could not connect to server.\nAre you sure that the server is running and that you're connecting to the right address?", file=sys.stderr) - return + colourGroup = parser.add_mutually_exclusive_group() + colourGroup.add_argument('-l', '--colours', '--colors', help='enable colours! :)', action="store_true") + colourGroup.add_argument('-b', '--nocolours', '--nocolors', help='disable colours! :)', action="store_true") + args = parser.parse_args() - caught_ctrl_c = False + charFile = args.characters + if charFile in standardCharFiles: + charFile = os.path.join(charMapPath, charFile + ".json") + with open(charFile, 'r') as cf: + charMap = json.load(cf) + keyFile = args.keybindings + if keyFile in standardKeyFiles: + keyFile = os.path.join(keybindingsPath, keyFile + ".json") + with open(keyFile, 'r') as kf: + keybindings = json.load(kf) - def start(stdscr): - display = Display(stdscr, characters, colours) - client = Client(stdscr, display, name, connection, keybindings) - nonlocal caught_ctrl_c - try: - client.start() - except KeyboardInterrupt: - caught_ctrl_c = True - client.keepAlive = False + address = args.address + if address == None: + address = defaultAdresses[args.socket] + if args.socket == "abstract": + address = '\0' + address + elif args.socket == "inet": + hostname, sep, port = address.partition(':') + address = (hostname, int(port)) - curses.wrapper(start) + colours = True + if args.colours: + colours = True + elif args.nocolours: + colours = False - if caught_ctrl_c: - print('^C caught, goodbye!') + clientmain(args.name, args.socket, address, keybindings, charMap, colours) + diff --git a/asciifarm/client/__main__.py b/asciifarm/client/__main__.py old mode 100755 new mode 100644 index 197f212..ccc3f91 --- a/asciifarm/client/__main__.py +++ b/asciifarm/client/__main__.py @@ -1,79 +1,10 @@ -#! /usr/bin/python3 + import sys +import client if sys.version_info[0] < 3: print("This game is written in python 3.\nRun 'python3 "+sys.argv[0]+"' or './"+sys.argv[0]+"'") sys.exit(-1) -import argparse -import getpass -import json -import os -import os.path - -import client - -thisPath = os.path.dirname(__file__) -farmsPath = os.path.join(thisPath, "..") -charMapPath = os.path.join(farmsPath, "charmaps") -keybindingsPath = os.path.join(farmsPath, "keybindings") - -standardCharFiles = [name[:-5] for name in os.listdir(charMapPath) if name[-5:] == ".json"] -standardKeyFiles = [name[:-5] for name in os.listdir(keybindingsPath) if name[-5:] == ".json"] - - -defaultAdresses = { - "abstract": "asciifarm", - "unix": "asciifarm.socket", - "inet": "localhost:9021", - } - -def main(): - - parser = argparse.ArgumentParser(description="The client to AsciiFarm. Run this to connect to to the server.", epilog=""" - Gameplay information: - Walk around and explore the rooms. - Kill the goblins and plant the seeds. - - ~troido""", formatter_class=argparse.RawDescriptionHelpFormatter) - parser.add_argument('-n', '--name', help='Your player name (must be unique!). Defaults to username', default=getpass.getuser()) - parser.add_argument("-a", "--address", help="The address of the socket. When the socket type is 'abstract' this is just a name. When it is 'unix' this is a filename. When it is 'inet' is should be in the format 'address:port', eg 'localhost:8080'. Defaults depends on the socket type") - parser.add_argument("-s", "--socket", help="the socket type. 'unix' is unix domain sockets, 'abstract' is abstract unix domain sockets and 'inet' is inet sockets. ", choices=["abstract", "unix", "inet"], default="abstract") - parser.add_argument('-k', '--keybindings', help='The file with the keybindings. If it is either of these names: {} it will be loaded from the keybindings directory.'.format(standardKeyFiles), default="default") - parser.add_argument('-c', '--characters', help='The file with the character mappings for the graphics. If it is either of these names: {} it will be loaded from the charmaps directory.'.format(standardCharFiles), default="default") - - colourGroup = parser.add_mutually_exclusive_group() - colourGroup.add_argument('-l', '--colours', '--colors', help='enable colours! :)', action="store_true") - colourGroup.add_argument('-b', '--nocolours', '--nocolors', help='disable colours! :)', action="store_true") - args = parser.parse_args() - - charFile = args.characters - if charFile in standardCharFiles: - charFile = os.path.join(charMapPath, charFile + ".json") - with open(charFile, 'r') as cf: - charMap = json.load(cf) - keyFile = args.keybindings - if keyFile in standardKeyFiles: - keyFile = os.path.join(keybindingsPath, keyFile + ".json") - with open(keyFile, 'r') as kf: - keybindings = json.load(kf) - - address = args.address - if address == None: - address = defaultAdresses[args.socket] - if args.socket == "abstract": - address = '\0' + address - elif args.socket == "inet": - hostname, sep, port = address.partition(':') - address = (hostname, int(port)) - - colours = True - if args.colours: - colours = True - elif args.nocolours: - colours = False - - client.main(args.name, args.socket, address, keybindings, charMap, colours) - -main() +client.main() diff --git a/asciifarm/client/client.py b/asciifarm/client/client.py deleted file mode 100644 index d6e2595..0000000 --- a/asciifarm/client/client.py +++ /dev/null @@ -1,110 +0,0 @@ -#! /usr/bin/python3 - -import os -import sys - -import curses -import threading -#import logging -import json -import getpass -import argparse -from .display.screen import Screen -import string -from .display import Display - -#logging.basicConfig(filename="client.log", filemode='w', level=logging.DEBUG) - -class Client: - - def __init__(self, stdscr, display, name, connection, keybindings): - self.stdscr = stdscr - self.display = display - self.name = name - self.keepalive = True - self.connection = connection - - self.commands = {} - for key, commands in keybindings["input"].items(): - if isinstance(commands[0], str): - commands = [commands] - self.commands[ord(key)] = [["input", command] for command in commands] - - self.controlsString = "Controls:\n"+'\n'.join( - chr(key) + ": " + ', '.join(' '.join(action[1]) for action in actions) - for key, actions in self.commands.items() - if chr(key) in string.printable) - - self.display.showInfo(self.controlsString) - - - - def start(self): - threading.Thread(target=self.listen, daemon=True).start() - self.connection.send(json.dumps(["name", self.name])) - 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 len(data) and isinstance(data[0], str): - data = [data] - for msg in data: - msgType = msg[0] - if msgType == 'error': - error = msg[1] - if error == "nametaken": - print("error: name is already taken", file=sys.stderr) - self.close() - if msgType == 'field': - field = msg[1] - fieldWidth = field['width'] - fieldHeight = field['height'] - self.display.resizeField((fieldWidth, fieldHeight)) - fieldCells = field['field'] - mapping = field['mapping'] - self.display.drawFieldCells( - (tuple(reversed(divmod(i, fieldWidth))), - mapping[spr]) - for i, spr in enumerate(fieldCells)) - - if msgType == 'changecells'and len(msg[1]): - self.display.drawFieldCells(msg[1]) - - if msgType == "playerpos": - self.display.setFieldCenter(msg[1]) - - if msgType == "health": - health = msg[1] - if health: - self.display.setHealth(*health) - if msgType == "inventory": - self.display.setInventory(msg[1]) - if msgType == "ground": - self.display.setGround(msg[1]) - - - self.display.update() - - def command_loop(self): - while self.keepalive: - key = self.stdscr.getch() - if key == 27: - self.keepalive = False - if key in self.commands: - self.connection.send(json.dumps(self.commands[key])) - - - - diff --git a/asciifarm/client/gameclient.py b/asciifarm/client/gameclient.py new file mode 100644 index 0000000..d6e2595 --- /dev/null +++ b/asciifarm/client/gameclient.py @@ -0,0 +1,110 @@ +#! /usr/bin/python3 + +import os +import sys + +import curses +import threading +#import logging +import json +import getpass +import argparse +from .display.screen import Screen +import string +from .display import Display + +#logging.basicConfig(filename="client.log", filemode='w', level=logging.DEBUG) + +class Client: + + def __init__(self, stdscr, display, name, connection, keybindings): + self.stdscr = stdscr + self.display = display + self.name = name + self.keepalive = True + self.connection = connection + + self.commands = {} + for key, commands in keybindings["input"].items(): + if isinstance(commands[0], str): + commands = [commands] + self.commands[ord(key)] = [["input", command] for command in commands] + + self.controlsString = "Controls:\n"+'\n'.join( + chr(key) + ": " + ', '.join(' '.join(action[1]) for action in actions) + for key, actions in self.commands.items() + if chr(key) in string.printable) + + self.display.showInfo(self.controlsString) + + + + def start(self): + threading.Thread(target=self.listen, daemon=True).start() + self.connection.send(json.dumps(["name", self.name])) + 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 len(data) and isinstance(data[0], str): + data = [data] + for msg in data: + msgType = msg[0] + if msgType == 'error': + error = msg[1] + if error == "nametaken": + print("error: name is already taken", file=sys.stderr) + self.close() + if msgType == 'field': + field = msg[1] + fieldWidth = field['width'] + fieldHeight = field['height'] + self.display.resizeField((fieldWidth, fieldHeight)) + fieldCells = field['field'] + mapping = field['mapping'] + self.display.drawFieldCells( + (tuple(reversed(divmod(i, fieldWidth))), + mapping[spr]) + for i, spr in enumerate(fieldCells)) + + if msgType == 'changecells'and len(msg[1]): + self.display.drawFieldCells(msg[1]) + + if msgType == "playerpos": + self.display.setFieldCenter(msg[1]) + + if msgType == "health": + health = msg[1] + if health: + self.display.setHealth(*health) + if msgType == "inventory": + self.display.setInventory(msg[1]) + if msgType == "ground": + self.display.setGround(msg[1]) + + + self.display.update() + + def command_loop(self): + while self.keepalive: + key = self.stdscr.getch() + if key == 27: + self.keepalive = False + if key in self.commands: + self.connection.send(json.dumps(self.commands[key])) + + + + diff --git a/asciifarm/client/start.py b/asciifarm/client/start.py new file mode 100644 index 0000000..4084f7f --- /dev/null +++ b/asciifarm/client/start.py @@ -0,0 +1,41 @@ + +import curses +import json +import os +import getpass +import sys +from .connection import Connection +from .gameclient import Client +from .display import Display + +defaultAdresses = { + "abstract": "asciifarm", + "unix": "asciifarm.socket", + "inet": "localhost:9021", + } + +def main(name, socketType, address, keybindings, characters, colours=False): + + connection = Connection(socketType) + try: + connection.connect(address) + except ConnectionRefusedError: + print("ERROR: Could not connect to server.\nAre you sure that the server is running and that you're connecting to the right address?", file=sys.stderr) + return + + caught_ctrl_c = False + + def start(stdscr): + display = Display(stdscr, characters, colours) + client = Client(stdscr, display, name, connection, keybindings) + nonlocal caught_ctrl_c + try: + client.start() + except KeyboardInterrupt: + caught_ctrl_c = True + client.keepAlive = False + + curses.wrapper(start) + + if caught_ctrl_c: + print('^C caught, goodbye!') -- cgit