1
2
Fork 0
mirror of https://github.com/mat-1/azalea.git synced 2025-08-02 14:26:04 +00:00

generate metadata.rs correctly for bevy_ecs

This commit is contained in:
mat 2022-12-17 19:09:36 -06:00
parent 52772afe85
commit 1d26604ec6
3 changed files with 6622 additions and 11463 deletions

View file

@ -54,7 +54,7 @@ pub enum EntityDataValue {
Float(f32),
String(String),
FormattedText(FormattedText),
OptionalComponent(Option<FormattedText>),
OptionalFormattedText(Option<FormattedText>),
ItemStack(Slot),
Boolean(bool),
Rotations(Rotations),

File diff suppressed because it is too large Load diff

View file

@ -15,8 +15,8 @@ def generate_entity_metadata(burger_entity_data: dict, mappings: Mappings):
{'name': 'Long', 'type': 'i64'},
{'name': 'Float', 'type': 'f32'},
{'name': 'String', 'type': 'String'},
{'name': 'Component', 'type': 'FormattedText'},
{'name': 'OptionalComponent', 'type': 'Option<FormattedText>'},
{'name': 'FormattedText', 'type': 'FormattedText'},
{'name': 'OptionalFormattedText', 'type': 'Option<FormattedText>'},
{'name': 'ItemStack', 'type': 'Slot'},
{'name': 'Boolean', 'type': 'bool'},
{'name': 'Rotations', 'type': 'Rotations'},
@ -42,7 +42,7 @@ def generate_entity_metadata(burger_entity_data: dict, mappings: Mappings):
#![allow(clippy::clone_on_copy, clippy::derivable_impls)]
use super::{
EntityDataValue, EntityMetadataItems, OptionalUnsignedInt, Pose, Rotations, VillagerData,
EntityDataValue, EntityMetadataItems, OptionalUnsignedInt, Pose, Rotations, VillagerData, EntityDataItem,
};
use azalea_block::BlockState;
use azalea_chat::FormattedText;
@ -129,13 +129,15 @@ impl From<EntityDataValue> for UpdateMetadataError {
return field_name_map[entity_ids_for_all_field_names_or_bitfields[index]][name]
return name
for parent_id in list(reversed(get_entity_parents(entity_id, burger_entity_data))):
parents = get_entity_parents(entity_id, burger_entity_data)
for parent_id in list(reversed(parents)):
for index, name_or_bitfield in get_entity_metadata_names(parent_id, burger_entity_data, mappings).items():
assert index == len(all_field_names_or_bitfields)
all_field_names_or_bitfields.append(name_or_bitfield)
entity_ids_for_all_field_names_or_bitfields.append(parent_id)
entity_metadatas.extend(get_entity_metadata(
parent_id, burger_entity_data))
parent_id = parents[1] if len(parents) > 1 else None
# now add all the fields/component structs
for index, name_or_bitfield in enumerate(all_field_names_or_bitfields):
@ -170,115 +172,147 @@ impl From<EntityDataValue> for UpdateMetadataError {
code.append(f'#[derive(Component)]')
code.append(f'pub struct {struct_name}(pub bool);')
# add the entity struct and Query struct
is_actually_entity = not entity_id.startswith('~')
if is_actually_entity:
struct_name: str = upper_first_letter(to_camel_case(entity_id))
code.append(f'#[derive(Component)]')
code.append(f'pub struct {struct_name};')
# add the entity struct and Bundle struct
struct_name: str = upper_first_letter(
to_camel_case(entity_id.lstrip('~')))
code.append(f'#[derive(Component)]')
code.append(f'pub struct {struct_name};')
# #[derive(Bundle)]
# struct AllayBundle {
# health: Health,
# ...
# dancing: Dancing,
# can_duplicate: CanDuplicate,
# }
bundle_struct_name = f'{struct_name}Bundle'
code.append(f'')
code.append(f'#[derive(Bundle)]')
code.append(f'struct {bundle_struct_name} {{')
for index, name_or_bitfield in enumerate(all_field_names_or_bitfields):
if isinstance(name_or_bitfield, str):
name_or_bitfield = maybe_rename_field(
name_or_bitfield, index)
struct_name = upper_first_letter(
to_camel_case(name_or_bitfield))
code.append(
f' {name_or_bitfield}: {struct_name},')
else:
for mask, name in name_or_bitfield.items():
name = maybe_rename_field(name, index)
parent_struct_name = upper_first_letter(
to_camel_case(parent_id.lstrip("~"))) if parent_id else None
struct_name = upper_first_letter(to_camel_case(name))
code.append(f' {name}: {struct_name},')
code.append('}')
# impl Allay {
# pub fn update_metadata(
# ecs: bevy_ecs::world::World,
# entity: &mut bevy_ecs::world::EntityMut,
# d: EntityDataItem,
# ) -> Result<(), UpdateMetadataError> {
# match d.index {
# 0..=15 => AbstractCreatureBundle::update_metadata(ecs, entity, d)?,
# 16 => entity.insert(Dancing(d.value.into_boolean()?)),
# 17 => entity.insert(CanDuplicate(d.value.into_boolean()?)),
# }
# Ok(())
# }
# }
code.append(f'impl {struct_name} {{')
code.append(
f' pub fn update_metadata(ecs: bevy_ecs::world::World, entity: &mut bevy_ecs::world::EntityMut, d: EntityDataItem) -> Result<(), UpdateMetadataError> {{')
code.append(f' match d.index {{')
# impl AllayBundle {
# pub fn update_metadata(
# &mut self,
# ecs: bevy_ecs::world::World,
# entity: bevy_ecs::world::EntityMut,
# data: EntityMetadataItems,
# ) -> Result<(), UpdateMetadataError> {
# for d in data.0 {
# match d.index {
# 0 => self.health = Health(d.value.into_float()?),
# 1 => self.dancing = Dancing(d.value.into_boolean()?),
# 2 => self.can_duplicate = CanDuplicate(d.value.into_boolean()?),
# }
# }
# Ok(())
# }
# }
code.append(f'impl {bundle_struct_name} {{')
parent_last_index = -1
for index, name_or_bitfield in enumerate(all_field_names_or_bitfields):
is_from_parent = entity_ids_for_all_field_names_or_bitfields[index] != entity_id
if is_from_parent:
parent_last_index = index
if parent_last_index != -1:
code.append(
f' pub fn update_metadata(&mut self, ecs: bevy_ecs::world::World, entity: bevy_ecs::world::EntityMut, data: EntityMetadataItems) -> Result<(), UpdateMetadataError> {{')
code.append(f' for d in data.0 {{')
code.append(f' match d.index {{')
for index, name_or_bitfield in enumerate(all_field_names_or_bitfields):
if isinstance(name_or_bitfield, str):
name_or_bitfield = maybe_rename_field(
name_or_bitfield, index)
f' 0..={parent_last_index} => {parent_struct_name}::update_metadata(ecs, entity, d)?,')
struct_name = upper_first_letter(
to_camel_case(name_or_bitfield))
if name_or_bitfield in single_use_imported_types:
struct_name = ''
for index, name_or_bitfield in enumerate(all_field_names_or_bitfields):
if index <= parent_last_index:
continue
if isinstance(name_or_bitfield, str):
name_or_bitfield = maybe_rename_field(
name_or_bitfield, index)
type_id = next(filter(lambda i: i['index'] == index, entity_metadatas))[
'type_id']
metadata_type_data = metadata_types[type_id]
rust_type = metadata_type_data['type']
type_name = metadata_type_data['name']
field_struct_name = upper_first_letter(
to_camel_case(name_or_bitfield))
if name_or_bitfield in single_use_imported_types:
field_struct_name = ''
type_id = next(filter(lambda i: i['index'] == index, entity_metadatas))[
'type_id']
metadata_type_data = metadata_types[type_id]
rust_type = metadata_type_data['type']
type_name = metadata_type_data['name']
type_name_field = to_snake_case(type_name)
read_field_code = f'{field_struct_name}(d.value.into_{type_name_field}()?)' if field_struct_name else f'd.value.into_{type_name_field}()?'
code.append(
f' {index} => {{ entity.insert({read_field_code}); }},')
else:
code.append(f' {index} => {{')
code.append(
f'let bitfield = d.value.into_byte()?;')
for mask, name in name_or_bitfield.items():
name = maybe_rename_field(name, index)
field_struct_name = upper_first_letter(to_camel_case(name))
type_name_field = to_snake_case(type_name)
read_field_code = f'{struct_name}(d.value.into_{type_name_field}()?)' if struct_name else f'd.value.into_{type_name_field}()?'
code.append(
f' {index} => self.{name_or_bitfield} = {read_field_code},')
else:
code.append(f' {index} => {{')
code.append(
f'let bitfield = d.value.into_byte()?;')
for mask, name in name_or_bitfield.items():
name = maybe_rename_field(name, index)
struct_name = upper_first_letter(to_camel_case(name))
f'entity.insert({field_struct_name}(bitfield & {mask} != 0));')
code.append(' },')
code.append(' }')
code.append(' Ok(())')
code.append(' }')
code.append('}')
code.append('')
code.append(
f'self.{name} = {struct_name}(bitfield & {mask} != 0);')
code.append(' },')
code.append(' }')
code.append(' }')
code.append(' Ok(())')
code.append(' }')
code.append('}')
code.append('')
# impl Default for AllayBundle {
# fn default() -> Self {
# Self {
# on_fire: OnFire(false),
# shift_key_down: ShiftKeyDown(false),
# sprinting: Sprinting(false),
# swimming: Swimming(false)
# }
# }
# }
code.append(f'impl Default for {bundle_struct_name} {{')
# #[derive(Bundle)]
# struct AllayBundle {
# health: Health,
# ...
# dancing: Dancing,
# can_duplicate: CanDuplicate,
# }
bundle_struct_name = f'{struct_name}Bundle'
code.append(f'')
code.append(f'#[derive(Bundle)]')
code.append(f'struct {bundle_struct_name} {{')
if parent_struct_name:
code.append(
' fn default() -> Self {')
code.append(' Self {')
for index, name_or_bitfield in enumerate(all_field_names_or_bitfields):
f' parent: {parent_struct_name}Bundle,')
for index, name_or_bitfield in get_entity_metadata_names(entity_id, burger_entity_data, mappings).items():
if isinstance(name_or_bitfield, str):
name_or_bitfield = maybe_rename_field(
name_or_bitfield, index)
struct_name = upper_first_letter(
to_camel_case(name_or_bitfield))
code.append(
f' {name_or_bitfield}: {struct_name},')
else:
for mask, name in name_or_bitfield.items():
name = maybe_rename_field(name, index)
struct_name = upper_first_letter(to_camel_case(name))
code.append(f' {name}: {struct_name},')
code.append('}')
# impl Default for AllayBundle {
# fn default() -> Self {
# Self {
# parent: AbstractCreatureBundle {
# on_fire: OnFire(false),
# shift_key_down: ShiftKeyDown(false),
# },
# sprinting: Sprinting(false),
# swimming: Swimming(false)
# }
# }
# }
code.append(f'impl Default for {bundle_struct_name} {{')
code.append(
' fn default() -> Self {')
def generate_fields(this_entity_id: str):
# on_fire: OnFire(false),
# shift_key_down: ShiftKeyDown(false),
# if it has a parent, put it (recursion)
# parent: AbstractCreatureBundle { ... },
this_entity_parent_ids = get_entity_parents(
this_entity_id, burger_entity_data)
this_entity_parent_id = this_entity_parent_ids[1] if len(
this_entity_parent_ids) > 1 else None
if this_entity_parent_id:
bundle_struct_name = upper_first_letter(
to_camel_case(this_entity_parent_id.lstrip('~'))) + 'Bundle'
code.append(
f' parent: {bundle_struct_name} {{')
generate_fields(this_entity_parent_id)
code.append(
' },')
for index, name_or_bitfield in get_entity_metadata_names(this_entity_id, burger_entity_data, mappings).items():
default = next(filter(lambda i: i['index'] == index, entity_metadatas)).get(
'default', 'Default::default()')
if isinstance(name_or_bitfield, str):
@ -324,7 +358,7 @@ impl From<EntityDataValue> for UpdateMetadataError {
default = f'Slot::Present({default})' if default != 'Empty' else 'Slot::Empty'
elif type_name == 'BlockState':
default = f'{default}' if default != 'Empty' else 'BlockState::Air'
elif type_name == 'OptionalComponent':
elif type_name == 'OptionalFormattedText':
default = f'Some({default})' if default != 'Empty' else 'None'
elif type_name == 'CompoundTag':
default = f'azalea_nbt::Tag::Compound({default})' if default != 'Empty' else 'azalea_nbt::Tag::Compound(Default::default())'
@ -343,352 +377,51 @@ impl From<EntityDataValue> for UpdateMetadataError {
default & mask != 0) else 'false'
code.append(
f' {name}: {upper_first_letter(to_camel_case(name))}({bit_default}),')
code.append(' }')
code.append(' }')
code.append('}')
code.append('')
code.append(' Self {')
generate_fields(entity_id)
code.append(' }')
code.append(' }')
code.append('}')
code.append('')
# parent_field_name = None
for entity_id in burger_entity_data:
new_entity(entity_id)
# and now make the main update_metadata
# fn update_metadata(
# and now make the main update_metadatas
# fn update_metadatas(
# ecs: bevy_ecs::world::World,
# entity: bevy_ecs::world::EntityMut,
# data: EntityMetadataItems,
# ) -> Result<(), UpdateMetadataError> {
# if let Ok(e) = world.query_one_mut::<AllayBundle>(entity) {
# e.update_metadata(ecs, entity, data)?;
# if entity.contains::<Allay>() {
# for d in data.0 {
# Allay::update_metadata(ecs, entity, d)?;
# }
# return Ok(());
# }
#
# Ok(())
# }
code.append(
f'fn update_metadata(ecs: bevy_ecs::world::World, entity: bevy_ecs::world::EntityMut, data: EntityMetadataItems) -> Result<(), UpdateMetadataError> {{')
f'fn update_metadatas(ecs: bevy_ecs::world::World, entity: bevy_ecs::world::EntityMut, data: EntityMetadataItems) -> Result<(), UpdateMetadataError> {{')
for entity_id in burger_entity_data:
if entity_id.startswith('~'):
# not actually an entiry
# not actually an entity
continue
struct_name: str = upper_first_letter(to_camel_case(entity_id))
bundle_struct_name = f'{struct_name}Bundle'
code.append(
f' if let Ok(e) = ecs.query_one_mut::<{bundle_struct_name}>(entity) {{')
f' if entity.contains::<{struct_name}>() {{')
code.append(' for d in data.0 {')
code.append(
f' e.update_metadata(ecs, entity, data)?;')
f' {struct_name}::update_metadata(ecs, &mut entity, d)?;')
code.append(' }')
code.append(f' return Ok(());')
code.append(' }')
code.append(' Ok(())')
code.append('}')
code.append('')
# entity_parents = get_entity_parents(entity_id, burger_entity_data)
# entity_metadata = get_entity_metadata(entity_id, burger_entity_data)
# entity_metadata_names = get_entity_metadata_names(
# entity_id, burger_entity_data, mappings)
# struct_name: str = upper_first_letter(
# to_camel_case(entity_parents[0].replace('~', '')))
# parent_struct_name: Optional[str] = upper_first_letter(to_camel_case(
# entity_parents[1].replace('~', ''))) if (len(entity_parents) >= 2) else None
# if parent_struct_name:
# parent_field_name = to_snake_case(parent_struct_name)
# if not entity_parents[0].startswith('~'):
# entity_structs.append(struct_name)
# reader_code = []
# writer_code = []
# set_index_code = []
# field_names = []
# code.append(f'#[derive(Debug, Clone)]')
# code.append(f'pub struct {struct_name} {{')
# if parent_struct_name:
# assert parent_field_name
# code.append(f'pub {parent_field_name}: {parent_struct_name},')
# reader_code.append(
# f'let {parent_field_name} = {parent_struct_name}::read(metadata)?;')
# writer_code.append(
# f'metadata.extend(self.{parent_field_name}.write());')
# for index, name_or_bitfield in entity_metadata_names.items():
# if isinstance(name_or_bitfield, str):
# # normal field (can be any type)
# name = name_or_bitfield
# if name == 'type':
# name = 'kind'
# field_names.append(name)
# type_id = next(filter(lambda i: i['index'] == index, entity_metadata))[
# 'type_id']
# metadata_type_data = metadata_types[type_id]
# rust_type = metadata_type_data['type']
# type_name = metadata_type_data['name']
# code.append(f'pub {name}: {rust_type},')
# type_name_field = to_snake_case(type_name)
# reader_code.append(
# f'let {name} = metadata.pop_front()?.into_{type_name_field}().ok()?;')
# writer_code.append(
# f'metadata.push(EntityDataValue::{type_name}(self.{name}.clone()));')
# # 1 => self.dancing = value.into_boolean().ok()?,
# set_index_code.append(
# f'{index} => self.{name} = value.into_{type_name_field}().ok()?,'
# )
# else:
# # bitfield (sent as a byte, each bit in the byte is used as a boolean)
# reader_code.append(
# 'let bitfield = metadata.pop_front()?.into_byte().ok()?;')
# writer_code.append('let mut bitfield = 0u8;')
# set_index_code.append(f'{index} => {{')
# set_index_code.append(
# f'let bitfield = value.into_byte().ok()?;')
# for mask, name in name_or_bitfield.items():
# if name == 'type':
# name = 'kind'
# field_names.append(name)
# code.append(f'pub {name}: bool,')
# reader_code.append(f'let {name} = bitfield & {mask} != 0;')
# writer_code.append(
# f'if self.{name} {{ bitfield &= {mask}; }}')
# set_index_code.append(
# f'self.{name} = bitfield & {mask} != 0;')
# writer_code.append(
# 'metadata.push(EntityDataValue::Byte(bitfield));')
# set_index_code.append('},')
# code.append('}')
# code.append('')
# code.append(f'impl {struct_name} {{')
# code.append(
# 'pub fn read(metadata: &mut VecDeque<EntityDataValue>) -> Option<Self> {')
# code.extend(reader_code)
# self_args = []
# if parent_struct_name:
# self_args.append(
# f'{parent_field_name}')
# self_args.extend(field_names)
# code.append(f'Some(Self {{ {",".join(self_args)} }})')
# code.append('}')
# code.append('')
# code.append('pub fn write(&self) -> Vec<EntityDataValue> {')
# code.append('let mut metadata = Vec::new();')
# code.extend(writer_code)
# code.append('metadata')
# code.append('}')
# code.append('}')
# code.append('')
# # default
# code.append(f'impl Default for {struct_name} {{')
# code.append('fn default() -> Self {')
# default_fields_code = []
# if parent_struct_name:
# assert parent_field_name
# default_fields_code.append(
# f'{parent_field_name}: Default::default()')
# for index, name_or_bitfield in entity_metadata_names.items():
# default = next(filter(lambda i: i['index'] == index, entity_metadata)).get(
# 'default', 'Default::default()')
# if isinstance(name_or_bitfield, str):
# type_id = next(filter(lambda i: i['index'] == index, entity_metadata))[
# 'type_id']
# metadata_type_data = metadata_types[type_id]
# type_name = metadata_type_data['name']
# # TODO: burger doesn't get the default if it's a complex type
# # like `Rotations`, so entities like armor stands will have the
# # wrong default metadatas. This should be added to Burger.
# if default is None:
# # some types don't have Default implemented
# if type_name == 'CompoundTag':
# default = 'azalea_nbt::Tag::Compound(Default::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 == 'VillagerData':
# default = 'VillagerData { kind: azalea_registry::VillagerType::Plains, profession: azalea_registry::VillagerProfession::None, level: 0 }'
# else:
# default = 'Default::default()'
# else:
# if type_name == 'Boolean':
# default = 'true' if default else 'false'
# elif type_name == 'String':
# string_escaped = default.replace('"', '\\"')
# default = f'"{string_escaped}".to_string()'
# elif type_name == 'BlockPos':
# 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':
# 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)'
# elif type_name == 'ItemStack':
# default = f'Slot::Present({default})' if default != 'Empty' else 'Slot::Empty'
# elif type_name == 'BlockState':
# default = f'{default}' if default != 'Empty' else 'BlockState::Air'
# elif type_name == 'OptionalComponent':
# default = f'Some({default})' if default != 'Empty' else 'None'
# elif type_name == 'CompoundTag':
# default = f'azalea_nbt::Tag::Compound({default})' if default != 'Empty' else 'azalea_nbt::Tag::Compound(Default::default())'
# print(default, name_or_bitfield, type_name)
# name = name_or_bitfield
# if name == 'type':
# name = 'kind'
# default_fields_code.append(f'{name}: {default}')
# else:
# # if it's a bitfield, we'll have to extract the default for
# # each bool from each bit in the default
# for mask, name in name_or_bitfield.items():
# if name == 'type':
# name = 'kind'
# mask = int(mask, 0)
# field_names.append(name)
# bit_default = 'true' if (default & mask != 0) else 'false'
# default_fields_code.append(f'{name}: {bit_default}')
# # Self { abstract_creature: Default::default(), dancing: Default::default(), can_duplicate: Default::default() }
# code.append(f'Self {{ {", ".join(default_fields_code)} }}')
# code.append('}')
# code.append('}')
# code.append('')
# # impl Allay {
# # pub fn set_index(&mut self, index: u8, value: EntityDataValue) -> Option<()> {
# # match index {
# # 0..=0 => self.abstract_creature.set_index(index, value),
# # 1 => self.dancing = value.into_boolean().ok()?,
# # 2 => self.can_duplicate = value.into_boolean().ok()?,
# # _ => {}
# # }
# # Some(())
# # }
# # }
# code.append(f'impl {struct_name} {{')
# code.append(
# 'pub fn set_index(&mut self, index: u8, value: EntityDataValue) -> Option<()> {')
# if len(entity_metadata_names) > 0:
# code.append('match index {')
# # get the smallest index for this entity
# smallest_index = min(entity_metadata_names.keys())
# if parent_struct_name:
# code.append(
# f'0..={smallest_index-1} => self.{parent_field_name}.set_index(index, value)?,')
# code.extend(set_index_code)
# code.append('_ => {}')
# code.append('}')
# code.append('Some(())')
# elif parent_struct_name:
# code.append(f'self.{parent_field_name}.set_index(index, value)')
# else:
# code.append('Some(())')
# code.append('}')
# code.append('}')
# # deref
# if parent_struct_name:
# code.append(f'impl Deref for {struct_name} {{')
# code.append(f'type Target = {parent_struct_name};')
# code.append(
# f'fn deref(&self) -> &Self::Target {{ &self.{parent_field_name} }}')
# code.append('}')
# code.append(f'impl DerefMut for {struct_name} {{')
# code.append(
# f'fn deref_mut(&mut self) -> &mut Self::Target {{ &mut self.{parent_field_name} }}')
# code.append('}')
# code.append('')
# # make the EntityMetadata enum from entity_structs
# code.append(f'#[derive(Debug, Clone, EnumAsInner)]')
# code.append('pub enum EntityMetadata {')
# for struct_name in entity_structs:
# code.append(f'{struct_name}({struct_name}),')
# code.append('}')
# code.append('')
# # impl From<azalea_registry::EntityKind> for EntityMetadata {
# code.append('impl From<azalea_registry::EntityKind> for EntityMetadata {')
# code.append('fn from(value: azalea_registry::EntityKind) -> Self {')
# code.append('match value {')
# # azalea_registry::EntityKind::Allay => EntityMetadata::Allay(Allay::default()),
# for struct_name in entity_structs:
# code.append(
# f'azalea_registry::EntityKind::{struct_name} => EntityMetadata::{struct_name}({struct_name}::default()),')
# code.append('}')
# code.append('}')
# code.append('}')
# code.append('')
# # impl From<EntityMetadata> for azalea_registry::EntityKind {
# code.append('impl From<&EntityMetadata> for azalea_registry::EntityKind {')
# code.append('fn from(value: &EntityMetadata) -> Self {')
# code.append('match value {')
# # EntityMetadata::Allay(_) => azalea_registry::EntityKind::Allay,
# for struct_name in entity_structs:
# code.append(
# f'EntityMetadata::{struct_name}(_) => azalea_registry::EntityKind::{struct_name},')
# code.append('}')
# code.append('}')
# code.append('}')
# code.append('')
# # impl EntityMetadata
# # pub fn set_index(&mut self, index: u8, value: EntityDataValue)
# code.append('impl EntityMetadata {')
# code.append(
# 'pub fn set_index(&mut self, index: u8, value: EntityDataValue) -> Option<()> {')
# code.append('match self {')
# # EntityMetadata::Allay(allay) => allay.set_index(index, value),
# for struct_name in entity_structs:
# code.append(
# f'EntityMetadata::{struct_name}(entity) => entity.set_index(index, value),')
# code.append('}')
# code.append('}')
# code.append('}')
# code.append('')
# # impl Deref for EntityMetadata {
# # type Target = AbstractEntity;
# # fn deref(&self) -> &Self::Target {
# # match self {
# # EntityMetadata::Allay(entity) => entity,
# # _ => {}
# # }
# # }
# # }
# code.append('impl Deref for EntityMetadata {')
# code.append('type Target = AbstractEntity;')
# code.append('fn deref(&self) -> &Self::Target {')
# code.append('match self {')
# for struct_name in entity_structs:
# code.append(
# f'EntityMetadata::{struct_name}(entity) => entity,')
# code.append('}')
# code.append('}')
# code.append('}')
# code.append('impl DerefMut for EntityMetadata {')
# code.append('fn deref_mut(&mut self) -> &mut Self::Target {')
# code.append('match self {')
# for struct_name in entity_structs:
# code.append(
# f'EntityMetadata::{struct_name}(entity) => entity,')
# code.append('}')
# code.append('}')
# code.append('}')
# code.append('')
with open(METADATA_RS_DIR, 'w') as f:
f.write('\n'.join(code))