aboutsummaryrefslogtreecommitdiff
path: root/data-code-generator/packetcodegen.py
blob: 674f97c2932cc317d19899903b707c9c5fdb0224 (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
from utils import to_snake_case, to_camel_case
from mappings import Mappings


def burger_type_to_rust_type(burger_type):
    is_var = False
    uses = set()

    if burger_type == 'byte':
        field_type_rs = 'i8'
    elif burger_type == 'short':
        field_type_rs = 'i16'
    elif burger_type == 'int':
        field_type_rs = 'i32'
    elif burger_type == 'long':
        field_type_rs = 'i64'
    elif burger_type == 'float':
        field_type_rs = 'f32'
    elif burger_type == 'double':
        field_type_rs = 'f64'

    elif burger_type == 'varint':
        is_var = True
        field_type_rs = 'i32'
    elif burger_type == 'varlong':
        is_var = True
        field_type_rs = 'i64'

    elif burger_type == 'boolean':
        field_type_rs = 'bool'
    elif burger_type == 'string':
        field_type_rs = 'String'

    elif burger_type == 'chatcomponent':
        field_type_rs = 'Component'
    elif burger_type == 'identifier':
        field_type_rs = 'ResourceLocation'
    elif burger_type == 'uuid':
        field_type_rs = 'Uuid'
    elif burger_type == 'position':
        field_type_rs = 'BlockPos'
    elif burger_type == 'nbtcompound':
        field_type_rs = 'azalea_nbt::Tag'
    elif burger_type == 'itemstack':
        field_type_rs = 'Slot'
    elif burger_type == 'metadata':
        field_type_rs = 'EntityMetadata'
    elif burger_type == 'enum':
        # enums are too complicated, leave those to the user
        field_type_rs = 'todo!()'
    elif burger_type.endswith('[]'):
        field_type_rs, is_var, uses = burger_type_to_rust_type(
            burger_type[:-2])
        field_type_rs = f'Vec<{field_type_rs}>'
    else:
        print('Unknown field type:', burger_type)
        exit()
    return field_type_rs, is_var, uses


def generate(burger_packets, mappings: Mappings):
    for packet in burger_packets.values():
        direction = packet['direction'].lower()  # serverbound or clientbound
        state = packet['state'].lower()

        generated_packet_code = []
        generated_packet_code.append(
            f'#[derive(Clone, Debug, {to_camel_case(state)}Packet)]')

        obfuscated_class_name = packet['class'].split('.')[0]
        class_name = mappings.get_class(obfuscated_class_name).split('.')[-1]

        generated_packet_code.append(
            f'pub struct {to_camel_case(class_name)} {{')

        for instruction in packet.get('instructions', []):
            if instruction['operation'] == 'write':
                obfuscated_field_name = instruction['field']
                if '.' in obfuscated_field_name or ' ' in obfuscated_field_name or '(' in obfuscated_field_name:
                    continue
                field_name = mappings.get_field(
                    obfuscated_class_name, obfuscated_field_name)
                if not field_name:
                    generated_packet_code.append(f'// TODO: {instruction}')
                    continue

                field_type = instruction['type']
                field_type_rs, is_var, uses = burger_type_to_rust_type(
                    field_type)
                if is_var:
                    generated_packet_code.append('#[var]')
                generated_packet_code.append(
                    f'pub {to_snake_case(field_name)}: {field_type_rs},')
            else:
                generated_packet_code.append(f'// TODO: {instruction}')
                continue

        generated_packet_code.append('}')
        print(generated_packet_code)
        print()