From f3d8655a95172a3551b0fb2c64654c1b98f5c304 Mon Sep 17 00:00:00 2001 From: Mr Finchum Date: Tue, 3 Dec 2024 17:57:48 +0000 Subject: [PATCH] Feature/basic version A python script consisting of just functions that backups and restore the continue.sav. --- README.md | 7 +- ftl-backup_script.py | 167 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 173 insertions(+), 1 deletion(-) create mode 100644 ftl-backup_script.py diff --git a/README.md b/README.md index d9d0a8b..de0e2bf 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,12 @@ # FTL Save File Manager Recreating the program I wrote in school in VS Basic but in Python. - It is a program enabling saving and loading in FTL (Faster Then Light) game. It is considered as a project to learn and be more confident with Python as well as Git. + + +## How it works +It has a very simple menu after starting, with option such as backup, restore backup, delete backup files and quite the program. +Import to notice how to backup and restore. +Backup can be done after a jump, restore does only work when the game is in main menu. diff --git a/ftl-backup_script.py b/ftl-backup_script.py new file mode 100644 index 0000000..39d1f80 --- /dev/null +++ b/ftl-backup_script.py @@ -0,0 +1,167 @@ +import os +import time +from datetime import datetime + +version = 0.01 +settings_path = "local_files/settings.txt" # containes two lines, first path of game, second path of savelocation +backup_files = {"1": "initiating"} # initiating global variable to be used in functions. + +def menu(options, names): + """"Use dict to select an option (function).""" + print_menu(options, names) + while True: + choice = input("Selection Option: ") + if choice in options: + options[choice]() + print_menu(options, names) + else: + print("Try again") + continue + +def print_menu(options, names): + #print("\033[H\033[J", end="") + print("Menu options") + for key in options: + print(f"{key}: {names[key]}") + +def copy_file(src, dst): + """"Simply copies a file from a to b.""" + if not os.path.isfile(src): + print(f"File to copy {src} does not exist.") + return False + os.system(f"cp {src} {dst}") + print(f"Wrote: {dst}") + +def list_backup(): + """"List all files inside the backup folder.""" + files = os.listdir(backup_path) + files.reverse() # this way the newest file is the top one. + backup_files.clear() + i = 1 + for file in files: + new_item = {f"{i}": file} + print(f"[{i}] {file}") + backup_files.update(new_item) + i += 1 + +def backup(): + """Copies the game file to the backup folder and adds date-time stamp.""" + now = datetime.now() + formatted_now = now.strftime("%Y-%m-%d_%H-%M") + copy_file(f"{game_path}/continue.sav", f"{backup_path}/{formatted_now}.bkup") + time.sleep(1) + +def restore(): + """Copies a selected backup file to the game folder.""" + print("Select a file to restore (back [b]):") + list_backup() + while True: + choice = input("Enter number (b = back): ") + if choice in backup_files: + copy_file(f"{backup_path}/{backup_files[choice]}", f"{game_path}/continue.sav") + print(f"{backup_files[choice]} restored.") + time.sleep(1) + break + elif choice == "b": + break + else: + print("not a valid option") + continue + +def delete_backup_file(): + # Making a yes/no function would be cleaner + if yes_no("Backup"): + for file in os.listdir(backup_path): + if file[-5:] == ".bkup": + try: + print(f"Deleting {file}.") + os.remove(f"{backup_path}/{file}") + time.sleep(1) + except Exception as e: + print(f"Failed to delete {file}. Reason: {e}.") + time.sleep(3) + +def yes_no(str): + while True: + choice = input(f"Are you sure you want to delete all {str} files? (y/n)") + if choice == "y": + return 1 + elif choice == "n": + print(f"Deleting {str} files aborted") + time.sleep(1) + return 0 + else: + print("Not a valid option, try again") + +def read_settings(): + if os.path.exists(settings_path): + with open(settings_path, "r") as f: + data = f.readlines() + for i in range(len(data)): + data[i] = data[i].strip() #stripping white space + return(data) + else: + print("settings file does not exit.") + return 0 + +def ask_for_path(): + paths = ["game_path", "backup_path"] + + paths[0] = get_path("Absolut save path") + paths[1] = get_path("Backup path") + return(paths) + +def get_path(str): + while True: + path = input(f"please enter {str}: ") + if os.path.exists(path): + break + else: + print("Path not valid, try again.") + continue + return path + +def write_settings(list): + with open(settings_path, "w") as f: + for item in list: + f.write(item + "\n") + + print("write settings.") + +settings = read_settings() +if settings != False: + game_path = settings[0] + backup_path = settings[1] + if not os.path.exists(f"{game_path}/ae_prof.sav") and not os.path.exists(backup_path): + print("Path in settings file are incorrect.") + paths = ask_for_path() + game_path = paths[0] + backup_path = paths[1] + write_settings((game_path, backup_path)) +else: + paths = ask_for_path() + game_path = paths[0] + backup_path = paths[1] + write_settings((game_path, backup_path)) + +print(f"Game location: {game_path}.\nSave loction: {backup_path}\n") +time.sleep(1) + +menu_options = { + "b": backup, + "r": restore, + "d": delete_backup_file, + "q": exit +} +menu_names = { + "b": "Backup now", + "r": "Restore backup", + "d": "Delete backup files", + "q": "Exit" +} +menu(menu_options, menu_names) + + +# TODO +# Backup profile +# updater