-
Notifications
You must be signed in to change notification settings - Fork 0
/
mrpack.py
144 lines (106 loc) · 4.41 KB
/
mrpack.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
import json
from os import path
import os
import zipfile
import tempfile
import hashlib
import shutil
import urllib.request
import minecraft_launcher_lib
LAUNCHER_NAME = "PyLauncher"
MODERINTH_REQUEST_HEADER={
"User-Agent": f"nobody1902/{LAUNCHER_NAME}/1.0",
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "en-US,en;q=0.9",
"Accept": "application/java-archive,text/html,application/xhtml+xml,application/xml",
}
def json_read(path:str):
if not os.path.exists(path):
print("Couldn't find json file.")
return
o = None
with open(path, "r") as f:
o = json.loads(f.read())
return o
def unzip(archive:str, output:str):
if not path.exists(archive):
print("Couldn't find the archive.")
return
with zipfile.ZipFile(archive, "r") as zip_ref:
zip_ref.extractall(output)
def download_file(url:str, install_location:str, overwrite=False):
os.makedirs(path.dirname(install_location), exist_ok=True)
if not overwrite and path.exists(install_location):
return
request = urllib.request.Request(url, None, MODERINTH_REQUEST_HEADER)
with urllib.request.urlopen(request) as response, open(install_location, "wb") as out_file:
shutil.copyfileobj(response, out_file)
def update_status(callback:minecraft_launcher_lib.types.CallbackDict|None, status:str):
if not callback:
return
callback["setStatus"](status)
def update_progress(callback:minecraft_launcher_lib.types.CallbackDict|None, progress:int):
if not callback:
return
callback["setProgress"](progress)
def update_max(callback:minecraft_launcher_lib.types.CallbackDict|None, max:int):
if not callback:
return
callback["setMax"](max)
def install_mrpack(mrpack:str, install_location:str, callback:minecraft_launcher_lib.types.CallbackDict|None=None)->tuple[str, tuple[str, str]]:
if not path.exists(mrpack):
return
TEMP_PATH = path.join(tempfile.gettempdir(), f"{LAUNCHER_NAME}")
pack_folder = path.join(TEMP_PATH, str(int(hashlib.sha1(path.basename(mrpack).encode("utf-8")).hexdigest(), 16) % (10 ** 8)))
# unzip mrpack
update_status(callback, "Unzipping mrpack")
unzip(mrpack, pack_folder)
# read the index.json
pack_info = json_read(path.join(pack_folder, "modrinth.index.json"))
# copy overrides
update_status(callback, "Copying overrides")
overrides_path = path.join(pack_folder, "overrides")
overrides = []
if path.exists(overrides_path):
for root, dirs, files in os.walk(overrides_path):
for file in files:
overrides.append(os.path.join(root,file))
update_max(callback, len(overrides))
update_status(callback, "Copying overrides")
for i, value in enumerate(overrides):
update_progress(callback, i)
update_status(callback, f"Copying {path.basename(value)}")
local_path = path.relpath(value, overrides_path)
destination_path = path.join(install_location, local_path)
os.makedirs(path.dirname(destination_path), exist_ok=True)
shutil.copy(value, destination_path)
# download pack files
file_count = len(pack_info["files"])
update_status(callback, "Downloading pack dependencies")
update_max(callback, file_count)
for i, file in enumerate(pack_info["files"]):
file_path = file["path"]
downloads = file["downloads"]
filesize = file["fileSize"]
update_progress(callback, i)
update_status(callback, f"Downloading {path.basename(file_path)}")
download_file(downloads[0], path.join(install_location, file_path))
shutil.rmtree(pack_folder)
# download version
dependencies:dict[str, str] = dict(pack_info["dependencies"])
minercaft_version = dependencies["minecraft"]
mod_loader = None
mod_loader_version = None
if dependencies.get("forge", None):
mod_loader = "forge"
mod_loader_version = dependencies["forge"]
elif dependencies.get("fabric-loader", None):
mod_loader = "fabric"
mod_loader_version = dependencies["fabric-loader"]
elif dependencies.get("quilt-loader", None):
mod_loader = "quilt"
mod_loader_version = dependencies["quilt-loader"]
elif dependencies.get("neoforge", None):
print("Neoforge is not supported.")
return None
return (minercaft_version, (mod_loader, mod_loader_version))