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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
|
# Extracting data from the Minecraft jars
import shutil
from .download import (
get_fabric_api_version,
get_latest_fabric_kotlin_version,
get_pumpkin_extractor,
get_server_jar,
get_burger,
get_client_jar,
get_fabric_data,
)
from .utils import get_dir_location
from zipfile import ZipFile
import subprocess
import json
import re
import os
def generate_data_from_server_jar(version_id: str):
if os.path.exists(get_dir_location(f"__cache__/generated-{version_id}")):
return
get_server_jar(version_id)
os.system(
f'cd {get_dir_location("__cache__")} && java -DbundlerMainClass=net.minecraft.data.Main -jar {get_dir_location(f"__cache__/server-{version_id}.jar")} --all --output "{get_dir_location(f"__cache__/generated-{version_id}")}"'
)
def get_block_states_report(version_id: str):
return get_report(version_id, "blocks")
def get_builtin_registries_report(version_id: str):
return get_report(version_id, "registries")
def get_packets_report(version_id: str):
return get_report(version_id, "packets")
def get_items_report(version_id: str):
generate_data_from_server_jar(version_id)
items_dir = get_dir_location(
f"__cache__/generated-{version_id}/reports/minecraft/components/item"
)
if not os.path.exists(items_dir):
return {}
items = {}
for root, dirs, files in os.walk(items_dir, topdown=False):
for name in files:
file = os.path.join(root, name)
relative_path = file.replace(items_dir, "")[1:]
if not file.endswith(".json"):
continue
with open(file, "r") as f:
items[relative_path[:-5]] = json.load(f)
return items
def get_report(version_id: str, name: str):
generate_data_from_server_jar(version_id)
with open(
get_dir_location(f"__cache__/generated-{version_id}/reports/{name}.json"), "r"
) as f:
return json.load(f)
def get_registry_tags(version_id: str, name: str):
generate_data_from_server_jar(version_id)
tags_directory = get_dir_location(
f"__cache__/generated-{version_id}/data/minecraft/tags/{name}"
)
if not os.path.exists(tags_directory):
return {}
tags = {}
for root, dirs, files in os.walk(tags_directory, topdown=False):
for name in files:
file = os.path.join(root, name)
relative_path = file.replace(tags_directory, "")[1:]
if not file.endswith(".json"):
continue
with open(file, "r") as f:
tags[relative_path[:-5]] = json.load(f)
return tags
# note that these are different from "builtin" registries
def get_data_registries(version_id: str):
generate_data_from_server_jar(version_id)
data_registries_dir = get_dir_location(
f"__cache__/generated-{version_id}/data/minecraft"
)
registries = {}
def add_entries_in_dir(parent_dir, registry_name):
entries = []
for variant_dir in os.listdir(os.path.join(parent_dir, registry_name)):
if not variant_dir.endswith(".json"):
continue
entries.append(variant_dir[:-5])
if len(entries) > 0:
registries[registry_name] = entries
for registry_name in os.listdir(data_registries_dir):
add_entries_in_dir(data_registries_dir, registry_name)
for registry_name in os.listdir(os.path.join(data_registries_dir, "worldgen")):
if registry_name != "biome":
continue
add_entries_in_dir(data_registries_dir, os.path.join("worldgen", registry_name))
return registries
python_command = None
def determine_python_command():
return "venv/bin/python"
def run_python_command_and_download_deps(command):
print(">", command)
for _ in range(10):
p = subprocess.Popen(command, stderr=subprocess.PIPE, shell=True)
stderr = b""
while True:
data = p.stderr.read()
if data == b"":
break
print(data.decode(), end="", flush=True)
stderr += data
regex_match = re.search(
r"ModuleNotFoundError: No module named \'(\w+?)\'", stderr.decode()
)
if not regex_match:
out, err = p.communicate()
if out:
print(out)
if err:
print(err)
break
missing_lib = regex_match.group(1)
print("Missing required lib:", missing_lib)
subprocess.run(
f"venv/bin/pip install {missing_lib}",
cwd=os.path.dirname(os.path.dirname(__file__)),
)
print("ok")
def get_burger_data_for_version(version_id: str):
if not os.path.exists(get_dir_location(f"__cache__/burger-{version_id}.json")):
get_burger()
get_client_jar(version_id)
print("\033[92mRunning azalea-burger...\033[m")
run_python_command_and_download_deps(
f"cd {get_dir_location('__cache__/azalea-burger')} && "
f"venv/bin/python munch.py {get_dir_location('__cache__')}/client-{version_id}.jar "
f"--output {get_dir_location('__cache__')}/burger-{version_id}.json "
)
with open(get_dir_location(f"__cache__/burger-{version_id}.json"), "r") as f:
return json.load(f)
def get_pumpkin_data(version_id: str, category: str):
assert "/" not in version_id
assert "\\" not in version_id
target_parent_dir = get_dir_location(f"__cache__/pumpkin-{version_id}")
category_dir = f"{target_parent_dir}/{category}.json"
if os.path.exists(category_dir):
with open(category_dir, "r") as f:
return json.load(f)
pumpkin_dir = get_pumpkin_extractor()
pumpkin_run_directory = f"{pumpkin_dir}/run"
if os.path.exists(pumpkin_run_directory):
shutil.rmtree(pumpkin_run_directory)
os.makedirs(pumpkin_run_directory, exist_ok=True)
with open(f"{pumpkin_run_directory}/eula.txt", "w") as f:
f.write("eula=true")
with open(f"{pumpkin_run_directory}/server.properties", "w") as f:
f.write("server-port=0")
fabric_data = get_fabric_data(version_id)[0]
fabric_api_version = get_fabric_api_version(version_id)
fabric_kotlin_version = get_latest_fabric_kotlin_version()
gradle_properties = f"""# Done to increase the memory available to gradle.
org.gradle.jvmargs=-Xmx2G
org.gradle.parallel=true
# Fabric Properties
# check these on https://fabricmc.net/develop/
minecraft_version={version_id}
loader_version={fabric_data["loader"]["version"]}
kotlin_loader_version={fabric_kotlin_version}
# Mod Properties
mod_version=1.0-SNAPSHOT
maven_group=de.snowii
archives_base_name=extractor
fabric_version={fabric_api_version}
"""
with open(f"{pumpkin_dir}/gradle.properties", "w") as f:
f.write(gradle_properties)
# run ./gradlew runServer until it logs "(pumpkin_extractor) Done"
p = subprocess.Popen(
f"cd {pumpkin_dir} && ./gradlew clean && ./gradlew runServer",
stderr=subprocess.PIPE,
stdout=subprocess.PIPE,
shell=True,
)
while True:
data = p.stdout.readline().decode()
print(">" + data, end="", flush=True)
if "[Server thread/INFO] (pumpkin_extractor) Done" in data:
print("Pumpkin extractor done")
break
if data == "":
break
p.terminate()
# move the run/pumpkin_extractor_output directory to target_parent_dir
# delete target_parent_dir if it's empty
if os.path.exists(target_parent_dir):
os.rmdir(target_parent_dir)
os.rename(f"{pumpkin_dir}/run/pumpkin_extractor_output", target_parent_dir)
with open(category_dir, "r") as f:
return json.load(f)
def get_file_from_jar(version_id: str, file_dir: str):
get_client_jar(version_id)
with ZipFile(get_dir_location(f"__cache__/client-{version_id}.jar")) as z:
with z.open(file_dir) as f:
return f.read()
def get_en_us_lang(version_id: str):
return json.loads(get_file_from_jar(version_id, "assets/minecraft/lang/en_us.json"))
|