aboutsummaryrefslogtreecommitdiff
path: root/codegen/lib/code
diff options
context:
space:
mode:
Diffstat (limited to 'codegen/lib/code')
-rwxr-xr-xcodegen/lib/code/blocks.py13
-rw-r--r--codegen/lib/code/entity.py18
-rw-r--r--codegen/lib/code/language.py8
-rwxr-xr-xcodegen/lib/code/packet.py3
-rwxr-xr-xcodegen/lib/code/registry.py41
-rwxr-xr-xcodegen/lib/code/shapes.py65
-rwxr-xr-xcodegen/lib/code/utils.py6
7 files changed, 118 insertions, 36 deletions
diff --git a/codegen/lib/code/blocks.py b/codegen/lib/code/blocks.py
index c32a3bbc..d5fca732 100755
--- a/codegen/lib/code/blocks.py
+++ b/codegen/lib/code/blocks.py
@@ -20,7 +20,6 @@ def generate_blocks(blocks_burger: dict, blocks_report: dict, ordered_blocks: li
new_make_block_states_macro_code = []
new_make_block_states_macro_code.append('make_block_states! {')
-
# Find properties
properties = {}
@@ -84,7 +83,6 @@ def generate_blocks(blocks_burger: dict, blocks_report: dict, ordered_blocks: li
new_make_block_states_macro_code.append(
f' "{property_name}" => {property_shape_code},')
-
new_make_block_states_macro_code.append(' },')
# Block codegen
@@ -101,7 +99,6 @@ def generate_blocks(blocks_burger: dict, blocks_report: dict, ordered_blocks: li
if state.get('default'):
default_property_variants = state.get('properties', {})
-
properties_code = '{'
for property_name in list(block_data_report.get('properties', {}).keys()):
property_burger = None
@@ -163,6 +160,7 @@ def generate_blocks(blocks_burger: dict, blocks_report: dict, ordered_blocks: li
with open(BLOCKS_RS_DIR, 'w') as f:
f.write('\n'.join(new_code))
+
def get_property_struct_name(property: Optional[dict], block_data_burger: dict, property_variants: list[str], mappings: Mappings) -> str:
# these are hardcoded because otherwise they cause conflicts
# some names inspired by https://github.com/feather-rs/feather/blob/main/feather/blocks/src/generated/table.rs
@@ -184,16 +182,23 @@ def get_property_struct_name(property: Optional[dict], block_data_burger: dict,
return 'ChestType'
if property_variants == ['compare', 'subtract']:
return 'ComparatorType'
+ if 'harp' in property_variants and 'didgeridoo' in property_variants:
+ return 'Sound'
if property is None:
return ''.join(map(to_camel_case, property_variants))
- property_name = None
for class_name in [block_data_burger['class']] + block_data_burger['super']:
property_name = mappings.get_field(
class_name, property['field_name'])
if property_name:
break
+ if property_name is None:
+ if 'declared_in' in property:
+ property_name = mappings.get_field(
+ property['declared_in'], property['field_name'])
+ if property_name is None:
+ property_name = property['name']
assert property_name
property_name = to_camel_case(property_name.lower())
if property['type'] == 'int':
diff --git a/codegen/lib/code/entity.py b/codegen/lib/code/entity.py
index 9b976ef6..6616c8d7 100644
--- a/codegen/lib/code/entity.py
+++ b/codegen/lib/code/entity.py
@@ -11,7 +11,8 @@ def generate_entity_metadata(burger_entity_data: dict, mappings: Mappings):
# TODO: auto generate this and use it for generating the EntityDataValue enum
metadata_types = [
{'name': 'Byte', 'type': 'u8'},
- {'name': 'Int', 'type': 'i32'},
+ {'name': 'Int', 'type': 'i32', 'var': True},
+ {'name': 'Long', 'type': 'i64'},
{'name': 'Float', 'type': 'f32'},
{'name': 'String', 'type': 'String'},
{'name': 'Component', 'type': 'Component'},
@@ -23,11 +24,11 @@ def generate_entity_metadata(burger_entity_data: dict, mappings: Mappings):
{'name': 'OptionalBlockPos', 'type': 'Option<BlockPos>'},
{'name': 'Direction', 'type': 'Direction'},
{'name': 'OptionalUuid', 'type': 'Option<Uuid>'},
- {'name': 'OptionalBlockState', 'type': 'Option<BlockState>'},
+ {'name': 'BlockState', 'type': 'BlockState'},
{'name': 'CompoundTag', 'type': 'azalea_nbt::Tag'},
{'name': 'Particle', 'type': 'Particle'},
{'name': 'VillagerData', 'type': 'VillagerData'},
- {'name': 'OptionalUnsignedInt', 'type': 'Option<u32>'},
+ {'name': 'OptionalUnsignedInt', 'type': 'OptionalUnsignedInt'},
{'name': 'Pose', 'type': 'Pose'},
{'name': 'CatVariant', 'type': 'azalea_registry::CatVariant'},
{'name': 'FrogVariant', 'type': 'azalea_registry::FrogVariant'},
@@ -40,7 +41,8 @@ def generate_entity_metadata(burger_entity_data: dict, mappings: Mappings):
code.append("// Don't change it manually!")
code.append('')
code.append('#![allow(clippy::clone_on_copy, clippy::derivable_impls)]')
- code.append('use super::{EntityDataValue, Rotations, VillagerData, Pose};')
+ code.append(
+ 'use super::{EntityDataValue, Rotations, VillagerData, OptionalUnsignedInt, Pose};')
code.append('use azalea_block::BlockState;')
code.append('use azalea_chat::Component;')
code.append('use azalea_core::{BlockPos, Direction, Particle, Slot};')
@@ -185,6 +187,8 @@ def generate_entity_metadata(burger_entity_data: dict, mappings: Mappings):
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:
@@ -200,11 +204,11 @@ def generate_entity_metadata(burger_entity_data: dict, mappings: Mappings):
elif type_name == 'OptionalUuid':
default = f'Some(uuid::uuid!({default}))' if default != 'Empty' else 'None'
elif type_name == 'OptionalUnsignedInt':
- default = f'Some({default})' if default != 'Empty' else 'None'
+ 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 == 'OptionalBlockState':
- default = f'Some({default})' if default != 'Empty' else 'None'
+ 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':
diff --git a/codegen/lib/code/language.py b/codegen/lib/code/language.py
new file mode 100644
index 00000000..d27dde81
--- /dev/null
+++ b/codegen/lib/code/language.py
@@ -0,0 +1,8 @@
+from lib.utils import get_dir_location
+import json
+
+LANGUAGE_DIR = get_dir_location('../azalea-language/src/en_us.json')
+
+def write_language(contents: dict):
+ with open(LANGUAGE_DIR, 'w') as f:
+ f.write(json.dumps(contents, indent=' ')) \ No newline at end of file
diff --git a/codegen/lib/code/packet.py b/codegen/lib/code/packet.py
index 4beccd35..48572aed 100755
--- a/codegen/lib/code/packet.py
+++ b/codegen/lib/code/packet.py
@@ -247,9 +247,10 @@ def burger_instruction_to_code(instructions: list[dict], index: int, generated_p
# figure out what kind of iterator it is
loop_instructions = next_next_instruction['instructions']
if len(loop_instructions) == 2:
- entry_type_rs, is_var, uses, extra_code = burger_type_to_rust_type(
+ entry_type_rs, is_var, value_uses, extra_code = burger_type_to_rust_type(
loop_instructions[1]['type'], None, loop_instructions[1], mappings, obfuscated_class_name)
field_type_rs = f'Vec<{entry_type_rs}>'
+ uses.update(value_uses)
elif len(loop_instructions) == 3:
is_map = loop_instructions[0]['type'].startswith(
'Map.Entry<')
diff --git a/codegen/lib/code/registry.py b/codegen/lib/code/registry.py
index c22eefe9..4df82c09 100755
--- a/codegen/lib/code/registry.py
+++ b/codegen/lib/code/registry.py
@@ -9,8 +9,45 @@ REGISTRIES_DIR = get_dir_location('../azalea-registry/src/lib.rs')
def generate_registries(registries: dict):
code = []
- code.append('use azalea_registry_macros::registry;')
- code.append('')
+ code.append('''// This file is automatically generated in codegen/lib/code/registry.py
+
+use azalea_buf::{BufReadError, McBufReadable, McBufVarReadable, McBufVarWritable, McBufWritable};
+use azalea_registry_macros::registry;
+use std::io::{Cursor, Write};
+
+pub trait Registry
+where
+ Self: Sized,
+{
+ fn from_u32(value: u32) -> Option<Self>;
+ fn to_u32(&self) -> u32;
+}
+
+/// A registry that might not be present. This is transmitted as a single
+/// varint in the protocol.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct OptionalRegistry<T: Registry>(Option<T>);
+
+impl<T: Registry> McBufReadable for OptionalRegistry<T> {
+ fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
+ Ok(OptionalRegistry(match u32::var_read_from(buf)? {
+ 0 => None,
+ value => Some(
+ T::from_u32(value - 1)
+ .ok_or(BufReadError::UnexpectedEnumVariant { id: value as i32 })?,
+ ),
+ }))
+ }
+}
+impl<T: Registry> McBufWritable for OptionalRegistry<T> {
+ fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
+ match &self.0 {
+ None => 0u32.var_write_into(buf),
+ Some(value) => (value.to_u32() + 1).var_write_into(buf),
+ }
+ }
+}
+''')
for registry_name, registry in registries.items():
# registry!(Block, {
diff --git a/codegen/lib/code/shapes.py b/codegen/lib/code/shapes.py
index 83521dac..06170552 100755
--- a/codegen/lib/code/shapes.py
+++ b/codegen/lib/code/shapes.py
@@ -7,8 +7,8 @@ COLLISION_BLOCKS_RS_DIR = get_dir_location(
'../azalea-physics/src/collision/blocks.rs')
-def generate_block_shapes(blocks: dict, shapes: dict, block_states_report, block_datas_burger, mappings: Mappings):
- blocks, shapes = simplify_shapes(blocks, shapes)
+def generate_block_shapes(blocks: dict, shapes: dict, aabbs: dict, block_states_report, block_datas_burger, mappings: Mappings):
+ blocks, shapes = simplify_shapes(blocks, shapes, aabbs)
code = generate_block_shapes_code(
blocks, shapes, block_states_report, block_datas_burger, mappings)
@@ -16,33 +16,54 @@ def generate_block_shapes(blocks: dict, shapes: dict, block_states_report, block
f.write(code)
-def simplify_shapes(blocks: dict, shapes: dict):
- shape_to_new_id = {}
+def simplify_shapes(blocks: dict, shapes: dict, aabbs: dict):
new_id_increment = 0
new_shapes = {}
old_id_to_new_id = {}
- for shape_id, shape in sorted(shapes.items(), key=lambda shape: int(shape[0])):
- # tuples are hashable
- shape_as_tuple = tuple(map(tuple, shape))
- if shape_as_tuple not in shape_to_new_id:
- shape_to_new_id[shape_as_tuple] = new_id_increment
- old_id_to_new_id[shape_id] = new_id_increment
- new_shapes[new_id_increment] = shape
- new_id_increment += 1
- else:
- old_id_to_new_id[shape_id] = shape_to_new_id[shape_as_tuple]
+ old_id_to_new_id[None] = 0
+ new_shapes[0] = ()
+ new_id_increment += 1
+
+ used_shape_ids = set()
+ # determine the used shape ids
+ for block_id, block_data in blocks.items():
+ block_id = block_id.split(':')[-1]
+ block_shapes = [state.get('collision_shape')
+ for state in block_data['states'].values()]
+ for s in block_shapes:
+ used_shape_ids.add(s)
+
+ for shape_id, shape in enumerate(shapes):
+ if shape_id not in used_shape_ids: continue
+ # pixlyzer gives us shapes as an index or list of indexes into the
+ # aabbs list
+ # and aabbs look like { "from": number or [x, y, z], "to": (number or vec3) }
+ # convert them to [x1, y1, z1, x2, y2, z2]
+ shape = [shape] if isinstance(shape, int) else shape
+ shape = [aabbs[shape_aabb] for shape_aabb in shape]
+ shape = tuple([(
+ (tuple(part['from']) if isinstance(
+ part['from'], list) else ((part['from'],)*3))
+ + (tuple(part['to']) if isinstance(part['to'], list)
+ else ((part['to'],)*3))
+ ) for part in shape])
+
+ old_id_to_new_id[shape_id] = new_id_increment
+ new_shapes[new_id_increment] = shape
+ new_id_increment += 1
# now map the blocks to the new shape ids
- for block_id, shape_ids in blocks.items():
- if isinstance(shape_ids, int):
- blocks[block_id] = old_id_to_new_id[str(shape_ids)]
- else:
- blocks[block_id] = [old_id_to_new_id[str(shape_id)]
- for shape_id in shape_ids]
+ new_blocks = {}
+ for block_id, block_data in blocks.items():
+ block_id = block_id.split(':')[-1]
+ block_shapes = [state.get('collision_shape')
+ for state in block_data['states'].values()]
+ new_blocks[block_id] = [old_id_to_new_id[shape_id]
+ for shape_id in block_shapes]
- return blocks, new_shapes
+ return new_blocks, new_shapes
def generate_block_shapes_code(blocks: dict, shapes: dict, block_states_report, block_datas_burger, mappings: Mappings):
@@ -116,7 +137,7 @@ def generate_code_for_shape(shape_id: str, parts: list[list[float]]):
code = ''
code += f'static SHAPE{shape_id}: Lazy<VoxelShape> = Lazy::new(|| {{'
steps = []
- if parts == []:
+ if parts == ():
steps.append('collision::empty_shape()')
else:
steps.append(f'collision::box_shape({make_arguments(parts[0])})')
diff --git a/codegen/lib/code/utils.py b/codegen/lib/code/utils.py
index 66b18eed..5550cdb2 100755
--- a/codegen/lib/code/utils.py
+++ b/codegen/lib/code/utils.py
@@ -63,6 +63,12 @@ def burger_type_to_rust_type(burger_type, field_name: Optional[str] = None, inst
elif burger_type == 'metadata':
field_type_rs = 'EntityMetadata'
uses.add('azalea_entity::EntityMetadata')
+ elif burger_type == 'bitset':
+ if instruction:
+ length = instruction['length']
+ field_type_rs = f'todo!("fixed bitset of length {length}")'
+ else:
+ field_type_rs = 'todo!("fixed bitset")'
elif burger_type == 'abstract':
field_type_rs = 'todo!()'
elif burger_type == 'enum':