diff options
Diffstat (limited to 'codegen')
| -rw-r--r-- | codegen/genitemcomponents.py | 165 | ||||
| -rwxr-xr-x | codegen/lib/code/blocks.py | 7 | ||||
| -rw-r--r-- | codegen/lib/code/entity.py | 30 | ||||
| -rw-r--r-- | codegen/lib/code/item_components.py | 164 | ||||
| -rwxr-xr-x | codegen/lib/code/packet.py | 37 | ||||
| -rwxr-xr-x | codegen/lib/extract.py | 5 | ||||
| -rwxr-xr-x | codegen/migrate.py | 8 |
7 files changed, 227 insertions, 189 deletions
diff --git a/codegen/genitemcomponents.py b/codegen/genitemcomponents.py index 625af847..b0002ae2 100644 --- a/codegen/genitemcomponents.py +++ b/codegen/genitemcomponents.py @@ -1,167 +1,6 @@ -import lib.code.inventory -import lib.code.registry +import lib.code.item_components import lib.code.version -import lib.code.packet -import lib.code.utils -import lib.code.tags -import lib.download -import lib.extract -import lib.utils - -ITEM_COMPONENTS_DIR = 'azalea-inventory/src/components.rs' - -def generate(version_id: str): - expected_variants = get_expected_variants(version_id) - actual_variants = get_actual_variants() - - new_variants = [] - removed_variants = [] - - for variant in expected_variants: - if variant not in actual_variants: - new_variants.append(variant) - for variant in actual_variants: - if variant not in expected_variants: - removed_variants.append(variant) - - print('New variants:') - for variant in new_variants: - print('-', variant) - print() - print('Removed variants:') - for variant in removed_variants: - print('-', variant) - print() - - for variant in removed_variants: - print(f'Removing {variant}...') - remove_variant(variant) - for variant in new_variants: - print(f'Adding {variant}...') - add_variant(variant) - - lib.code.utils.fmt() - - print('Done!') - -def get_expected_variants(version_id: str): - expected_variants = [] - registries = lib.extract.get_registries_report(version_id) - - registry = registries['minecraft:data_component_type'] - registry_entries = sorted( - registry['entries'].items(), key=lambda x: x[1]['protocol_id']) - for variant_name, _variant in registry_entries: - variant_struct_name = lib.utils.to_camel_case(variant_name.split(':')[-1]) - expected_variants.append(variant_struct_name) - - return expected_variants - -def get_actual_variants(): - actual_variants = [] - with open(ITEM_COMPONENTS_DIR, 'r') as f: - code = f.read().split('\n') - - in_match = False - for line in code: - if in_match: - if line == ' })': - break - variant_line_prefix = ' DataComponentKind::' - if line.startswith(variant_line_prefix): - variant = line[len(variant_line_prefix):].split(' ', 1)[0] - actual_variants.append(variant) - elif line == ' Ok(match kind {': - in_match = True - - return actual_variants - -def remove_variant(variant: str): - with open(ITEM_COMPONENTS_DIR, 'r') as f: - code = f.read().split('\n') - - first_line_with_variant = None - line_after_variant = None - - in_match = False - for i, line in enumerate(list(code)): - if in_match: - if line == ' })': - line_after_variant = i - break - variant_line_prefix = ' DataComponentKind::' - if line.startswith(variant_line_prefix): - if first_line_with_variant is not None: - line_after_variant = i - break - variant_name = line[len(variant_line_prefix):].split(' ', 1)[0] - if variant_name == variant: - first_line_with_variant = i - elif line == ' Ok(match kind {': - in_match = True - - if first_line_with_variant is None: - raise ValueError(f'Variant {variant} not found') - if line_after_variant is None: - raise ValueError(f'Couldn\'t find end of variant {variant}') - - code = code[:first_line_with_variant] + code[line_after_variant:] - - # now remove the struct - line_before_struct = None # this is the #[derive] line - line_after_struct = None # impl DataComponent for ... {\n...\n} - for i, line in enumerate(list(code)): - if line == f'pub struct {variant} {{' or line == f'pub struct {variant};': - line_before_struct = i - 1 - elif line == f'impl DataComponent for {variant} {{': - line_after_struct = i + 3 - break - if line_before_struct is None: - raise ValueError(f'Couldn\'t find struct {variant}') - if line_after_struct is None: - raise ValueError(f'Couldn\'t find impl DataComponent for {variant}') - - code = code[:line_before_struct] + code[line_after_struct:] - - with open(ITEM_COMPONENTS_DIR, 'w') as f: - f.write('\n'.join(code)) - -def add_variant(variant: str): - with open(ITEM_COMPONENTS_DIR, 'r') as f: - code = f.read().split('\n') - - in_match = False - last_line_in_match = None - for i, line in enumerate(list(code)): - if in_match: - if line == ' })': - last_line_in_match = i - break - elif line == ' Ok(match kind {': - in_match = True - - if last_line_in_match is None: - raise ValueError('Couldn\'t find end of match') - - code = code[:last_line_in_match] + [ - f' DataComponentKind::{variant} => Box::new({variant}::azalea_read(buf)?),', - ] + code[last_line_in_match:] - - # now insert the struct - code.append('') - code.append('#[derive(Clone, PartialEq, AzBuf)]') - code.append(f'pub struct {variant} {{') - code.append(' pub todo: todo!(), // see DataComponents.java') - code.append('}') - code.append(f'impl DataComponent for {variant} {{') - code.append(f' const KIND: DataComponentKind = DataComponentKind::{variant};') - code.append('}') - - with open(ITEM_COMPONENTS_DIR, 'w') as f: - f.write('\n'.join(code)) - - lib.code.utils.fmt() if __name__ == '__main__': version_id = lib.code.version.get_version_id() - generate(version_id) + lib.code.item_components.generate(version_id) diff --git a/codegen/lib/code/blocks.py b/codegen/lib/code/blocks.py index 181ce774..aaa95ffa 100755 --- a/codegen/lib/code/blocks.py +++ b/codegen/lib/code/blocks.py @@ -33,8 +33,7 @@ def generate_blocks(blocks_report: dict, pixlyzer_block_datas: dict, ordered_blo for property_id in list(block_data_report.get('properties', {}).keys()): property_variants = block_data_report['properties'][property_id] - property_struct_name = get_property_struct_name( - block_id, property_id, property_variants) + property_struct_name = get_property_struct_name(block_id, property_id, property_variants) if property_struct_name in properties: if not properties[property_struct_name] == property_variants: @@ -192,6 +191,10 @@ def get_property_struct_name(block_id: str, property_id: str, property_variants: return 'TrialSpawnerState' if property_variants == ['inactive', 'active', 'unlocking', 'ejecting']: return 'VaultState' + if property_variants == ['start', 'log', 'fail', 'accept']: + return 'TestMode' + if property_variants == ['save', 'load', 'corner', 'data']: + return 'StructureMode' if 'harp' in property_variants and 'didgeridoo' in property_variants: return 'Sound' if is_list_of_string_integers(property_variants): diff --git a/codegen/lib/code/entity.py b/codegen/lib/code/entity.py index a1f5525d..c27c4ce7 100644 --- a/codegen/lib/code/entity.py +++ b/codegen/lib/code/entity.py @@ -103,23 +103,24 @@ def generate_entity_metadata(burger_entities_data: dict, mappings: Mappings): // This file is generated from codegen/lib/code/entity.py. // Don't change it manually! -use crate::particle::Particle; - -use super::{ - ArmadilloStateKind, EntityDataItem, EntityDataValue, OptionalUnsignedInt, Pose, Quaternion, - Rotations, SnifferStateKind, VillagerData, -}; use azalea_chat::FormattedText; use azalea_core::{ direction::Direction, position::{BlockPos, Vec3}, }; use azalea_inventory::ItemStack; +use azalea_registry::DataRegistry; use bevy_ecs::{bundle::Bundle, component::Component}; use derive_more::{Deref, DerefMut}; use thiserror::Error; use uuid::Uuid; +use super::{ + ArmadilloStateKind, EntityDataItem, EntityDataValue, OptionalUnsignedInt, Pose, Quaternion, + Rotations, SnifferStateKind, VillagerData, +}; +use crate::particle::Particle; + #[derive(Error, Debug)] pub enum UpdateMetadataError { #[error("Wrong type ({0:?})")] @@ -410,12 +411,15 @@ impl From<EntityDataValue> for UpdateMetadataError { # some types don't have Default implemented if type_name == 'CompoundTag': default = 'simdnbt::owned::NbtCompound::default()' - elif type_name == 'CatVariant': - default = 'azalea_registry::CatVariant::Tabby' - elif type_name == 'PaintingVariant': - default = 'azalea_registry::PaintingVariant::Kebab' - elif type_name == 'FrogVariant': - default = 'azalea_registry::FrogVariant::Temperate' + # elif type_name == 'CatVariant': + # # TODO: the default should be Tabby but we don't have a way to get that from here + # default = 'azalea_registry::CatVariant::new_raw(0)' + # elif type_name == 'PaintingVariant': + # default = 'azalea_registry::PaintingVariant::Kebab' + # elif type_name == 'FrogVariant': + # default = 'azalea_registry::FrogVariant::Temperate' + elif type_name.endswith('Variant'): + default = f'azalea_registry::{type_name}::new_raw(0)' elif type_name == 'VillagerData': default = 'VillagerData { kind: azalea_registry::VillagerKind::Plains, profession: azalea_registry::VillagerProfession::None, level: 0 }' else: @@ -430,7 +434,7 @@ impl From<EntityDataValue> for UpdateMetadataError { default = f'BlockPos::new{default}' elif type_name == 'OptionalBlockPos': # Option<BlockPos> default = f'Some(BlockPos::new{default})' if default != 'Empty' else 'None' - elif type_name == 'OptionalUuid': + elif type_name == 'OptionalLivingEntityReference': default = f'Some(uuid::uuid!({default}))' if default != 'Empty' else 'None' elif type_name == 'OptionalUnsignedInt': default = f'OptionalUnsignedInt(Some({default}))' if default != 'Empty' else 'OptionalUnsignedInt(None)' diff --git a/codegen/lib/code/item_components.py b/codegen/lib/code/item_components.py new file mode 100644 index 00000000..3d4bf6a6 --- /dev/null +++ b/codegen/lib/code/item_components.py @@ -0,0 +1,164 @@ +import lib.code.inventory +import lib.code.registry +import lib.code.version +import lib.code.packet +import lib.code.utils +import lib.code.tags +import lib.download +import lib.extract +import lib.utils + + +ITEM_COMPONENTS_DIR = 'azalea-inventory/src/components.rs' + +def generate(version_id: str): + expected_variants = get_expected_variants(version_id) + actual_variants = get_actual_variants() + + new_variants = [] + removed_variants = [] + + for variant in expected_variants: + if variant not in actual_variants: + new_variants.append(variant) + for variant in actual_variants: + if variant not in expected_variants: + removed_variants.append(variant) + + print('New variants:') + for variant in new_variants: + print('-', variant) + print() + print('Removed variants:') + for variant in removed_variants: + print('-', variant) + print() + + for variant in removed_variants: + print(f'Removing {variant}...') + remove_variant(variant) + for variant in new_variants: + print(f'Adding {variant}...') + add_variant(variant) + + lib.code.utils.fmt() + + print('Done!') + +def get_expected_variants(version_id: str): + expected_variants = [] + registries = lib.extract.get_registries_report(version_id) + + registry = registries['minecraft:data_component_type'] + registry_entries = sorted( + registry['entries'].items(), key=lambda x: x[1]['protocol_id']) + for variant_name, _variant in registry_entries: + variant_struct_name = lib.utils.to_camel_case(variant_name.split(':')[-1]) + expected_variants.append(variant_struct_name) + + return expected_variants + +def get_actual_variants(): + actual_variants = [] + with open(ITEM_COMPONENTS_DIR, 'r') as f: + code = f.read().split('\n') + + in_match = False + for line in code: + if in_match: + if line == ' })': + break + variant_line_prefix = ' DataComponentKind::' + if line.startswith(variant_line_prefix): + variant = line[len(variant_line_prefix):].split(' ', 1)[0] + actual_variants.append(variant) + elif line == ' Ok(match kind {': + in_match = True + + return actual_variants + +def remove_variant(variant: str): + with open(ITEM_COMPONENTS_DIR, 'r') as f: + code = f.read().split('\n') + + first_line_with_variant = None + line_after_variant = None + + in_match = False + for i, line in enumerate(list(code)): + if in_match: + if line == ' })': + line_after_variant = i + break + variant_line_prefix = ' DataComponentKind::' + if line.startswith(variant_line_prefix): + if first_line_with_variant is not None: + line_after_variant = i + break + variant_name = line[len(variant_line_prefix):].split(' ', 1)[0] + if variant_name == variant: + first_line_with_variant = i + elif line == ' Ok(match kind {': + in_match = True + + if first_line_with_variant is None: + raise ValueError(f'Variant {variant} not found') + if line_after_variant is None: + raise ValueError(f'Couldn\'t find end of variant {variant}') + + code = code[:first_line_with_variant] + code[line_after_variant:] + + # now remove the struct + line_before_struct = None # this is the #[derive] line + line_after_struct = None # impl DataComponent for ... {\n...\n} + for i, line in enumerate(list(code)): + if line == f'pub struct {variant} {{' or line == f'pub struct {variant};': + line_before_struct = i - 1 + elif line == f'impl DataComponent for {variant} {{': + line_after_struct = i + 3 + break + if line_before_struct is None: + raise ValueError(f'Couldn\'t find struct {variant}') + if line_after_struct is None: + raise ValueError(f'Couldn\'t find impl DataComponent for {variant}') + + code = code[:line_before_struct] + code[line_after_struct:] + + with open(ITEM_COMPONENTS_DIR, 'w') as f: + f.write('\n'.join(code)) + +def add_variant(variant: str): + with open(ITEM_COMPONENTS_DIR, 'r') as f: + code = f.read().split('\n') + + in_match = False + last_line_in_match = None + for i, line in enumerate(list(code)): + if in_match: + if line == ' })': + last_line_in_match = i + break + elif line == ' Ok(match kind {': + in_match = True + + if last_line_in_match is None: + raise ValueError('Couldn\'t find end of match') + + code = code[:last_line_in_match] + [ + f' DataComponentKind::{variant} => Box::new({variant}::azalea_read(buf)?),', + ] + code[last_line_in_match:] + + # now insert the struct + code.append('') + code.append('#[derive(Clone, PartialEq, AzBuf)]') + code.append(f'pub struct {variant} {{') + code.append(' pub todo: todo!(), // see DataComponents.java') + code.append('}') + code.append(f'impl DataComponent for {variant} {{') + code.append(f' const KIND: DataComponentKind = DataComponentKind::{variant};') + code.append('}') + + with open(ITEM_COMPONENTS_DIR, 'w') as f: + f.write('\n'.join(code)) + + lib.code.utils.fmt() diff --git a/codegen/lib/code/packet.py b/codegen/lib/code/packet.py index 1d60378a..5ae2d41f 100755 --- a/codegen/lib/code/packet.py +++ b/codegen/lib/code/packet.py @@ -14,6 +14,8 @@ MOJMAP_TO_AZALEA_STATE_NAME_MAPPING = { } AZALEA_TO_MOJMAP_STATE_NAME_MAPPING = {v: k for k, v in MOJMAP_TO_AZALEA_STATE_NAME_MAPPING.items()} +PACKETS_DIR = '../azalea-protocol/src/packets' + def generate_packet(packets_report, packet_name, direction, state): mojmap_state = AZALEA_TO_MOJMAP_STATE_NAME_MAPPING.get(state, state) _packet_report = packets_report[mojmap_state][direction]['minecraft:' + packet_name] @@ -24,7 +26,7 @@ def generate_packet(packets_report, packet_name, direction, state): packet_derive_name = f'{to_camel_case(direction)}{to_camel_case(state)}Packet' packet_struct_name = to_camel_case(f'{direction}_{packet_name}') - packet_module_name = f'{direction[0]}_{packet_name}' + packet_module_name = get_packet_module_name(packet_name, direction) code.append(f'use azalea_buf::AzBuf;') code.append(f'use azalea_protocol_macros::{packet_derive_name};') @@ -42,11 +44,16 @@ def generate_packet(packets_report, packet_name, direction, state): # this won't handle writing to the packets/{state}/mod.rs file since we'd need to know the full packet list -def set_packets(packets_report): +def get_packet_module_name(packet_name: str, direction: str): + return f'{direction[0]}_{packet_name}' + +def set_packets(packets_report): for mojmap_state in packets_report: state = MOJMAP_TO_AZALEA_STATE_NAME_MAPPING.get(mojmap_state, mojmap_state) - mod_rs_dir = get_dir_location( - f'../azalea-protocol/src/packets/{state}/mod.rs') + + expected_packet_module_names = set() + state_dir = get_dir_location(f'{PACKETS_DIR}/{state}') + mod_rs_dir = get_dir_location(f'{state_dir}/mod.rs') serverbound_packets = packet_direction_report_to_packet_names(packets_report[mojmap_state]['serverbound']) clientbound_packets = packet_direction_report_to_packet_names(packets_report[mojmap_state].get('clientbound', {})) @@ -61,10 +68,12 @@ def set_packets(packets_report): code.append(' Clientbound => [') for packet_id, packet_name in enumerate(clientbound_packets): code.append(f' {packet_name}, // {padded_hex(packet_id)}') + expected_packet_module_names.add(get_packet_module_name(packet_name, 'clientbound')) code.append(' ],') code.append(' Serverbound => [') for packet_id, packet_name in enumerate(serverbound_packets): code.append(f' {packet_name}, // {padded_hex(packet_id)}') + expected_packet_module_names.add(get_packet_module_name(packet_name, 'serverbound')) code.append(' ]') code.append(');') code.append('') @@ -72,6 +81,23 @@ def set_packets(packets_report): with open(mod_rs_dir, 'w') as f: f.write('\n'.join(code)) + existing_packet_module_names = set() + # iterate over the directory + for file in os.listdir(state_dir): + if file.endswith('.rs') and file != 'mod.rs': + existing_packet_module_names.add(file[:-len('.rs')]) + for packet_module_name in expected_packet_module_names - existing_packet_module_names: + direction = None + if packet_module_name.startswith('c_'): + direction = 'clientbound' + elif packet_module_name.startswith('s_'): + direction = 'serverbound' + else: + raise Exception(f'Invalid packet module name: {packet_module_name}') + packet = packet_module_name[2:] + generate_packet(packets_report, packet, direction, state) + + def packet_direction_report_to_packet_names(report): name_to_id = {} for resource_location, packet in report.items(): @@ -82,8 +108,7 @@ def packet_direction_report_to_packet_names(report): return names_sorted def get_packets(direction: str, state: str): - mod_rs_dir = get_dir_location( - f'../azalea-protocol/src/packets/{state}/mod.rs') + mod_rs_dir = get_dir_location(f'{PACKETS_DIR}/{state}/mod.rs') with open(mod_rs_dir, 'r') as f: mod_rs = f.read().splitlines() diff --git a/codegen/lib/extract.py b/codegen/lib/extract.py index c62b2b99..564133e2 100755 --- a/codegen/lib/extract.py +++ b/codegen/lib/extract.py @@ -85,8 +85,7 @@ def run_python_command_and_download_deps(command): break missing_lib = regex_match.group(1) print('Missing required lib:', missing_lib) - os.system( - f'{determine_python_command()} -m pip install {missing_lib}') + subprocess.run(f'venv/bin/pip install {missing_lib}', cwd=os.path.dirname(os.path.dirname(__file__))) print('ok') @@ -99,7 +98,7 @@ def get_burger_data_for_version(version_id: str): print('\033[92mRunning Burger...\033[m') run_python_command_and_download_deps( f'cd {get_dir_location("__cache__/Burger")} && '\ - f'{determine_python_command()} munch.py {get_dir_location("__cache__")}/client-{version_id}.jar '\ + f'venv/bin/python munch.py {get_dir_location("__cache__")}/client-{version_id}.jar '\ f'--output {get_dir_location("__cache__")}/burger-{version_id}.json '\ f'--mappings {get_dir_location("__cache__")}/mappings-{version_id}.txt' ) diff --git a/codegen/migrate.py b/codegen/migrate.py index 53d5b588..30e33812 100755 --- a/codegen/migrate.py +++ b/codegen/migrate.py @@ -1,3 +1,4 @@ +import lib.code.item_components import lib.code.inventory import lib.code.language import lib.code.registry @@ -48,7 +49,7 @@ new_block_states_report = lib.extract.get_block_states_report(new_version_id) new_registries = lib.extract.get_registries_report(new_version_id) new_ordered_blocks = lib.code.blocks.get_ordered_blocks(new_registries) lib.code.blocks.generate_blocks( - new_block_states_report, new_pixlyzer_block_datas, new_ordered_blocks) + new_block_states_report, new_pixlyzer_block_datas, new_ordered_blocks, new_burger_data) lib.code.shapes.generate_block_shapes( new_pixlyzer_block_datas, new_shape_datas['shapes'], new_shape_datas['aabbs'], new_block_states_report) @@ -60,10 +61,13 @@ print('Generating registries...') import genregistries genregistries.generate(new_version_id) -# print('Generating entity metadata...') +print('Generating entity metadata...') burger_entities_data = new_burger_data[0]['entities'] lib.code.entity.generate_entity_metadata(burger_entities_data, new_mappings) +print('Generating item components...') +lib.code.item_components.generate(new_version_id) + print('Finishing touches, setting version in README and formatting code...') lib.code.version.set_version_id(new_version_id) |
