Initial Commit
This commit is contained in:
commit
bce7314e43
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
mods/
|
||||
venv/
|
||||
.idea/
|
||||
*.jar
|
||||
*.log
|
38
StickyPiston/StickyPiston.py
Normal file
38
StickyPiston/StickyPiston.py
Normal file
@ -0,0 +1,38 @@
|
||||
import requests
|
||||
import datetime
|
||||
|
||||
|
||||
class StickyPiston:
|
||||
def __init__(self):
|
||||
self.url = ""
|
||||
self.version = "v0.0.1a"
|
||||
self.last_version_check = datetime.datetime.utcnow()
|
||||
self.up_to_date = None
|
||||
|
||||
def version_url(self) -> str:
|
||||
sep = '/' if self.url[-1] != '/' else ''
|
||||
return self.url + sep + 'piston_version'
|
||||
|
||||
def check_for_updates(self):
|
||||
"""Checks for any updates to the StickyPiston module."""
|
||||
self.last_version_check = datetime.datetime.utcnow()
|
||||
|
||||
resp = requests.get(self.version_url())
|
||||
resp.raise_for_status()
|
||||
|
||||
current_version = resp.json()['version']
|
||||
self.up_to_date = current_version.strip() == self.version.strip()
|
||||
|
||||
def up_to_date(self) -> str:
|
||||
if not self.up_to_date:
|
||||
self.check_for_updates()
|
||||
if self.up_to_date():
|
||||
return "Up to date"
|
||||
return "New version available"
|
||||
|
||||
def update(self, force: bool = False):
|
||||
if force or not self.up_to_date():
|
||||
# perform the update
|
||||
pass
|
||||
else:
|
||||
return 0
|
0
StickyPiston/__init__.py
Normal file
0
StickyPiston/__init__.py
Normal file
251
pyPiston.py
Normal file
251
pyPiston.py
Normal file
@ -0,0 +1,251 @@
|
||||
# find minecraft installation
|
||||
# install forge client
|
||||
# create install if one doesn't already exist
|
||||
# copy mods to folder
|
||||
|
||||
import os
|
||||
from sys import stdout
|
||||
import json
|
||||
import uuid
|
||||
import logging
|
||||
import webbrowser
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
from distutils.dir_util import copy_tree
|
||||
import zipfile
|
||||
# from StickyPiston import StickyPiston
|
||||
|
||||
|
||||
DT_FORMAT = '%Y-%m-%dT%H:%M:%S.%fZ'
|
||||
PROFILE_NAME = "William's Modded 1.19.2"
|
||||
|
||||
|
||||
class MinecraftProfile:
|
||||
def __init__(
|
||||
self,
|
||||
profile_id: str,
|
||||
dt_created: datetime,
|
||||
icon: str,
|
||||
last_used: datetime,
|
||||
last_version_id: str,
|
||||
profile_name: str = '',
|
||||
profile_type: str = 'custom',
|
||||
java_args: str = '',
|
||||
game_dir: Path = None
|
||||
):
|
||||
self.profile_id = profile_id
|
||||
self.dt_created = dt_created
|
||||
self.icon = icon
|
||||
self.last_used = last_used
|
||||
self.last_version_id = last_version_id
|
||||
self.profile_name = profile_name
|
||||
self.profile_type = profile_type
|
||||
self.java_args = java_args
|
||||
self.game_dir = game_dir
|
||||
|
||||
@classmethod
|
||||
def from_json_obj(cls, obj, profile_id):
|
||||
return cls(
|
||||
profile_id=profile_id,
|
||||
dt_created=datetime.strptime(obj['created'], DT_FORMAT) if obj.get('created') else None,
|
||||
icon=obj.get('icon', 'Crafting_Table'),
|
||||
last_used=datetime.strptime(obj['lastUsed'], DT_FORMAT) if obj.get('lastUsed') else None,
|
||||
last_version_id=obj.get('lastVersionId', 'latest-release'),
|
||||
profile_name=obj.get('name', ''),
|
||||
profile_type=obj.get('type', 'latest-release'),
|
||||
java_args=obj.get('javaArgs', ''),
|
||||
game_dir=Path(obj['gameDir']) if obj.get('gameDir') else None
|
||||
)
|
||||
|
||||
def to_json(self) -> dict:
|
||||
return {
|
||||
"created": self.dt_created.strftime(DT_FORMAT),
|
||||
"gameDir": str(self.game_dir),
|
||||
'icon': self.icon,
|
||||
'javaArgs': self.java_args,
|
||||
'lastUsed': self.last_used.strftime(DT_FORMAT),
|
||||
'lastVersionId': self.last_version_id,
|
||||
'name': self.profile_name,
|
||||
'type': self.profile_type
|
||||
}
|
||||
|
||||
|
||||
def get_minecraft_folder(**kwargs):
|
||||
|
||||
mc_path = kwargs.get('minecraft_root', Path(os.getenv('APPDATA')) / '.minecraft')
|
||||
|
||||
if mc_path.exists():
|
||||
return mc_path
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def load_profiles(**kwargs):
|
||||
|
||||
mc_path = kwargs.get('minecraft_path', get_minecraft_folder())
|
||||
|
||||
profiles_file = mc_path / 'launcher_profiles.json'
|
||||
|
||||
profiles_list = []
|
||||
if profiles_file.exists():
|
||||
with open(profiles_file, 'r') as json_file:
|
||||
profiles_json = json.load(json_file)
|
||||
for profile in profiles_json['profiles']:
|
||||
profile_obj = profiles_json['profiles'][profile]
|
||||
profiles_list.append(
|
||||
MinecraftProfile.from_json_obj(profile_obj, profile)
|
||||
)
|
||||
|
||||
return profiles_list
|
||||
|
||||
|
||||
def add_profile(profile: MinecraftProfile):
|
||||
mc_path = get_minecraft_folder()
|
||||
|
||||
profiles_file = mc_path / 'launcher_profiles.json'
|
||||
|
||||
profiles_list = load_profiles()
|
||||
|
||||
if profile.profile_id in [p.profile_id for p in profiles_list]:
|
||||
return 0
|
||||
|
||||
with open(profiles_file, 'r') as json_file:
|
||||
json_raw = json.load(json_file)
|
||||
|
||||
json_raw['profiles'][profile.profile_id] = profile.to_json()
|
||||
|
||||
with open(profiles_file, 'w') as json_file:
|
||||
json.dump(json_raw, json_file, indent=2)
|
||||
|
||||
return 1
|
||||
|
||||
|
||||
def any_key():
|
||||
return input("Press enter to continue...")
|
||||
|
||||
|
||||
def package_mods(profile_name: str):
|
||||
"""
|
||||
Packages mods into a zip file for distribution
|
||||
:param profile_name: The name of the profile to be deployed
|
||||
:return:
|
||||
"""
|
||||
|
||||
profiles_list = load_profiles()
|
||||
|
||||
profile_to_load = [profile for profile in profiles_list if profile.profile_name == profile_name]
|
||||
|
||||
if not profile_to_load:
|
||||
raise IndexError(f"Profile {profile_name} does not exist!")
|
||||
|
||||
if len(profile_to_load) == 1:
|
||||
profile_to_load = profile_to_load[0]
|
||||
else:
|
||||
raise IndexError(f"Multiple profiles match the name {profile_name}!")
|
||||
|
||||
# Create the zip
|
||||
zip_file_name = profile_name.strip().lower().replace(' ', '_') + '.zip'
|
||||
with zipfile.ZipFile(zip_file_name, 'w', zipfile.ZIP_DEFLATED) as zipf:
|
||||
for root, dirs, files in os.walk(profile_to_load.game_dir):
|
||||
for file in files:
|
||||
if not file.endswith('.jar'):
|
||||
# Skip all non-jar files
|
||||
continue
|
||||
zipf.write(
|
||||
os.path.join(root, file),
|
||||
os.path.relpath(
|
||||
os.path.join(root, file),
|
||||
os.getcwd()
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
log = logging.getLogger()
|
||||
log.setLevel(logging.DEBUG)
|
||||
log.addHandler(logging.StreamHandler(stream=stdout))
|
||||
|
||||
profiles = load_profiles()
|
||||
forge_profiles = [profile for profile in profiles if 'forge' in profile.last_version_id]
|
||||
log.info(f"Hello and welcome! I'm going to install the modpack this script was packaged with.")
|
||||
log.info(f"You shouldn't have to do anything - I'll let you know if I found anything weird that I need help with.")
|
||||
log.debug(f"Found {len(forge_profiles)} modded profiles")
|
||||
|
||||
if PROFILE_NAME in [profile_name.profile_name for profile_name in forge_profiles]:
|
||||
log.info(f"Modpack is already installed, exiting!")
|
||||
return 0
|
||||
|
||||
# Before we add the profile, we need to make sure forge is installed
|
||||
forge_profile = [profile for profile in profiles if profile.profile_name == 'forge'
|
||||
and profile.last_version_id == '1.19.2-forge-43.1.42']
|
||||
if not forge_profile:
|
||||
# We need to install the forge version we were packaged with!
|
||||
# First, make sure java is installed and on the path:
|
||||
java_version_output = os.system('java --version')
|
||||
if java_version_output != 0:
|
||||
# Java is not installed!
|
||||
log.info(f"Java is not installed! Please install OpenJDK and run this script again.")
|
||||
webbrowser.open("https://aka.ms/download-jdk/microsoft-jdk-17.0.4.1-windows-x64.msi")
|
||||
any_key()
|
||||
return 1
|
||||
|
||||
log.info(f"Forge needs to be installed - select \"install client\" and follow the on-screen prompts.")
|
||||
log.info(f"Check back here when you're done!")
|
||||
forge_install_output = os.system('java -jar forge-1.19.2-43.1.42-installer.jar')
|
||||
if forge_install_output != 0:
|
||||
log.error(f"The install command failed! Is java installed?")
|
||||
any_key()
|
||||
return 1
|
||||
|
||||
log.info(f"Modpack is not already installed - just needed to check that before continuing!")
|
||||
modded_folder = Path(os.getenv('APPDATA')) / '.moddedminecraft' / '1.19.2' / PROFILE_NAME
|
||||
if modded_folder.exists():
|
||||
log.warning(f"Profile path already exists! Continuing, but this is weird!")
|
||||
else:
|
||||
try:
|
||||
modded_folder.mkdir(parents=True, exist_ok=True)
|
||||
except BaseException as e:
|
||||
log.error(f"I ran into an error while trying to make the profile path... can you make it for me?\n"
|
||||
f"The path needs to be here: {modded_folder}\n"
|
||||
f"Once you create it, run this script again, and I should be good to go.",
|
||||
exc_info=e)
|
||||
any_key()
|
||||
raise e
|
||||
log.info(f"Created profile path successfully!")
|
||||
modded_profile = MinecraftProfile(
|
||||
profile_id=str(uuid.uuid4()).replace('-', ''),
|
||||
profile_name=PROFILE_NAME,
|
||||
dt_created=datetime.utcnow(),
|
||||
icon='Furnace_On',
|
||||
java_args=" ".join([
|
||||
"-Xmx8G",
|
||||
"-XX:+UnlockExperimentalVMOptions",
|
||||
"-XX:+UseG1GC",
|
||||
"-XX:G1NewSizePercent=20",
|
||||
"-XX:G1ReservePercent=20",
|
||||
"-XX:MaxGCPauseMillis=50",
|
||||
"-XX:G1HeapRegionSize=32M"
|
||||
]),
|
||||
last_used=datetime.utcnow(),
|
||||
last_version_id='1.19.2-forge-43.1.42',
|
||||
profile_type='custom',
|
||||
game_dir=modded_folder
|
||||
)
|
||||
|
||||
log.debug(f"Profile to be added:\n{json.dumps(modded_profile.to_json(), indent=4)}")
|
||||
|
||||
add_profile(modded_profile)
|
||||
log.info(f"Profile added! Copying mod files...")
|
||||
|
||||
mods_folder = Path('mods')
|
||||
dest_mods_folder = modded_profile.game_dir / 'mods'
|
||||
dest_mods_folder.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
copy_tree(str(mods_folder), str(dest_mods_folder))
|
||||
|
||||
log.info("All done!")
|
||||
any_key()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
Loading…
x
Reference in New Issue
Block a user