From 254cda60e0e0398fb01e2ffdef6a318c1cb59e7b Mon Sep 17 00:00:00 2001 From: Daniel Dolezal Date: Mon, 24 Apr 2023 00:00:49 +0200 Subject: [PATCH] init commit, working save game --- .gitignore | 6 +++ classes/GameBoard.py | 58 ++++++++++++++++++++++++++++ classes/Map.py | 22 +++++++++++ classes/Player.py | 16 ++++++++ classes/SavedState.py | 19 ++++++++++ my_helpers/myPickle.py | 85 ++++++++++++++++++++++++++++++++++++++++++ requirements.txt | 4 ++ run.py | 26 +++++++++++++ 8 files changed, 236 insertions(+) create mode 100644 .gitignore create mode 100644 classes/GameBoard.py create mode 100644 classes/Map.py create mode 100644 classes/Player.py create mode 100644 classes/SavedState.py create mode 100644 my_helpers/myPickle.py create mode 100644 requirements.txt create mode 100644 run.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e8d832f --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +.venv/ +__pycache__/ + +*.pyc +Map/*.json +**/*pkl* diff --git a/classes/GameBoard.py b/classes/GameBoard.py new file mode 100644 index 0000000..c7fa33d --- /dev/null +++ b/classes/GameBoard.py @@ -0,0 +1,58 @@ +from classes.SavedState import SavedState +import my_helpers.myPickle as my_pickle + +import os + +class GameBoard: + def __init__(self, config:dict, save_state_file:dict, map_file:dict): + self.config = config + self.save_state_file = save_state_file + self.map_file = map_file + + def create_character(self, player_config:dict): + name = input("Enter Character Name: ") + + species = list(player_config["species"].keys()) + print(species) + + types = [ x["name"] for x in player_config["types"] ] + print(types) + + species_selected = player_config["species"]["Gnoll"] + species_selected["name"] = "Gnoll" + + return { + "name": name, + "species": species_selected, + "type": types + } + + def find_save_state(self): + if os.path.exists(self.save_state_file['path']): + saved_state:SavedState = self.load_from_file(self.save_state_file) + else: + saved_state = SavedState() + player = self.create_character(self.config["player"]) + saved_state.add_player(player) + self.save_to_file(saved_state, self.save_state_file) + + self.map = self.load_from_file(self.map_file) + self.saved_state = saved_state + return saved_state + + def load_from_file(self, file_options): + if os.path.exists(file_options["path"]): + with open(file_options["path"], "rb") as f: + data = my_pickle.load(f, file_options['compression'], None) + + return data + else: + raise FileNotFoundError(f"Could not load map file: {file_options['path']}") + + def save_to_file(self, obj, file_options): + os.makedirs(os.path.dirname(file_options["path"]), exist_ok=True) + with open(file_options["path"], "wb") as f: + my_pickle.dump(obj, f, file_options['compression'], None) + + def get_world(self): + return self.map[self.saved_state.story_position]["World"][self.saved_state.story_world_index] \ No newline at end of file diff --git a/classes/Map.py b/classes/Map.py new file mode 100644 index 0000000..73c8dec --- /dev/null +++ b/classes/Map.py @@ -0,0 +1,22 @@ +from json import load as json_load +import os + +class Map: + def __init__(self, path): + self.path = path + self.story = {} + + def make_file(self, story:dict={}): + for file in os.listdir(self.path): + if file.endswith("json"): + with open(f"{self.path}/{file}", "r") as f: + filename = os.path.splitext(os.path.basename(file))[0] + story[filename] = json_load(f) + + self.story = story + + def __str__(self): + return f"{self.__class__.__name__} | Story: {self.story}" + + def __getitem__(self, key): + return self.story[key] diff --git a/classes/Player.py b/classes/Player.py new file mode 100644 index 0000000..b3dfb43 --- /dev/null +++ b/classes/Player.py @@ -0,0 +1,16 @@ +class Player: + def __init__(self, name:str, type:dict, species:dict): + self.name = name + self.type = type + self.species = species + self.inventory = [] + self.inventory_size = species["inventory_size"] + + def get_inventory(self): + return self.inventory + + def attack(self): + pass + + def __str__(self): + return f"{self.__class__.__name__} | Name :{self.name}\nType :{self.type}\nSpecies :{self.species}\nInventory: {self.inventory}" diff --git a/classes/SavedState.py b/classes/SavedState.py new file mode 100644 index 0000000..30306e9 --- /dev/null +++ b/classes/SavedState.py @@ -0,0 +1,19 @@ +from classes.Player import Player + +from classes.MapObject.Home import Home + +class SavedState: + def __init__(self, story_position:str="The Beginning"): + self.home = Home() + + self.story_position = story_position + self.story_world_index = 0 + + def add_player(self, player:dict): + self.player = Player(player["name"], player["type"], player["species"]) + + def get_home(self): + return self.home + + def get_player(self): + return self.player diff --git a/my_helpers/myPickle.py b/my_helpers/myPickle.py new file mode 100644 index 0000000..964c894 --- /dev/null +++ b/my_helpers/myPickle.py @@ -0,0 +1,85 @@ +from cryptography.fernet import Fernet +import pickle +import io + +def writeKey(filename:str) -> Fernet: + """ + Generates a key and save it into a file + """ + key = Fernet.generate_key() + with open(f'{filename}.key', 'wb') as key_file: + key_file.write(key) + + return Fernet(key) + +def generateKey() -> Fernet: + """ + Generates a key and returns it + """ + key = Fernet.generate_key() + return Fernet(key) + +def loadKey(filename:str) -> Fernet: + """ + Loads the key from the current directory named `key.key` + """ + with open(f'{filename}.key', 'rb') as f: + data = f.read() + return Fernet(data) + +def dumps(obj, compress=None, encrypt:Fernet=None) -> bytes: + """ + Dumps the object into a byte stream + """ + data = pickle.dumps(obj) + if compress: + data = compress.compress(data) + if encrypt: + data = encrypt.encrypt(data) + + return data + +def dump(obj, file: io.BytesIO, compress=None, encrypt:Fernet=None) -> None: + """ + Dumps the object into a file + """ + data = pickle.dumps(obj) + data = dumps(data, compress, encrypt) + + file.write(data) + file.flush() + +def loads(data, compress=None, encrypt:Fernet=None) -> object: + """ + Loads the object from a byte stream + """ + if encrypt: + data = encrypt.decrypt(data) + if compress: + data = compress.decompress(data) + + return pickle.loads(data) + +def load(file: io.BytesIO, compress=None, encrypt:Fernet=None) -> object: + """ + Loads the object from a file + """ + data = file.read() + data = loads(data, compress, encrypt) + + return pickle.loads(data) + +if __name__ == "__main__": + import lzma + + data = {'a': 'A', 'b': (1, 2, 3, 4, 5)} + #writeKey('key') + key = loadKey('key') + dataCompressedAndEncrypted = dumps(data, compress=lzma, encrypt=key) + print(dataCompressedAndEncrypted) + + del key + + key = loadKey('key') + dataCompressedAndEncrypted = loads(dataCompressedAndEncrypted, compress=lzma, encrypt=key) + print(dataCompressedAndEncrypted) \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..9b40642 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +cffi==1.15.1 +cryptography==40.0.2 +pip-autoremove==0.10.0 +pycparser==2.21 diff --git a/run.py b/run.py new file mode 100644 index 0000000..1ac913a --- /dev/null +++ b/run.py @@ -0,0 +1,26 @@ +from classes.GameBoard import GameBoard + +from json import load as json_load +import lzma + +if __name__ == '__main__': + with open("config.json", "r") as f: + CONFIG = json_load(f) + + SAVE_STATE_FILE = { + "path": f"{CONFIG['save_file']['path']}/{CONFIG['save_file']['filename']}", + "compression": lzma, + "key": CONFIG["save_file"]["encryption_key"] + } + MAP_FILE = { + "path": f"{CONFIG['map_file']['path']}/{CONFIG['map_file']['filename']}", + "compression": lzma, + "key": CONFIG["map_file"]["encryption_key"] + } + + game_board = GameBoard(CONFIG, SAVE_STATE_FILE, MAP_FILE) + saved_state = game_board.find_save_state() + + print("Story Pos:", game_board.get_world()) + print(game_board.map) + print(saved_state.get_player())