143 lines
5.0 KiB
Python
Executable File
143 lines
5.0 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
import os
|
|
import re
|
|
import shutil
|
|
import hashlib
|
|
from datetime import datetime
|
|
|
|
REPO_DIR = "/tmp/mod_repo"
|
|
SERVER_MODS_FILE = "/tmp/server_mods.txt"
|
|
MINECRAFT_MODS_DIR = "/home/minecraft/mods"
|
|
TACZ_DIR = "/home/minecraft/tacz"
|
|
STATE_DIR = f"{REPO_DIR}/state"
|
|
MODPACK_DIR = f"{REPO_DIR}/modpack"
|
|
VERSION_FILE = f"{REPO_DIR}/VERSION"
|
|
TRUEMODS_DIR = f"{REPO_DIR}/truemods"
|
|
TRUEGUNPACKS_DIR = f"{REPO_DIR}/truegunpacks"
|
|
|
|
CLIENT_ONLY_MODS = [
|
|
"jei", "xaero", "ambient", "apple", "inventoryprofiles",
|
|
"chunky", "patchouli", "worldedit", "spark", "customskinloader", "gd656killicon"
|
|
]
|
|
|
|
def log(msg):
|
|
ts = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
print(f"[{ts}] {msg}")
|
|
|
|
def get_mod_name(jar_path):
|
|
basename = os.path.basename(jar_path)
|
|
name = re.sub(r'-\d+.*\.jar$', '', basename)
|
|
name = re.sub(r'^\[.*?\]\s*', '', name)
|
|
return name
|
|
|
|
def is_client_only(mod_name):
|
|
mod_lower = mod_name.lower()
|
|
for client_mod in CLIENT_ONLY_MODS:
|
|
if client_mod in mod_lower:
|
|
return True
|
|
return False
|
|
|
|
def get_hash(path):
|
|
with open(path, 'rb') as f:
|
|
return hashlib.sha1(f.read()).hexdigest()
|
|
|
|
def sync_minimal_pack():
|
|
for d in [TRUEMODS_DIR, TRUEGUNPACKS_DIR]:
|
|
if os.path.exists(d):
|
|
shutil.rmtree(d)
|
|
os.makedirs(d)
|
|
|
|
with open(SERVER_MODS_FILE, 'r') as f:
|
|
server_mods = [line.strip() for line in f if line.strip() and not line.startswith('disabled')]
|
|
|
|
included, excluded = [], []
|
|
|
|
for mod in server_mods:
|
|
base_name = re.sub(r'-\d+.*$', '', mod)
|
|
jar_file = None
|
|
for f in os.listdir(MINECRAFT_MODS_DIR):
|
|
if f.startswith(base_name) and f.endswith('.jar'):
|
|
jar_file = os.path.join(MINECRAFT_MODS_DIR, f)
|
|
break
|
|
|
|
if jar_file:
|
|
mod_name = get_mod_name(jar_file)
|
|
filename = os.path.basename(jar_file)
|
|
if is_client_only(mod_name):
|
|
excluded.append(filename)
|
|
else:
|
|
shutil.copy(jar_file, TRUEMODS_DIR)
|
|
included.append(filename)
|
|
|
|
if os.path.exists(TACZ_DIR):
|
|
for f in os.listdir(TACZ_DIR):
|
|
if f.endswith('.zip'):
|
|
shutil.copy(os.path.join(TACZ_DIR, f), TRUEGUNPACKS_DIR)
|
|
|
|
return sorted(included), sorted(excluded), sorted(os.listdir(TRUEGUNPACKS_DIR))
|
|
|
|
def create_index(version, mods, gunpacks):
|
|
lines = ['{', ' "formatVersion": 1,', ' "game": {', ' "type": "forge",',
|
|
' "version": "1.20.1"', ' },', f' "versionId": "{version}",',
|
|
' "name": "minimal-client-modpack",',
|
|
' "summary": "Minimal client modpack for connecting to the server"', ' "files": [']
|
|
|
|
first = True
|
|
for mod in mods:
|
|
path = f"{TRUEMODS_DIR}/{mod}"
|
|
if os.path.exists(path):
|
|
h = get_hash(path)
|
|
if not first: lines.append(',')
|
|
first = False
|
|
lines.append(f' {{"path": "mods/{mod}", "hashes": {{"sha1": "{h}"}}, "env": {{"client": ["required"], "server": ["unsupported"]}}, "downloads": []}}')
|
|
|
|
for gp in gunpacks:
|
|
path = f"{TRUEGUNPACKS_DIR}/{gp}"
|
|
if os.path.exists(path):
|
|
h = get_hash(path)
|
|
if not first: lines.append(',')
|
|
first = False
|
|
lines.append(f' {{"path": "tacz/{gp}", "hashes": {{"sha1": "{h}"}}, "env": {{"client": ["required"], "server": ["unsupported"]}}, "downloads": []}}')
|
|
|
|
lines.extend([' ]', '}'])
|
|
os.makedirs(MODPACK_DIR, exist_ok=True)
|
|
with open(f"{MODPACK_DIR}/modrinth.index.json", 'w') as f:
|
|
f.write('\n'.join(lines))
|
|
|
|
def main():
|
|
log("Starting minimal modpack synchronization")
|
|
os.makedirs(STATE_DIR, exist_ok=True)
|
|
|
|
included, excluded, gunpacks = sync_minimal_pack()
|
|
|
|
current = open(VERSION_FILE).read().strip() if os.path.exists(VERSION_FILE) else "0.0.0"
|
|
parts = current.split('.')
|
|
new_version = f"{parts[0]}.{parts[1]}.{int(parts[2]) + 1}"
|
|
open(VERSION_FILE, 'w').write(new_version)
|
|
|
|
create_index(new_version, included, gunpacks)
|
|
|
|
with open(f"{STATE_DIR}/mods.json", 'w') as f:
|
|
f.write('\n'.join(included))
|
|
with open(f"{STATE_DIR}/gunpacks.json", 'w') as f:
|
|
f.write('\n'.join(gunpacks))
|
|
|
|
log(f"Version: {new_version}")
|
|
log(f"Mods included: {len(included)} (excluded {len(excluded)} client-only)")
|
|
log(f"Gunpacks: {len(gunpacks)}")
|
|
|
|
log("Updating git repository")
|
|
os.system("cd /tmp/mod_repo && git add -A >/dev/null 2>&1")
|
|
result = os.popen("cd /tmp/mod_repo && git commit -m 'Update minimal modpack to version " + new_version + "' 2>&1").read()
|
|
if "nothing to commit" not in result:
|
|
log("Pushing to remote")
|
|
os.system("cd /tmp/mod_repo && git push origin main >/dev/null 2>&1 &")
|
|
log(f"Successfully pushed version {new_version}")
|
|
else:
|
|
log("No changes to commit")
|
|
|
|
log("Synchronization completed")
|
|
|
|
if __name__ == "__main__":
|
|
main()
|