From 5fe6ac7adf92850b0996868a4bb4bf93883a8f5c Mon Sep 17 00:00:00 2001 From: mat Date: Sat, 7 May 2022 18:34:55 -0500 Subject: rename data-code-generator to code-generator --- code-generator/packetcodegen.py | 169 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 code-generator/packetcodegen.py (limited to 'code-generator/packetcodegen.py') diff --git a/code-generator/packetcodegen.py b/code-generator/packetcodegen.py new file mode 100644 index 00000000..59a48535 --- /dev/null +++ b/code-generator/packetcodegen.py @@ -0,0 +1,169 @@ +from utils import to_snake_case, to_camel_case +from mappings import Mappings +import os + + +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' + uses.add('azalea_chat::component::Component') + elif burger_type == 'identifier': + field_type_rs = 'ResourceLocation' + uses.add('azalea_core::resource_location::ResourceLocation') + elif burger_type == 'uuid': + field_type_rs = 'Uuid' + uses.add('uuid::Uuid') + elif burger_type == 'position': + field_type_rs = 'BlockPos' + uses.add('azalea_core::BlockPos') + elif burger_type == 'nbtcompound': + field_type_rs = 'azalea_nbt::Tag' + elif burger_type == 'itemstack': + field_type_rs = 'Slot' + uses.add('azalea_core::Slot') + elif burger_type == 'metadata': + field_type_rs = 'EntityMetadata' + uses.add('crate::mc_buf::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 write_packet_file(state, packet_name_snake_case, code): + with open(f'../azalea-protocol/src/packets/{state}/{packet_name_snake_case}.rs', 'w') as f: + f.write(code) + + +def generate(burger_packets, mappings: Mappings, target_packet_id, target_packet_direction, target_packet_state): + for packet in burger_packets.values(): + if packet['id'] != target_packet_id: + continue + + direction = packet['direction'].lower() # serverbound or clientbound + state = {'PLAY': 'game'}.get(packet['state'], packet['state'].lower()) + + if state != target_packet_state or direction != target_packet_direction: + continue + + generated_packet_code = [] + uses = set() + generated_packet_code.append( + f'#[derive(Clone, Debug, {to_camel_case(state)}Packet)]') + uses.add(f'packet_macros::{to_camel_case(state)}Packet') + + obfuscated_class_name = packet['class'].split('.')[0] + class_name = mappings.get_class( + obfuscated_class_name).split('.')[-1].split('$')[0] + + 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, instruction_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},') + uses.update(instruction_uses) + else: + generated_packet_code.append(f'// TODO: {instruction}') + continue + + generated_packet_code.append('}') + + if uses: + # empty line before the `use` statements + generated_packet_code.insert(0, '') + for use in uses: + generated_packet_code.insert(0, f'use {use};') + + print(generated_packet_code) + write_packet_file(state, to_snake_case(class_name), + '\n'.join(generated_packet_code)) + print() + + mod_rs_dir = f'../azalea-protocol/src/packets/{state}/mod.rs' + with open(mod_rs_dir, 'r') as f: + mod_rs = f.read().splitlines() + + pub_mod_line = f'pub mod {to_snake_case(class_name)};' + if pub_mod_line not in mod_rs: + mod_rs.insert(0, pub_mod_line) + packet_mod_rs_line = f' {hex(packet["id"])}: {to_snake_case(class_name)}::{to_camel_case(class_name)},' + + in_serverbound = False + in_clientbound = False + for i, line in enumerate(mod_rs): + if line.strip() == 'Serverbound => {': + in_serverbound = True + continue + elif line.strip() == 'Clientbound => {': + in_clientbound = True + continue + elif line.strip() in ('}', '},'): + if (in_serverbound and direction == 'serverbound') or (in_clientbound and direction == 'clientbound'): + mod_rs.insert(i, packet_mod_rs_line) + break + in_serverbound = in_clientbound = False + continue + + if line.strip() == '' or line.strip().startswith('//') or (not in_serverbound and direction == 'serverbound') or (not in_clientbound and direction == 'clientbound'): + continue + + line_packet_id_hex = line.strip().split(':')[0] + assert line_packet_id_hex.startswith('0x') + line_packet_id = int(line_packet_id_hex[2:], 16) + if line_packet_id > packet['id']: + mod_rs.insert(i, packet_mod_rs_line) + break + + with open(mod_rs_dir, 'w') as f: + f.write('\n'.join(mod_rs)) -- cgit v1.2.3 From e53ef8b0ddd46b3a85e597e7da57139960304e35 Mon Sep 17 00:00:00 2001 From: mat Date: Sat, 7 May 2022 19:46:06 -0500 Subject: update advancements packet --- azalea-client/src/connect.rs | 7 +- azalea-protocol/packet-macros/src/lib.rs | 2 +- azalea-protocol/src/mc_buf/read.rs | 13 +++- azalea-protocol/src/mc_buf/write.rs | 14 +++- .../game/clientbound_update_advancements_packet.rs | 90 ++++++++++++++++++++++ azalea-protocol/src/packets/game/mod.rs | 2 + code-generator/packetcodegen.py | 1 + 7 files changed, 124 insertions(+), 5 deletions(-) create mode 100644 azalea-protocol/src/packets/game/clientbound_update_advancements_packet.rs (limited to 'code-generator/packetcodegen.py') diff --git a/azalea-client/src/connect.rs b/azalea-client/src/connect.rs index cd6891c0..a73e0146 100755 --- a/azalea-client/src/connect.rs +++ b/azalea-client/src/connect.rs @@ -244,10 +244,10 @@ impl Client { println!("Got add entity packet {:?}", p); } GamePacket::ClientboundSetEntityDataPacket(p) => { - println!("Got set entity data packet {:?}", p); + // println!("Got set entity data packet {:?}", p); } GamePacket::ClientboundUpdateAttributesPacket(p) => { - println!("Got update attributes packet {:?}", p); + // println!("Got update attributes packet {:?}", p); } GamePacket::ClientboundEntityVelocityPacket(p) => { println!("Got entity velocity packet {:?}", p); @@ -279,6 +279,9 @@ impl Client { GamePacket::ClientboundTeleportEntityPacket(p) => { println!("Got teleport entity packet {:?}", p); } + GamePacket::ClientboundUpdateAdvancementsPacket(p) => { + println!("Got update advancements packet {:?}", p); + } _ => panic!("Unexpected packet {:?}", packet), } println!(); diff --git a/azalea-protocol/packet-macros/src/lib.rs b/azalea-protocol/packet-macros/src/lib.rs index a25492c6..35bf8b9b 100755 --- a/azalea-protocol/packet-macros/src/lib.rs +++ b/azalea-protocol/packet-macros/src/lib.rs @@ -72,7 +72,7 @@ fn create_impl_mcbufreadable(ident: &Ident, data: &Data) -> proc_macro2::TokenSt impl crate::mc_buf::McBufReadable for #ident { fn read_into(buf: &mut impl std::io::Read) -> Result { - let id = buf.read_varint()?; + let id = crate::mc_buf::McBufVarReadable::var_read_into(buf)?; match id { #match_contents _ => Err(format!("Unknown enum variant {}", id)), diff --git a/azalea-protocol/src/mc_buf/read.rs b/azalea-protocol/src/mc_buf/read.rs index e67cfa3c..991bf53b 100755 --- a/azalea-protocol/src/mc_buf/read.rs +++ b/azalea-protocol/src/mc_buf/read.rs @@ -6,7 +6,7 @@ use azalea_core::{ }; use byteorder::{ReadBytesExt, WriteBytesExt, BE}; use serde::Deserialize; -use std::io::Read; +use std::{collections::HashMap, hash::Hash, io::Read}; use tokio::io::{AsyncRead, AsyncReadExt}; use uuid::Uuid; @@ -294,6 +294,17 @@ impl McBufReadable for Vec { } } +impl McBufReadable for HashMap { + default fn read_into(buf: &mut impl Read) -> Result { + let length = buf.read_varint()? as usize; + let mut contents = HashMap::with_capacity(length); + for _ in 0..length { + contents.insert(K::read_into(buf)?, V::read_into(buf)?); + } + Ok(contents) + } +} + impl McBufReadable for Vec { fn read_into(buf: &mut impl Read) -> Result { buf.read_byte_array() diff --git a/azalea-protocol/src/mc_buf/write.rs b/azalea-protocol/src/mc_buf/write.rs index 10271bf8..66f129f1 100755 --- a/azalea-protocol/src/mc_buf/write.rs +++ b/azalea-protocol/src/mc_buf/write.rs @@ -5,7 +5,7 @@ use azalea_core::{ serializable_uuid::SerializableUuid, BlockPos, Direction, Slot, }; use byteorder::{BigEndian, WriteBytesExt}; -use std::io::Write; +use std::{collections::HashMap, io::Write}; use uuid::Uuid; pub trait Writable: Write { @@ -174,6 +174,18 @@ impl McBufWritable for Vec { } } +impl McBufWritable for HashMap { + default fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> { + u32::var_write_into(&(self.len() as u32), buf)?; + for (key, value) in self { + key.write_into(buf)?; + value.write_into(buf)?; + } + + Ok(()) + } +} + impl McBufWritable for Vec { fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> { buf.write_byte_array(self) diff --git a/azalea-protocol/src/packets/game/clientbound_update_advancements_packet.rs b/azalea-protocol/src/packets/game/clientbound_update_advancements_packet.rs new file mode 100644 index 00000000..fe2c226d --- /dev/null +++ b/azalea-protocol/src/packets/game/clientbound_update_advancements_packet.rs @@ -0,0 +1,90 @@ +use crate::packets::{McBufReadable, McBufWritable}; +use azalea_chat::component::Component; +use azalea_core::{resource_location::ResourceLocation, Slot}; +use packet_macros::{GamePacket, McBufReadable, McBufWritable}; +use std::{ + collections::HashMap, + io::{Read, Write}, +}; + +#[derive(Clone, Debug, GamePacket)] +pub struct ClientboundUpdateAdvancementsPacket { + pub reset: bool, + pub added: HashMap, + pub removed: Vec, + pub progress: HashMap, +} + +#[derive(Clone, Debug, McBufReadable, McBufWritable)] +pub struct Advancement { + parent_id: Option, + display: Option, + // rewards: AdvancementRewards.EMPTY, + criteria: HashMap, + requirements: Vec>, + // requirements_strategy: RequirementsStrategy.AND +} + +#[derive(Clone, Debug, McBufReadable, McBufWritable)] +pub struct DisplayInfo { + pub title: Component, + pub description: Component, + pub icon: Slot, + pub frame: FrameType, + pub flags: DisplayFlags, + pub background: Option, + pub x: f32, + pub y: f32, +} + +#[derive(Clone, Debug)] +pub struct DisplayFlags { + pub background: bool, + pub show_toast: bool, + pub hidden: bool, +} + +impl McBufReadable for DisplayFlags { + fn read_into(buf: &mut impl Read) -> Result { + let data = u32::read_into(buf)?; + Ok(DisplayFlags { + background: (data & 0b1) != 0, + show_toast: (data & 0b10) != 0, + hidden: (data & 0b100) != 0, + }) + } +} + +impl McBufWritable for DisplayFlags { + fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> { + let mut data = 0; + if self.background { + data |= 0b1; + } + if self.show_toast { + data |= 0b10; + } + if self.hidden { + data |= 0b100; + } + u32::write_into(&data, buf) + } +} + +#[derive(Clone, Debug, Copy, McBufReadable, McBufWritable)] +pub enum FrameType { + Task = 0, + Challenge = 1, + Goal = 2, +} + +// nothing is written here +#[derive(Clone, Debug, McBufReadable, McBufWritable)] +pub struct Criterion {} + +pub type AdvancementProgress = HashMap; + +#[derive(Clone, Debug, McBufReadable, McBufWritable)] +pub struct CriterionProgress { + date: Option, +} diff --git a/azalea-protocol/src/packets/game/mod.rs b/azalea-protocol/src/packets/game/mod.rs index d3ea7281..db1c0b11 100755 --- a/azalea-protocol/src/packets/game/mod.rs +++ b/azalea-protocol/src/packets/game/mod.rs @@ -25,6 +25,7 @@ pub mod clientbound_set_experience_packet; pub mod clientbound_set_health_packet; pub mod clientbound_set_time_packet; pub mod clientbound_teleport_entity_packet; +pub mod clientbound_update_advancements_packet; pub mod clientbound_update_attributes_packet; pub mod clientbound_update_recipes_packet; pub mod clientbound_update_tags_packet; @@ -67,6 +68,7 @@ declare_state_packets!( 0x52: clientbound_set_health_packet::ClientboundSetHealthPacket, 0x59: clientbound_set_time_packet::ClientboundSetTimePacket, 0x62: clientbound_teleport_entity_packet::ClientboundTeleportEntityPacket, + 0x63: clientbound_update_advancements_packet::ClientboundUpdateAdvancementsPacket, 0x64: clientbound_update_attributes_packet::ClientboundUpdateAttributesPacket, 0x66: clientbound_update_recipes_packet::ClientboundUpdateRecipesPacket, 0x67: clientbound_update_tags_packet::ClientboundUpdateTagsPacket, diff --git a/code-generator/packetcodegen.py b/code-generator/packetcodegen.py index 59a48535..bd8f0b3b 100644 --- a/code-generator/packetcodegen.py +++ b/code-generator/packetcodegen.py @@ -98,6 +98,7 @@ def generate(burger_packets, mappings: Mappings, target_packet_id, target_packet if instruction['operation'] == 'write': obfuscated_field_name = instruction['field'] if '.' in obfuscated_field_name or ' ' in obfuscated_field_name or '(' in obfuscated_field_name: + generated_packet_code.append(f'// TODO: {instruction}') continue field_name = mappings.get_field( obfuscated_class_name, obfuscated_field_name) -- cgit v1.2.3 From d8049a5d0c9a2c79d576785dc1681ae60e44a04b Mon Sep 17 00:00:00 2001 From: mat Date: Sat, 7 May 2022 20:00:59 -0500 Subject: move entity and rotate head packets --- azalea-client/src/connect.rs | 6 ++++++ .../src/packets/game/clientbound_move_entity_packet.rs | 11 +++++++++++ .../src/packets/game/clientbound_rotate_head_packet.rs | 8 ++++++++ azalea-protocol/src/packets/game/mod.rs | 4 ++++ code-generator/packetcodegen.py | 5 +++-- 5 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 azalea-protocol/src/packets/game/clientbound_move_entity_packet.rs create mode 100644 azalea-protocol/src/packets/game/clientbound_rotate_head_packet.rs (limited to 'code-generator/packetcodegen.py') diff --git a/azalea-client/src/connect.rs b/azalea-client/src/connect.rs index a73e0146..0fc7273b 100755 --- a/azalea-client/src/connect.rs +++ b/azalea-client/src/connect.rs @@ -282,6 +282,12 @@ impl Client { GamePacket::ClientboundUpdateAdvancementsPacket(p) => { println!("Got update advancements packet {:?}", p); } + GamePacket::ClientboundRotateHeadPacket(p) => { + println!("Got rotate head packet {:?}", p); + } + GamePacket::ClientboundMoveEntityPacket(p) => { + println!("Got move entity packet {:?}", p); + } _ => panic!("Unexpected packet {:?}", packet), } println!(); diff --git a/azalea-protocol/src/packets/game/clientbound_move_entity_packet.rs b/azalea-protocol/src/packets/game/clientbound_move_entity_packet.rs new file mode 100644 index 00000000..285a45a4 --- /dev/null +++ b/azalea-protocol/src/packets/game/clientbound_move_entity_packet.rs @@ -0,0 +1,11 @@ +use packet_macros::GamePacket; + +#[derive(Clone, Debug, GamePacket)] +pub struct ClientboundMoveEntityPacket { + #[var] + pub entity_id: u32, + pub y_rot: i16, + pub x_rot: i16, + pub z_rot: i16, + pub on_ground: bool, +} diff --git a/azalea-protocol/src/packets/game/clientbound_rotate_head_packet.rs b/azalea-protocol/src/packets/game/clientbound_rotate_head_packet.rs new file mode 100644 index 00000000..d423885d --- /dev/null +++ b/azalea-protocol/src/packets/game/clientbound_rotate_head_packet.rs @@ -0,0 +1,8 @@ +use packet_macros::GamePacket; + +#[derive(Clone, Debug, GamePacket)] +pub struct ClientboundRotateHeadPacket { + #[var] + pub entity_id: u32, + pub y_head_rot: i8, +} diff --git a/azalea-protocol/src/packets/game/mod.rs b/azalea-protocol/src/packets/game/mod.rs index db1c0b11..0f7d00d0 100755 --- a/azalea-protocol/src/packets/game/mod.rs +++ b/azalea-protocol/src/packets/game/mod.rs @@ -12,10 +12,12 @@ pub mod clientbound_initialize_border_packet; pub mod clientbound_level_chunk_with_light_packet; pub mod clientbound_light_update_packet; pub mod clientbound_login_packet; +pub mod clientbound_move_entity_packet; pub mod clientbound_player_abilities_packet; pub mod clientbound_player_info_packet; pub mod clientbound_player_position_packet; pub mod clientbound_recipe_packet; +pub mod clientbound_rotate_head_packet; pub mod clientbound_set_carried_item_packet; pub mod clientbound_set_chunk_cache_center; pub mod clientbound_set_default_spawn_position_packet; @@ -53,10 +55,12 @@ declare_state_packets!( 0x22: clientbound_level_chunk_with_light_packet::ClientboundLevelChunkWithLightPacket, 0x25: clientbound_light_update_packet::ClientboundLightUpdatePacket, 0x26: clientbound_login_packet::ClientboundLoginPacket, + 0x29: clientbound_move_entity_packet::ClientboundMoveEntityPacket, 0x32: clientbound_player_abilities_packet::ClientboundPlayerAbilitiesPacket, 0x36: clientbound_player_info_packet::ClientboundPlayerInfoPacket, 0x38: clientbound_player_position_packet::ClientboundPlayerPositionPacket, 0x39: clientbound_recipe_packet::ClientboundRecipePacket, + 0x3e: clientbound_rotate_head_packet::ClientboundRotateHeadPacket, 0x48: clientbound_set_carried_item_packet::ClientboundSetCarriedItemPacket, 0x49: clientbound_set_chunk_cache_center::ClientboundSetChunkCacheCenterPacket, 0x4a: clientbound_update_view_distance_packet::ClientboundUpdateViewDistancePacket, diff --git a/code-generator/packetcodegen.py b/code-generator/packetcodegen.py index bd8f0b3b..fbb38eeb 100644 --- a/code-generator/packetcodegen.py +++ b/code-generator/packetcodegen.py @@ -87,7 +87,7 @@ def generate(burger_packets, mappings: Mappings, target_packet_id, target_packet f'#[derive(Clone, Debug, {to_camel_case(state)}Packet)]') uses.add(f'packet_macros::{to_camel_case(state)}Packet') - obfuscated_class_name = packet['class'].split('.')[0] + obfuscated_class_name = packet['class'].split('.')[0].split('$')[0] class_name = mappings.get_class( obfuscated_class_name).split('.')[-1].split('$')[0] @@ -103,7 +103,8 @@ def generate(burger_packets, mappings: Mappings, target_packet_id, target_packet field_name = mappings.get_field( obfuscated_class_name, obfuscated_field_name) if not field_name: - generated_packet_code.append(f'// TODO: {instruction}') + generated_packet_code.append( + f'// TODO: unknown field {instruction}') continue field_type = instruction['type'] -- cgit v1.2.3