From 74c3ae52f84d988b8bf3f0affe143d2cd2d8143a Mon Sep 17 00:00:00 2001 From: mat Date: Thu, 16 Jun 2022 23:38:51 -0500 Subject: azalea-world uses azalea-block --- azalea-world/src/bit_storage.rs | 6 ++++++ azalea-world/src/lib.rs | 21 +++++++++++++++------ 2 files changed, 21 insertions(+), 6 deletions(-) (limited to 'azalea-world/src') diff --git a/azalea-world/src/bit_storage.rs b/azalea-world/src/bit_storage.rs index aba52aef..c69cb216 100644 --- a/azalea-world/src/bit_storage.rs +++ b/azalea-world/src/bit_storage.rs @@ -188,6 +188,12 @@ impl BitStorage { let bit_index = (index - cell_index * self.values_per_long as usize) * self.bits; *cell = *cell & !(self.mask << bit_index) | (value & self.mask) << bit_index; } + + /// The number of entries. + #[inline] + pub fn size(&self) -> usize { + self.size + } } #[cfg(test)] diff --git a/azalea-world/src/lib.rs b/azalea-world/src/lib.rs index 766c61f0..8777c0a3 100644 --- a/azalea-world/src/lib.rs +++ b/azalea-world/src/lib.rs @@ -8,6 +8,7 @@ use azalea_core::{BlockPos, ChunkBlockPos, ChunkPos, ChunkSectionBlockPos}; use azalea_protocol::mc_buf::{McBufReadable, McBufWritable}; pub use bit_storage::BitStorage; use palette::PalettedContainer; +use azalea_block::BlockState; use std::{ io::{Read, Write}, ops::{Index, IndexMut}, @@ -57,7 +58,7 @@ impl World { self.storage.view_center = *pos; } - pub fn get_block_state(&self, pos: &BlockPos) -> Option { + pub fn get_block_state(&self, pos: &BlockPos) -> Option { self.storage.get_block_state(pos, self.min_y) } } @@ -122,7 +123,7 @@ impl ChunkStorage { && (chunk_pos.z - self.view_center.z).unsigned_abs() <= self.chunk_radius } - pub fn get_block_state(&self, pos: &BlockPos, min_y: i32) -> Option { + pub fn get_block_state(&self, pos: &BlockPos, min_y: i32) -> Option { let chunk_pos = ChunkPos::from(pos); println!("chunk_pos {:?} block_pos {:?}", chunk_pos, pos); let chunk = &self[&chunk_pos]; @@ -175,7 +176,7 @@ impl Chunk { (y.div_floor(16) - min_section_index) as u32 } - pub fn get(&self, pos: &ChunkBlockPos, min_y: i32) -> u32 { + pub fn get(&self, pos: &ChunkBlockPos, min_y: i32) -> BlockState { let section_index = self.section_index(pos.y, min_y); // TODO: make sure the section exists let section = &self.sections[section_index as usize]; @@ -210,6 +211,14 @@ impl McBufReadable for Section { // "A section has more blocks than what should be possible. This is a bug!" // ); let states = PalettedContainer::read_with_type(buf, &PalettedContainerType::BlockStates)?; + for i in 0..states.storage.size() { + if !BlockState::is_valid_state(states.storage.get(i) as u32) { + return Err(format!( + "Invalid block state {} (index {}) found in section.", + states.storage.get(i), i + )); + } + } let biomes = PalettedContainer::read_with_type(buf, &PalettedContainerType::Biomes)?; Ok(Section { block_count, @@ -229,9 +238,9 @@ impl McBufWritable for Section { } impl Section { - // TODO: return a BlockState instead of a u32 - fn get(&self, pos: ChunkSectionBlockPos) -> u32 { + fn get(&self, pos: ChunkSectionBlockPos) -> BlockState { + // TODO: use the unsafe method and do the check earlier self.states - .get(pos.x as usize, pos.y as usize, pos.z as usize) + .get(pos.x as usize, pos.y as usize, pos.z as usize).try_into().expect("Invalid block state.") } } -- cgit v1.2.3 From 69e1125ecbb3e695125b8e65deba3e3f7be41b70 Mon Sep 17 00:00:00 2001 From: mat Date: Fri, 17 Jun 2022 15:59:27 -0500 Subject: Slightly improve bit storage --- .vscode/settings.json | 2 +- azalea-world/src/bit_storage.rs | 12 ++++++------ azalea-world/src/lib.rs | 4 ++++ bot/src/main.rs | 2 +- 4 files changed, 12 insertions(+), 8 deletions(-) (limited to 'azalea-world/src') diff --git a/.vscode/settings.json b/.vscode/settings.json index b0d07499..3b614348 100755 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,3 @@ { - "editor.formatOnSave": false + "editor.formatOnSave": true } \ No newline at end of file diff --git a/azalea-world/src/bit_storage.rs b/azalea-world/src/bit_storage.rs index c69cb216..0dc81f9a 100644 --- a/azalea-world/src/bit_storage.rs +++ b/azalea-world/src/bit_storage.rs @@ -77,8 +77,8 @@ pub struct BitStorage { mask: u64, size: usize, values_per_long: u8, - divide_mul: i32, - divide_add: i32, + divide_mul: u64, + divide_add: u64, divide_shift: i32, } @@ -138,16 +138,16 @@ impl BitStorage { mask, size, values_per_long: values_per_long as u8, - divide_mul, - divide_add, + divide_mul: divide_mul as u32 as u64, + divide_add: divide_add as u32 as u64, divide_shift, }) } pub fn cell_index(&self, index: u64) -> usize { // as unsigned wrap - let first = self.divide_mul as u32 as u64; - let second = self.divide_add as u64; + let first = self.divide_mul; + let second = self.divide_add; (((index * first) + second) >> 32 >> self.divide_shift) .try_into() diff --git a/azalea-world/src/lib.rs b/azalea-world/src/lib.rs index 8777c0a3..26566416 100644 --- a/azalea-world/src/lib.rs +++ b/azalea-world/src/lib.rs @@ -205,12 +205,15 @@ pub struct Section { impl McBufReadable for Section { fn read_into(buf: &mut impl Read) -> Result { let block_count = u16::read_into(buf)?; + // this is commented out because the vanilla server is wrong // assert!( // block_count <= 16 * 16 * 16, // "A section has more blocks than what should be possible. This is a bug!" // ); + let states = PalettedContainer::read_with_type(buf, &PalettedContainerType::BlockStates)?; + for i in 0..states.storage.size() { if !BlockState::is_valid_state(states.storage.get(i) as u32) { return Err(format!( @@ -219,6 +222,7 @@ impl McBufReadable for Section { )); } } + let biomes = PalettedContainer::read_with_type(buf, &PalettedContainerType::Biomes)?; Ok(Section { block_count, diff --git a/bot/src/main.rs b/bot/src/main.rs index 8ad74ec4..cd27ba5a 100644 --- a/bot/src/main.rs +++ b/bot/src/main.rs @@ -6,7 +6,7 @@ async fn main() { println!("Hello, world!"); // let address = "95.111.249.143:10000"; - let address = "localhost:65519"; + let address = "localhost:51028"; // let response = azalea_client::ping::ping_server(&address.try_into().unwrap()) // .await // .unwrap(); -- cgit v1.2.3 From d0fc7d0eff32687d7210b730584db2c3faa055ae Mon Sep 17 00:00:00 2001 From: mat Date: Fri, 17 Jun 2022 16:27:58 -0500 Subject: ClientboundSetEquipmentPacket --- azalea-block/src/blocks.rs | 2 +- azalea-block/src/lib.rs | 56 ++++++++-------- .../game/clientbound_set_equipment_packet.rs | 74 ++++++++++++++++++++++ azalea-protocol/src/packets/game/mod.rs | 2 + azalea-world/src/lib.rs | 9 ++- codegen/lib/code/packet.py | 9 +-- codegen/lib/code/utils.py | 5 +- codegen/lib/code/version.py | 2 +- 8 files changed, 120 insertions(+), 39 deletions(-) create mode 100644 azalea-protocol/src/packets/game/clientbound_set_equipment_packet.rs (limited to 'azalea-world/src') diff --git a/azalea-block/src/blocks.rs b/azalea-block/src/blocks.rs index b8d204fd..05973797 100644 --- a/azalea-block/src/blocks.rs +++ b/azalea-block/src/blocks.rs @@ -4951,4 +4951,4 @@ make_block_states! { reinforced_deepslate => BlockBehavior::default(), { }, } -} \ No newline at end of file +} diff --git a/azalea-block/src/lib.rs b/azalea-block/src/lib.rs index 95e8ce37..a6de1e92 100644 --- a/azalea-block/src/lib.rs +++ b/azalea-block/src/lib.rs @@ -7,41 +7,41 @@ pub use blocks::*; use std::mem; impl BlockState { - /// Transmutes a u32 to a block state. UB if the value is not a valid block - /// state. - #[inline] - pub unsafe fn from_u32_unsafe(state_id: u32) -> Self { - mem::transmute::(state_id) - } - - #[inline] - pub fn is_valid_state(state_id: u32) -> bool { - state_id <= Self::max_state() - } + /// Transmutes a u32 to a block state. UB if the value is not a valid block + /// state. + #[inline] + pub unsafe fn from_u32_unsafe(state_id: u32) -> Self { + mem::transmute::(state_id) + } + + #[inline] + pub fn is_valid_state(state_id: u32) -> bool { + state_id <= Self::max_state() + } } impl TryFrom for BlockState { - type Error = (); - - /// Safely converts a state id to a block state. - fn try_from(state_id: u32) -> Result { - if Self::is_valid_state(state_id) { - Ok(unsafe { Self::from_u32_unsafe(state_id) }) - } else { - Err(()) - } - } + type Error = (); + + /// Safely converts a state id to a block state. + fn try_from(state_id: u32) -> Result { + if Self::is_valid_state(state_id) { + Ok(unsafe { Self::from_u32_unsafe(state_id) }) + } else { + Err(()) + } + } } #[cfg(test)] mod tests { - use super::*; + use super::*; - #[test] - fn test_from_u32() { - assert_eq!(BlockState::try_from(0).unwrap(), BlockState::Air); + #[test] + fn test_from_u32() { + assert_eq!(BlockState::try_from(0).unwrap(), BlockState::Air); - assert!(BlockState::try_from(BlockState::max_state()).is_ok()); - assert!(BlockState::try_from(BlockState::max_state() + 1).is_err()); - } + assert!(BlockState::try_from(BlockState::max_state()).is_ok()); + assert!(BlockState::try_from(BlockState::max_state() + 1).is_err()); + } } diff --git a/azalea-protocol/src/packets/game/clientbound_set_equipment_packet.rs b/azalea-protocol/src/packets/game/clientbound_set_equipment_packet.rs new file mode 100644 index 00000000..3acbd58f --- /dev/null +++ b/azalea-protocol/src/packets/game/clientbound_set_equipment_packet.rs @@ -0,0 +1,74 @@ +use azalea_core::Slot; +use packet_macros::{GamePacket, McBuf}; + +use crate::mc_buf::{McBufReadable, McBufWritable}; + +#[derive(Clone, Debug, McBuf, GamePacket)] +pub struct ClientboundSetEquipmentPacket { + #[var] + pub entity: i32, + pub slots: EquipmentSlots, +} + +#[derive(Clone, Debug)] +pub struct EquipmentSlots { + pub slots: Vec<(EquipmentSlot, Slot)>, +} + +impl McBufReadable for EquipmentSlots { + fn read_into(buf: &mut impl std::io::Read) -> Result { + let mut slots = vec![]; + + loop { + let equipment_byte = u8::read_into(buf)?; + let equipment_slot = EquipmentSlot::from_byte(equipment_byte & 127) + .ok_or_else(|| format!("Invalid equipment slot byte {}", equipment_byte))?; + let item = Slot::read_into(buf)?; + slots.push((equipment_slot, item)); + if equipment_byte & 128 == 0 { + break; + }; + } + + Ok(EquipmentSlots { slots }) + } +} +impl McBufWritable for EquipmentSlots { + fn write_into(&self, buf: &mut impl std::io::Write) -> Result<(), std::io::Error> { + for i in 0..self.slots.len() { + let (equipment_slot, item) = &self.slots[i]; + let mut equipment_byte = *equipment_slot as u8; + if i != self.slots.len() - 1 { + equipment_byte |= 128; + } + equipment_byte.write_into(buf)?; + item.write_into(buf)?; + } + + Ok(()) + } +} + +#[derive(Clone, Debug, Copy, McBuf)] +pub enum EquipmentSlot { + MainHand = 0, + OffHand = 1, + Feet = 2, + Legs = 3, + Chest = 4, + Head = 5, +} + +impl EquipmentSlot { + pub fn from_byte(byte: u8) -> Option { + match byte { + 0 => Some(EquipmentSlot::MainHand), + 1 => Some(EquipmentSlot::OffHand), + 2 => Some(EquipmentSlot::Feet), + 3 => Some(EquipmentSlot::Legs), + 4 => Some(EquipmentSlot::Chest), + 5 => Some(EquipmentSlot::Head), + _ => None, + } + } +} diff --git a/azalea-protocol/src/packets/game/mod.rs b/azalea-protocol/src/packets/game/mod.rs index eee36788..c4435636 100755 --- a/azalea-protocol/src/packets/game/mod.rs +++ b/azalea-protocol/src/packets/game/mod.rs @@ -37,6 +37,7 @@ pub mod clientbound_set_default_spawn_position_packet; pub mod clientbound_set_display_chat_preview_packet; pub mod clientbound_set_entity_data_packet; pub mod clientbound_set_entity_link_packet; +pub mod clientbound_set_equipment_packet; pub mod clientbound_set_experience_packet; pub mod clientbound_set_health_packet; pub mod clientbound_set_time_packet; @@ -104,6 +105,7 @@ declare_state_packets!( 0x4b: clientbound_set_display_chat_preview_packet::ClientboundSetDisplayChatPreviewPacket, 0x4d: clientbound_set_entity_data_packet::ClientboundSetEntityDataPacket, 0x4f: clientbound_entity_velocity_packet::ClientboundEntityVelocityPacket, + 0x50: clientbound_set_equipment_packet::ClientboundSetEquipmentPacket, 0x51: clientbound_set_experience_packet::ClientboundSetExperiencePacket, 0x52: clientbound_set_health_packet::ClientboundSetHealthPacket, 0x59: clientbound_set_time_packet::ClientboundSetTimePacket, diff --git a/azalea-world/src/lib.rs b/azalea-world/src/lib.rs index 26566416..e651e455 100644 --- a/azalea-world/src/lib.rs +++ b/azalea-world/src/lib.rs @@ -4,11 +4,11 @@ mod bit_storage; mod palette; use crate::palette::PalettedContainerType; +use azalea_block::BlockState; use azalea_core::{BlockPos, ChunkBlockPos, ChunkPos, ChunkSectionBlockPos}; use azalea_protocol::mc_buf::{McBufReadable, McBufWritable}; pub use bit_storage::BitStorage; use palette::PalettedContainer; -use azalea_block::BlockState; use std::{ io::{Read, Write}, ops::{Index, IndexMut}, @@ -218,7 +218,8 @@ impl McBufReadable for Section { if !BlockState::is_valid_state(states.storage.get(i) as u32) { return Err(format!( "Invalid block state {} (index {}) found in section.", - states.storage.get(i), i + states.storage.get(i), + i )); } } @@ -245,6 +246,8 @@ impl Section { fn get(&self, pos: ChunkSectionBlockPos) -> BlockState { // TODO: use the unsafe method and do the check earlier self.states - .get(pos.x as usize, pos.y as usize, pos.z as usize).try_into().expect("Invalid block state.") + .get(pos.x as usize, pos.y as usize, pos.z as usize) + .try_into() + .expect("Invalid block state.") } } diff --git a/codegen/lib/code/packet.py b/codegen/lib/code/packet.py index 36e0ba0c..2aabf39a 100644 --- a/codegen/lib/code/packet.py +++ b/codegen/lib/code/packet.py @@ -1,6 +1,6 @@ -from .utils import burger_type_to_rust_type, write_packet_file -from ..utils import padded_hex, to_snake_case, to_camel_case -from ..mappings import Mappings +from lib.code.utils import burger_type_to_rust_type, write_packet_file +from lib.utils import padded_hex, to_snake_case, to_camel_case, get_dir_location +from lib.mappings import Mappings import os @@ -74,7 +74,8 @@ def generate_packet(burger_packets, mappings: Mappings, target_packet_id, target '\n'.join(generated_packet_code)) print() - mod_rs_dir = f'../azalea-protocol/src/packets/{state}/mod.rs' + mod_rs_dir = get_dir_location( + f'../azalea-protocol/src/packets/{state}/mod.rs') with open(mod_rs_dir, 'r') as f: mod_rs = f.read().splitlines() diff --git a/codegen/lib/code/utils.py b/codegen/lib/code/utils.py index 28a5ef3c..ecfff4fb 100644 --- a/codegen/lib/code/utils.py +++ b/codegen/lib/code/utils.py @@ -1,4 +1,5 @@ +from lib.utils import get_dir_location import os # utilities specifically for codegen @@ -67,9 +68,9 @@ def burger_type_to_rust_type(burger_type): 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: + with open(get_dir_location(f'../azalea-protocol/src/packets/{state}/{packet_name_snake_case}.rs'), 'w') as f: f.write(code) def fmt(): - os.system('cd .. && cargo fmt') + os.system(f'cd {get_dir_location("..")} && cargo fmt') diff --git a/codegen/lib/code/version.py b/codegen/lib/code/version.py index 4c8500be..511d30d1 100644 --- a/codegen/lib/code/version.py +++ b/codegen/lib/code/version.py @@ -1,6 +1,6 @@ +from lib.utils import get_dir_location import re import os -from lib.utils import get_dir_location README_DIR = get_dir_location('../README.md') VERSION_REGEX = r'\*Currently supported Minecraft version: `(.*)`.\*' -- cgit v1.2.3