Created
June 29, 2022 08:52
-
-
Save kubinka0505/000b77ae8b33be086d271ad067343ada to your computer and use it in GitHub Desktop.
Automatic script for Gothic saves backup.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""Gothic Saves Backup | |
Automatic script for Gothic saves backup.""" | |
from os import * | |
from tkinter import * | |
from zipfile import * | |
from pathlib import Path | |
from shutil import rmtree | |
from tkinter import filedialog as fd | |
from distutils.dir_util import copy_tree | |
del open | |
#-=-=-=-# | |
__author__ = "kubinka0505" | |
__credits__ = __author__ | |
__version__ = "1.0" | |
__date__ = "29.06.2022" | |
#-=-=-=-=-=-# | |
# Game location | |
# | |
# Gothic I - r"C:/Program Files (x86)/Piranha Bytes/Gothic" | |
# Gothic II - r"C:/Program Files (x86)/JoWood/Gothic II Zlota Edycja" | |
Game = r"C:/Program Files (x86)/JoWood/Gothic II Zlota Edycja" | |
# Saveslot number | |
# | |
# "savegameX", where X is number (10 stands for "savegame10" etc.) | |
Save_Slot = 10 | |
Output_Directory = r"~/Documents/Gothic_Saves_Backup" | |
# Keep first unnamed savegame | |
# | |
# True if first savegame named "---" will be archived, False for last | |
Keep_First = True | |
#-=-=-=-=-=-# | |
def Clamp(Number: float, Minimum: float, Maximum: float) -> float: | |
"""Limits `Number` in range (`Minimum`, `Maximum`).""" | |
return max(min(Maximum, Number), Minimum) | |
def Path(Path: str): | |
"""Resolves path using `pathlib.Path.resolve`.""" | |
return str(Path.resolve()) | |
#-=-=-=-# | |
root = Tk() | |
root.withdraw() | |
Counter = 0 | |
Saves_Folders = [] | |
Sorted_Saves = {"Main": {}, "Cleared": {}} | |
Save_Slot = str(Clamp(Save_Slot), 1, 20) | |
Output_Directory = path.expanduser(Output_Directory) | |
Game = NormPath(Game) | |
chdir(Game) | |
#-=-=-=-# | |
# Find latest save folder | |
for Folder in Path(Game).glob("*"): | |
Folder = NormPath(Folder).lower() | |
#-=-=-=-# | |
if "saves_" in Folder: | |
Saves_Folders.append(Folder.split(sep)[-1]) | |
Saves_Folders = sorted(Saves_Folders, key = path.getmtime) | |
Latest_Save_Folder = Saves_Folders[-1] | |
# Select folder | |
Save_Folder = fd.askdirectory( | |
title = "Open saves directory", | |
initialdir = path.abspath(Latest_Save_Folder) | |
) | |
Save_Folder = path.basename(Save_Folder).split("saves_")[-1] | |
# Go to output directory | |
Output_Directory = NormPath( | |
path.join( | |
Output_Directory, | |
Save_Folder | |
) | |
) | |
print(f'Output directory is "{Output_Directory}"') | |
print(f'Game directory is "{Game}"') | |
# Remove existing saves | |
if path.exists(Output_Directory): | |
print(f'\nRemoving existing "{path.basename(Save_Folder)}" saves...') | |
rmtree(Output_Directory) | |
else: | |
makedirs(Output_Directory) | |
# Copy saves | |
try: | |
copy_tree("saves_" + Save_Folder, Output_Directory) | |
print("Copied saves") | |
except OSError: | |
raise SystemExit("File selection aborted") | |
chdir(Output_Directory) | |
# Remove "current" directory | |
try: | |
rmtree("current") | |
except OSError: | |
pass | |
# Get save states names | |
for Folder in next(walk("."))[1][::1 if Keep_First else -1]: | |
File = path.abspath(path.join(Folder, "SaveInfo.sav")) | |
File = open(File).read() | |
Sorted_Saves["Main"][ | |
File.split("Title=string:")[-1].split("\n")[0] | |
] = Folder | |
# Remove duplicate savestates with "---" name | |
for Key, Value in Sorted_Saves["Main"].items(): | |
if Value not in Sorted_Saves["Cleared"].values(): | |
Sorted_Saves["Cleared"][Key] = Value | |
# Copy saves to named folders | |
for Key, Value in Sorted_Saves["Cleared"].items(): | |
mkdir(Key) | |
copy_tree( | |
Value, | |
Key.replace("_", " ").title() + "/savegame" + Save_Slot | |
) | |
rmtree(Value) | |
# Remove junk | |
for Folder in next(walk("."))[1]: | |
if Folder not in Sorted_Saves["Cleared"].keys(): | |
rmtree(Folder) | |
# Making archives | |
print("\nMaking archives...") | |
try: | |
for Folder in next(walk("."))[1]: | |
Counter += 1 | |
print( | |
"\t", | |
f"[{Counter}/{len(listdir())}]", | |
f"\t\t{Folder}", | |
"\t" * 3, | |
#-=-=-=-# | |
end = "\r" | |
) | |
#-=-=-=-# | |
with ZipFile(Folder + ".zip", "w", ZIP_DEFLATED, 0, 9) as ZIP: | |
for File in Path(Folder).glob("**/*"): | |
ZIP.write(File) | |
rmtree(Folder) | |
except (KeyboardInterrupt, EOFError): | |
raise SystemExit("Making archives aborted") | |
# Open containing directory | |
print("Done!\a") | |
system(fr'start /max C:\Windows\explorer.exe "{Output_Directory}"') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment