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')