diff --git a/.gitignore b/.gitignore index f8b73e7..630a2ad 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +.idea/ +testing_data/ + # ---> Python # Byte-compiled / optimized / DLL files __pycache__/ diff --git a/piston.py b/piston.py new file mode 100644 index 0000000..638522f --- /dev/null +++ b/piston.py @@ -0,0 +1,95 @@ +import platform +from pathlib import PurePath, Path +from os import getenv +import json +import uuid +from zipfile import ZipFile +import datetime +import logging + +# Launcher/Install profiles are found in .minecraft/launcher_profiles.json + + +def get_sysroot(): + if platform.system() == 'Windows': + if getenv('APPDATA'): + return PurePath(getenv('APPDATA')) + if platform.system() == 'Darwin': + return PurePath(Path.home(), 'Library', 'Application Support') + if platform.system() == 'Linux': + return PurePath(Path.home()) + return None + + +def get_minecraft_folder(sys_root): + return sys_root / f"{'' if platform.system() == 'Darwin' else '.'}minecraft" + + +def get_installs(minecraft_folder): + with open(minecraft_folder / 'launcher_profiles.json') as f: + json_data = json.load(f) + return json_data.get('profiles') + + +def get_modpack_id(modpack_name, install_list): + for install in install_list: + if modpack_name in install_list[install]['name']: + return install + return None + + +def main(modpack_path): + # Get Minecraft Install Location + sys_root = get_sysroot() + if not sys_root: + sys_root = input("Unable to locate your minecraft install - please enter it here: ") + + logging.debug(f"System path set to: {sys_root}") + + # Get Modpack Name from zipfile: + modpack_name = modpack_path.stem + logging.debug(f"Modpack name extracted as: {modpack_name}") + + # Get Minecraft Installs + install_list = get_installs(get_minecraft_folder(sys_root)) + modpack_id = get_modpack_id(modpack_name, install_list) or uuid.uuid4().hex + logging.debug(f"Modpack ID extracted as: {modpack_id}") + + install_path = sys_root / '.moddedminecraft' / modpack_name + logging.debug(f"Modpack install path set to: {install_path}") + + # Check if modpack is already installed + if modpack_id not in install_list: + logging.info(f"Modpack {modpack_name} ({modpack_id}) not found in install list - creating...") + install_list[modpack_id] = { + 'created': datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z', + 'gameDir': install_path, + 'icon': 'Redstone_Block', + 'javaArgs': '-Xmx4G ' + '-XX:+UnlockExperimentalVMOptions ' + '-XX:+UseG1GC -XX:G1NewSizePercent=20 ' + '-XX:G1ReservePercent=20 ' + '-XX:MaxGCPauseMillis=50 ' + '-XX:G1HeapRegionSize=32M', + 'lastUsed': '', + 'lastVersionId': '1.16.5-forge-36.0.43', + 'name': modpack_name, + 'type': 'custom' + } + with open(get_minecraft_folder(sys_root) / 'launcher_profiles.json', 'r') as f: + full_profile_setup = json.load(f) + with open(get_minecraft_folder(sys_root) / 'launcher_profiles.json', 'w') as f: + full_profile_setup['profiles'] = install_list + json.dump(full_profile_setup, f) + logging.info(f"Successfully added mod to installed profile list.") + + # Validate file structure compared to mod zip + with ZipFile(modpack_path, 'r') as zip: + logging.info("Validating mod files...") + Path(install_path).mkdir(parents=True, exist_ok=True) + zip.extractall(install_path) + logging.info("Validation Completed.") + + +if __name__ == '__main__': + main(PurePath() / 'testing_data' / 'FusterCluck_test.zip')