diff options
| author | mat <27899617+mat-1@users.noreply.github.com> | 2026-03-24 11:15:56 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-03-24 11:15:56 -0500 |
| commit | eeaf1435e81d9cbd8daa0efa22029c1f259a64b5 (patch) | |
| tree | 3486e26d5409708370e4e259d240fb77c6e1e439 /codegen/lib/code | |
| parent | 41a9ae6aaff77646c08c64ac1334a8cc6081c24f (diff) | |
| download | azalea-drasl-eeaf1435e81d9cbd8daa0efa22029c1f259a64b5.tar.xz | |
26.1 (#316)
* start updating to 26.1
* start updating to 26.1-snapshot-6
* 26.1-snapshot-6
* 26.1-snapshot-10
* 26.1-rc-1
* fix tests
* 26.1-rc-2 and sort default components
* 26.1
* update changelog
Diffstat (limited to 'codegen/lib/code')
| -rw-r--r-- | codegen/lib/code/data_components.py | 27 | ||||
| -rw-r--r-- | codegen/lib/code/entity.py | 49 | ||||
| -rw-r--r-- | codegen/lib/code/packet.py | 106 | ||||
| -rw-r--r-- | codegen/lib/code/registry.py | 2 | ||||
| -rw-r--r-- | codegen/lib/code/tags.py | 39 | ||||
| -rw-r--r-- | codegen/lib/code/utils.py | 72 |
6 files changed, 110 insertions, 185 deletions
diff --git a/codegen/lib/code/data_components.py b/codegen/lib/code/data_components.py index e6de6201..992ba83f 100644 --- a/codegen/lib/code/data_components.py +++ b/codegen/lib/code/data_components.py @@ -360,7 +360,7 @@ use crate::{ ) elif target_rust_type == "ItemStack": item_rust_value = python_to_rust_value(python_value["id"], "ItemKind") - count = python_value["count"] + count = python_value.get("count", 1) if count == 1: return f"ItemStack::from({item_rust_value})" else: @@ -411,9 +411,6 @@ use crate::{ fields_for_rust_type = enum_and_struct_fields.get(target_rust_type, []) if "Referenced(Identifier)" in fields_for_rust_type: return f"{target_rust_type}::Referenced({python_to_rust_value(python_value, 'Identifier')})" - elif "Registry(data::Instrument)" in fields_for_rust_type: - # TODO - return f"{target_rust_type}::Registry(azalea_registry::data::Instrument::new_raw(0))" elif target_rust_type.startswith("HolderSet<"): holderset_type = target_rust_type.split("<", 1)[1].split(",", 1)[0] main_vec = python_to_rust_value( @@ -429,10 +426,10 @@ use crate::{ elif target_rust_type == "Identifier": # convert minecraft:air into Identifier::from_static("minecraft:air") return f'"{python_value}".into()' - elif target_rust_type == "DamageType": + elif target_rust_type.startswith("azalea_registry::data::"): # TODO: this is intentionally incorrect, see the comment in # azalea-registry/src/data.rs to see how to fix this properly - return "DamageType::Registry(azalea_registry::data::DamageKind::new_raw(0))" + return f"{target_rust_type}::new_raw(0)" else: # enum variant return f"{target_rust_type}::{to_camel_case(identifier_to_path(python_value))}" @@ -472,9 +469,17 @@ use crate::{ tag_module = "blocks" else: tag_module = "FIXME_UNKNOWN_MODULE" - vectors.append( - f"azalea_registry::tags::{tag_module}::{tag_name}.clone().into_iter().collect()" - ) + + # TODO: it's not currently possible to have a holderset for data registry items + # (because registries would need to be translated during packet parsing/writing), + # so we leave this empty for now. + if inner_type in {"BannerPatternKind", "DamageKind"}: + pass + else: + vectors.append( + f"azalea_registry::tags::{tag_module}::{tag_name}.clone().into_iter().collect()" + ) + continue main_vec += python_to_rust_value(v, inner_type) + "," main_vec = main_vec.rstrip(",") + "]" @@ -533,11 +538,11 @@ use crate::{ item_defaults_original = item_defaults item_defaults = {} - for k, v in item_defaults_original.items(): + for k, v in sorted(item_defaults_original.items(), key=lambda i: i[0]): item_defaults[k] = python_to_rust_value(v, field_type) default_values_frequency = {} - for value in item_defaults.values(): + for value in sorted(item_defaults.values()): if value not in default_values_frequency: default_values_frequency[value] = 0 default_values_frequency[value] += 1 diff --git a/codegen/lib/code/entity.py b/codegen/lib/code/entity.py index d10a159f..992d9b19 100644 --- a/codegen/lib/code/entity.py +++ b/codegen/lib/code/entity.py @@ -1,5 +1,4 @@ from lib.utils import to_camel_case, to_snake_case, get_dir_location, upper_first_letter -from lib.mappings import Mappings from typing import Optional import re @@ -8,18 +7,19 @@ DATA_RS_DIR = get_dir_location("../azalea-entity/src/data.rs") DIMENSIONS_RS_DIR = get_dir_location("../azalea-entity/src/dimensions.rs") -def generate_metadata_names(burger_dataserializers: dict, mappings: Mappings): +def generate_metadata_names(burger_dataserializers: dict): serializer_names: list[Optional[str]] = [None] * len(burger_dataserializers) for burger_serializer in burger_dataserializers.values(): print(burger_serializer) + # TODO: remove these comments # burger gives us the wrong class, so we do this instead - data_serializers_class = mappings.get_class_from_deobfuscated_name( - "net.minecraft.network.syncher.EntityDataSerializers" - ) - mojmap_name = mappings.get_field( - data_serializers_class, burger_serializer["field"] - ).lower() + # data_serializers_class = "net/minecraft/network/syncher/EntityDataSerializers" + # mojmap_name = mappings.get_field( + # data_serializers_class, burger_serializer["field"] + # ).lower() + + mojmap_name = burger_serializer["field"].lower() if mojmap_name == "component": mojmap_name = "formatted_text" @@ -58,11 +58,11 @@ def parse_metadata_types_from_code(): return data -def generate_entity_metadata(burger_entities_data: dict, mappings: Mappings): +def generate_entity_metadata(burger_entities_data: dict): burger_entity_metadata = burger_entities_data["entity"] new_metadata_names = generate_metadata_names( - burger_entities_data["dataserializers"], mappings + burger_entities_data["dataserializers"] ) parsed_metadata_types = parse_metadata_types_from_code() @@ -173,7 +173,7 @@ impl From<EntityDataValue> for UpdateMetadataError { for entity_id in burger_entity_metadata.keys(): field_name_map[entity_id] = {} for field_name_or_bitfield in get_entity_metadata_names( - entity_id, burger_entity_metadata, mappings + entity_id, burger_entity_metadata ).values(): if isinstance(field_name_or_bitfield, str): if field_name_or_bitfield in previous_field_names: @@ -204,7 +204,7 @@ impl From<EntityDataValue> for UpdateMetadataError { # and now figure out what to rename them to for entity_id in burger_entity_metadata.keys(): for index, field_name_or_bitfield in get_entity_metadata_names( - entity_id, burger_entity_metadata, mappings + entity_id, burger_entity_metadata ).items(): if isinstance(field_name_or_bitfield, str): new_field_name = field_name_or_bitfield @@ -245,7 +245,7 @@ impl From<EntityDataValue> for UpdateMetadataError { parents = get_entity_parents(entity_id, burger_entity_metadata) for parent_id in list(reversed(parents)): for index, name_or_bitfield in get_entity_metadata_names( - parent_id, burger_entity_metadata, mappings + parent_id, burger_entity_metadata ).items(): assert index == len(all_field_names_or_bitfields) all_field_names_or_bitfields.append(name_or_bitfield) @@ -462,7 +462,7 @@ impl From<EntityDataValue> for UpdateMetadataError { if parent_struct_name: code.append(f" parent: {parent_struct_name}MetadataBundle,") for index, name_or_bitfield in get_entity_metadata_names( - entity_id, burger_entity_metadata, mappings + entity_id, burger_entity_metadata ).items(): if isinstance(name_or_bitfield, str): name_or_bitfield = maybe_rename_field(name_or_bitfield, index) @@ -514,7 +514,7 @@ impl From<EntityDataValue> for UpdateMetadataError { code.append(" parent: Default::default(),") for index, name_or_bitfield in get_entity_metadata_names( - this_entity_id, burger_entity_metadata, mappings + this_entity_id, burger_entity_metadata ).items(): default = next( filter(lambda i: i["index"] == index, entity_metadatas) @@ -792,22 +792,19 @@ def get_entity_metadata(entity_id: str, burger_entity_metadata: dict): # returns a dict of {index: (name or bitfield)} -def get_entity_metadata_names( - entity_id: str, burger_entity_metadata: dict, mappings: Mappings -): +def get_entity_metadata_names(entity_id: str, burger_entity_metadata: dict): entity_metadata = burger_entity_metadata[entity_id]["metadata"] mapped_metadata_names = {} for metadata_item in entity_metadata: if "data" in metadata_item: - obfuscated_class = metadata_item["class"] + # obfuscated_class = metadata_item["class"] # mojang_class = mappings.get_class(obfuscated_class) first_byte_index = None for metadata_attribute in metadata_item["data"]: - obfuscated_field = metadata_attribute["field"] - mojang_field = mappings.get_field(obfuscated_class, obfuscated_field) + mojang_field = metadata_attribute["field"] pretty_mojang_name = prettify_mojang_field(mojang_field) mapped_metadata_names[metadata_attribute["index"]] = pretty_mojang_name @@ -820,12 +817,10 @@ def get_entity_metadata_names( if metadata_item["bitfields"] and first_byte_index is not None: clean_bitfield = {} for bitfield_item in metadata_item["bitfields"]: - bitfield_item_obfuscated_class = bitfield_item.get( - "class", obfuscated_class - ) - mojang_bitfield_item_name = mappings.get_method( - bitfield_item_obfuscated_class, bitfield_item["method"], "" - ) + # bitfield_item_obfuscated_class = bitfield_item.get( + # "class", obfuscated_class + # ) + mojang_bitfield_item_name = bitfield_item["method"] bitfield_item_name = prettify_mojang_method( mojang_bitfield_item_name ) diff --git a/codegen/lib/code/packet.py b/codegen/lib/code/packet.py index 9ce5c137..1131cb49 100644 --- a/codegen/lib/code/packet.py +++ b/codegen/lib/code/packet.py @@ -1,6 +1,5 @@ from lib.utils import identifier_to_path, to_snake_case, to_camel_case, get_dir_location from lib.code.utils import burger_type_to_rust_type, write_packet_file -from lib.mappings import Mappings from typing import Optional import os import re @@ -175,7 +174,6 @@ def burger_instruction_to_code( instructions: list[dict], index: int, generated_packet_code: list[str], - mappings: Mappings, obfuscated_class_name: str, uses: set, extra_code: list[str], @@ -208,8 +206,7 @@ def burger_instruction_to_code( and next_next_instruction and next_next_instruction["operation"] == "loop" ): - obfuscated_field_name = instruction["field"].split(".")[0] - field_name = mappings.get_field(obfuscated_class_name, obfuscated_field_name) + field_name = instruction["field"].split("/")[0] # figure out what kind of iterator it is loop_instructions = next_next_instruction["instructions"] @@ -218,7 +215,6 @@ def burger_instruction_to_code( loop_instructions[1]["type"], None, loop_instructions[1], - mappings, obfuscated_class_name, ) field_type_rs = f"Vec<{entry_type_rs}>" @@ -235,7 +231,6 @@ def burger_instruction_to_code( loop_instructions[1]["type"], None, loop_instructions[1], - mappings, obfuscated_class_name, ) ) @@ -248,7 +243,6 @@ def burger_instruction_to_code( loop_instructions[2]["type"], None, loop_instructions[2], - mappings, obfuscated_class_name, ) ) @@ -277,16 +271,14 @@ def burger_instruction_to_code( ) ): print("ok is option") - obfuscated_field_name = instruction["field"].split(".")[0].split(" ")[0] + field_name = instruction["field"].split(".")[0].split(" ")[0] - if obfuscated_field_name in known_variable_types: - # just use the known name since it's not gonna be in the mappings - obfuscated_field_name = known_variable_types[obfuscated_field_name] - - field_name = mappings.get_field(obfuscated_class_name, obfuscated_field_name) + # if obfuscated_field_name in known_variable_types: + # just use the known name since it's not gonna be in the mappings + # obfuscated_field_name = known_variable_types[obfuscated_field_name] if field_name is None: - field_name = obfuscated_field_name.split("/")[-1] + field_name = field_name.split("/")[-1] if "<" in field_name: field_name = "value" @@ -306,7 +298,6 @@ def burger_instruction_to_code( condition_instruction["type"], None, condition_instruction, - mappings, obfuscated_class_name, ) ) @@ -321,54 +312,35 @@ def burger_instruction_to_code( skip = 1 else: field_type = instruction["type"] - obfuscated_field_name = instruction["field"] + field_name = instruction["field"] - if obfuscated_field_name.startswith("(float)"): - obfuscated_field_name = obfuscated_field_name[len("(float)") :] - - field_name = mappings.get_field( - obfuscated_class_name, obfuscated_field_name - ) or mappings.get_field( - obfuscated_class_name.split("$")[0], obfuscated_field_name - ) + if field_name.startswith("(float)"): + field_name = field_name[len("(float)") :] field_type_rs, is_var, instruction_uses, instruction_extra_code = ( burger_type_to_rust_type( - field_type, field_name, instruction, mappings, obfuscated_class_name + field_type, field_name, instruction, obfuscated_class_name ) ) - if obfuscated_field_name in known_variable_types: + if field_name in known_variable_types: # just use the known name since it's not gonna be in the mappings - field_name = obfuscated_field_name + pass - elif ( - "." in obfuscated_field_name - or " " in obfuscated_field_name - or "(" in obfuscated_field_name - ): - field_type_rs2, obfuscated_field_name, field_comment = burger_field_to_type( - obfuscated_field_name, - mappings, + elif "." in field_name or " " in field_name or "(" in field_name: + field_type_rs2, field_name, field_comment = burger_field_to_type( + field_name, obfuscated_class_name, known_variable_types, ) if not field_type_rs2: generated_packet_code.append(f"// TODO: {instruction}") return - if obfuscated_field_name in known_variable_types: + if field_name in known_variable_types: # just use the known name since it's not gonna be in the mappings - obfuscated_field_name = known_variable_types[obfuscated_field_name] - print("got obfuscated_field_name", obfuscated_field_name) - - # try to get the field name again with the new stuff we know - field_name = mappings.get_field( - obfuscated_class_name, obfuscated_field_name - ) or mappings.get_field( - obfuscated_class_name.split("$")[0], obfuscated_field_name - ) - if field_name is None: - field_name = obfuscated_field_name.split("/")[-1] + field_name = known_variable_types[field_name] + print("got obfuscated_field_name", field_name) + uses.update(instruction_uses) extra_code.extend(instruction_extra_code) @@ -387,7 +359,7 @@ def burger_instruction_to_code( def burger_field_to_type( - field, mappings: Mappings, obfuscated_class_name: str, known_variable_types={} + field, obfuscated_class_name: str, known_variable_types={} ) -> tuple[Optional[str], str, Optional[str]]: """ Returns field_type_rs, obfuscated_field_name, field_comment @@ -399,38 +371,18 @@ def burger_field_to_type( match = re.match(r"^\w+\.\w+\(\)$", field) if match: print("field", field) - obfuscated_first = field.split(".")[0] - obfuscated_second = field.split(".")[1].split("(")[0] + first_type = field.split(".")[0] + second_type = field.split(".")[1].split("(")[0] # first = mappings.get_field(obfuscated_class_name, obfuscated_first) - if obfuscated_first in known_variable_types: - first_type = known_variable_types[obfuscated_first] - else: - try: - first_type = mappings.get_field_type( - obfuscated_class_name, obfuscated_first - ) - except Exception: - first_type = "TODO" - first_obfuscated_class_name: Optional[str] = ( - mappings.get_class_from_deobfuscated_name(first_type) - ) - if first_obfuscated_class_name: - try: - second = mappings.get_method( - first_obfuscated_class_name, obfuscated_second, "" - ) - except Exception: - # if this happens then the field is probably from a super class - second = obfuscated_second - else: - second = obfuscated_second - first_type_short = first_type.split(".")[-1] - if second in {"byteValue"}: - return (first_type_short, obfuscated_first, None) + if first_type in known_variable_types: + first_type = known_variable_types[first_type] + first_type_short = first_type.split("/")[-1] + if second_type in {"byteValue"}: + return (first_type_short, first_type, None) return ( first_type_short, - obfuscated_first, - f"TODO: Does {first_type_short}::{second}, may not be implemented", + first_type, + f"TODO: Does {first_type_short}::{second_type}, may not be implemented", ) return None, field, None diff --git a/codegen/lib/code/registry.py b/codegen/lib/code/registry.py index 01462e1f..9c30a273 100644 --- a/codegen/lib/code/registry.py +++ b/codegen/lib/code/registry.py @@ -154,7 +154,7 @@ def registry_name_to_enum_name(registry_name: str) -> str: # change _type to _kind because that's Rustier (and because _type # is a reserved keyword) registry_name = registry_name[:-5] + "_kind" - elif registry_name in {"menu", "block", "item"}: + elif registry_name in {"menu", "block", "item", "banner_pattern"}: registry_name += "_kind" return to_camel_case(registry_name) diff --git a/codegen/lib/code/tags.py b/codegen/lib/code/tags.py index b6e225ac..2a44d35c 100644 --- a/codegen/lib/code/tags.py +++ b/codegen/lib/code/tags.py @@ -1,25 +1,45 @@ from lib.code.registry import registry_name_to_enum_name -from lib.utils import identifier_to_namespace, identifier_to_path, to_snake_case, upper_first_letter, get_dir_location, to_camel_case +from lib.utils import ( + identifier_to_namespace, + identifier_to_path, + to_snake_case, + upper_first_letter, + get_dir_location, + to_camel_case, +) TAGS_DIR = get_dir_location("../azalea-registry/src/tags") -def generate_tags(registries: dict, tags: dict, file_name: str, registry_name: str): +def generate_tags( + registries: dict, + tags: dict, + file_name: str, + registry_name: str, + is_data_registry: bool = False, +): struct_name = registry_name_to_enum_name(registry_name) tags_dir = f"{TAGS_DIR}/{file_name}.rs" + registry_module = "data" if is_data_registry else "builtin" + if is_data_registry: + struct_name += "Key" + generated = f"""// This file was @generated by codegen/lib/code/tags.py, don't edit it manually! use std::sync::LazyLock; -use crate::{{builtin::{struct_name}, tags::RegistryTag}}; +use crate::{{{registry_module}::{struct_name}, tags::RegistryTag}}; """ - protocol_ids = {} - for k, v in registries["minecraft:" + registry_name]["entries"].items(): - protocol_ids[identifier_to_path(k)] = v["protocol_id"] + if is_data_registry: + protocol_ids = None + else: + protocol_ids = {} + for k, v in registries[f"minecraft:{registry_name}"]["entries"].items(): + protocol_ids[identifier_to_path(k)] = v["protocol_id"] for tag_name, tag in sorted(tags.items(), key=lambda x: x[0]): entries = [] @@ -41,9 +61,10 @@ use crate::{{builtin::{struct_name}, tags::RegistryTag}}; generated += f"pub static {static_set_name}: LazyLock<RegistryTag<{struct_name}>> = LazyLock::new(|| RegistryTag::new(vec![" - # this is important because we binary search registries in some cases - # and they need to be sorted by their rust Ord order - entries.sort(key=lambda e: protocol_ids[e]) + if not is_data_registry: + # this is important because we binary search registries in some cases + # and they need to be sorted by their rust Ord order + entries.sort(key=lambda e: protocol_ids[e]) for entry_name in entries: generated += ( diff --git a/codegen/lib/code/utils.py b/codegen/lib/code/utils.py index 62b4627b..9bfb3504 100644 --- a/codegen/lib/code/utils.py +++ b/codegen/lib/code/utils.py @@ -1,7 +1,6 @@ # utilities specifically for codegen from lib.utils import to_camel_case, to_snake_case, get_dir_location -from lib.mappings import Mappings from typing import Optional import os @@ -10,8 +9,7 @@ def burger_type_to_rust_type( burger_type, field_name: Optional[str] = None, instruction=None, - mappings: Optional[Mappings] = None, - obfuscated_class_name: Optional[str] = None, + class_name: Optional[str] = None, ): is_var = False uses = set() @@ -90,7 +88,7 @@ def burger_type_to_rust_type( # depends on context field_type_rs = "todo!()" elif burger_type == "enum": - if not instruction or not mappings or not obfuscated_class_name: + if not instruction or not class_name: field_type_rs = 'todo!("enum")' else: # generate the whole enum :) @@ -98,57 +96,20 @@ def burger_type_to_rust_type( enum_field = instruction["field"] # enums with a.b() as the field if "." in enum_field: - enum_first_part_name = mappings.get_field_type( - obfuscated_class_name, enum_field.split(".")[0] - ) - enum_first_part_obfuscated_name = ( - mappings.get_class_from_deobfuscated_name(enum_first_part_name) - ) - print( - "enum_first_part_obfuscated_name", enum_first_part_obfuscated_name - ) + enum_first_part_name = enum_field.split("/")[0] + print("enum_first_part_name", enum_first_part_name) print("enum field", enum_field.split(".")[1].split("(")[0]) - try: - enum_name = mappings.get_method_type( - enum_first_part_obfuscated_name, - enum_field.split(".")[1].split("(")[0], - "", - ) - except KeyError: - # sometimes enums are fields instead of methods - enum_name = mappings.get_field_type( - enum_first_part_obfuscated_name, - enum_field.split(".")[1].split("(")[0], - ) + enum_name = enum_field.split("$")[1].split("(")[0] print("hm", enum_name) else: - try: - enum_name = mappings.get_field_type( - obfuscated_class_name, enum_field - ) - except Exception: - enum_name = mappings.get_class(obfuscated_class_name) - print( - f"failed getting {obfuscated_class_name}.{enum_field} but continuing with {enum_name} anyways" - ) + enum_name = enum_field or class_name print("enum_name", enum_name) - enum_obfuscated_name = mappings.get_class_from_deobfuscated_name(enum_name) + enum_obfuscated_name = enum_name print("enum_obfuscated_name", enum_obfuscated_name) enum_variants = [] - for obfuscated_field_name in mappings.fields[enum_obfuscated_name]: - field_name = mappings.get_field( - enum_obfuscated_name, obfuscated_field_name - ) - - # get the type just to make sure it's actually a variant and not something else - field_type = mappings.get_field_type( - enum_obfuscated_name, obfuscated_field_name - ) - if field_type != enum_name: - continue - - enum_variants.append(field_name) + raise RuntimeError("TODO: extracting enum variants") + enum_variants.append(field_name) field_type_rs = to_camel_case(enum_name.split(".")[-1].split("$")[-1]) extra_code.append("") @@ -165,28 +126,19 @@ def burger_type_to_rust_type( field_type_rs = f"Vec<{field_type_rs}>" # sometimes burger gives us a slightly incorrect type - if mappings and instruction: + if instruction: if field_type_rs == "Vec<u8>": field = instruction["field"] if field.endswith(".copy()"): field = field[:-7] - try: - array_type = mappings.get_field_type(obfuscated_class_name, field) - except KeyError: - print("Error getting array type", field) - return field_type_rs, is_var, uses, extra_code + array_type = field if array_type == "net.minecraft.network.FriendlyByteBuf": field_type_rs = "UnsizedByteArray" uses.add("azalea_buf::UnsizedByteArray") else: print("instruction that we errored on:", instruction) - deobfuscated_class_name = ( - mappings.get_class(obfuscated_class_name) if obfuscated_class_name else None - ) - raise Exception( - f"Unknown field type: {burger_type} ({deobfuscated_class_name or obfuscated_class_name})" - ) + raise Exception(f"Unknown field type: {burger_type} ({class_name})") return field_type_rs, is_var, uses, extra_code |
