aboutsummaryrefslogtreecommitdiff
path: root/codegen/lib/extract.py
blob: 5d49ac62c828e33b0beeeb5ec05ca6185dcecc05 (plain)
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
# Extracting data from the Minecraft jars

from lib.download import get_server_jar, get_burger, get_client_jar, get_generator_mod, get_yarn_data, get_fabric_api_versions, get_fabric_loader_versions
from lib.utils import get_dir_location
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'downloads/generated-{version_id}')):
        return

    get_server_jar(version_id)
    os.system(
        f'cd {get_dir_location(f"downloads")} && java -DbundlerMainClass=net.minecraft.data.Main -jar {get_dir_location(f"downloads/server-{version_id}.jar")} --all --output \"{get_dir_location(f"downloads/generated-{version_id}")}\"'
    )


def get_block_states_report(version_id: str):
    generate_data_from_server_jar(version_id)
    with open(get_dir_location(f'downloads/generated-{version_id}/reports/blocks.json'), 'r') as f:
        return json.load(f)


def get_registries_report(version_id: str):
    generate_data_from_server_jar(version_id)
    with open(get_dir_location(f'downloads/generated-{version_id}/reports/registries.json'), 'r') as f:
        return json.load(f)


def get_block_states_burger(version_id: str):
    burger_data = get_burger_data_for_version(version_id)
    return burger_data[0]['blocks']['block']


def get_ordered_blocks_burger(version_id: str):
    burger_data = get_burger_data_for_version(version_id)
    return burger_data[0]['blocks']['ordered_blocks']


python_command = None


def determine_python_command():
    global python_command
    if python_command:
        return python_command

    def try_python_command(version):
        return os.system(f'{version} --version') == 0

    for version in ('python3.9', 'python3.8', 'python3', 'python'):
        if try_python_command(version):
            python_command = version
            return version
    raise Exception(
        'Couldn\'t determine python command to use to run burger with!')


def get_burger_data_for_version(version_id: str):
    if not os.path.exists(get_dir_location(f'downloads/burger-{version_id}.json')):
        get_burger()
        get_client_jar(version_id)

        for _ in range(10):
            r = subprocess.run(
                f'cd {get_dir_location("downloads/Burger")} && {determine_python_command()} munch.py ../client-{version_id}.jar --output ../burger-{version_id}.json',
                capture_output=True,
                shell=True
            )
            regex_match = re.search(
                r'ModuleNotFoundError: No module named \'(\w+?)\'', r.stderr.decode())
            if not regex_match:
                break
            missing_lib = regex_match.group(1)
            print('Missing required lib for Burger:', missing_lib)
            os.system(
                f'{determine_python_command()} -m pip install {missing_lib}')
    with open(get_dir_location(f'downloads/burger-{version_id}.json'), 'r') as f:
        return json.load(f)


def get_generator_mod_data(version_id: str, category: str):
    '''
    Gets data from u9g's data generator mod. Note that this is not very stable, and it requires Yarn to release updates first.
    '''

    target_dir = get_dir_location(f'downloads/generator-mod-{version_id}')

    if not os.path.exists(get_dir_location(target_dir)):
        generator_mod_dir = get_generator_mod()

        yarn_data = get_yarn_data(version_id)
        if not yarn_data:
            raise Exception(
                'Fabric/Yarn hasn\'t been updated to this version yet.')
        # looks like 1.19+build.1
        yarn_version = yarn_data['version']

        fabric_api_version = get_fabric_api_versions()[-1]
        fabric_loader_version = get_fabric_loader_versions()[0]

        # the mod has the minecraft version hard-coded by default, so we just change the gradle.properties and fabric.mod.json
        with open(get_dir_location(f'{generator_mod_dir}/gradle.properties'), 'r') as f:
            lines = f.readlines()
        with open(get_dir_location(f'{generator_mod_dir}/gradle.properties'), 'w') as f:
            for line in lines:
                if line.startswith('minecraft_version='):
                    line = f'minecraft_version={version_id}\n'
                if line.startswith('yarn_mappings='):
                    line = f'yarn_mappings={yarn_version}\n'
                if line.startswith('fabric_version='):
                    line = f'fabric_version={fabric_api_version}\n'
                if line.startswith('loader_version='):
                    line = f'loader_version={fabric_loader_version}\n'
                f.write(line)
        # edit the fabric.mod.json to support this version
        with open(get_dir_location(f'{generator_mod_dir}/src/main/resources/fabric.mod.json'), 'r') as f:
            fabric_mod_json = json.load(f)
        fabric_mod_json['depends']['minecraft'] = '*'
        with open(get_dir_location(f'{generator_mod_dir}/src/main/resources/fabric.mod.json'), 'w') as f:
            json.dump(fabric_mod_json, f, indent=2)

        try: os.system(f'cd {generator_mod_dir} && chmod u+x ./gradlew')
        except: pass

        # set the server port to something other than 25565 so it doesn't
        # conflict with anything else that's running
        try: os.makedirs(get_dir_location(f'{generator_mod_dir}/run'))
        except: pass
        with open(get_dir_location(f'{generator_mod_dir}/run/server.properties'), 'w') as f:
            f.write('server-port=56553')

        # make sure we have perms to run this file
        # (on windows it fails but keeps running)
        os.system(f'cd {generator_mod_dir} && chmod u+x ./gradlew')
        try:
            subprocess.run(
                [f'cd {generator_mod_dir} && ./gradlew runServer'],
                check=True,
                shell=True
            )
        except Exception as e:
            os.system(f'cd {generator_mod_dir} && gradlew runServer')

        if os.path.exists(target_dir):
            os.unlink(target_dir)
        os.rename(
            get_dir_location(
                f'{generator_mod_dir}/run/minecraft-data/{version_id}'),
            target_dir
        )

    with open(f'{target_dir}/{category}.json', 'r') as f:
        return json.load(f)