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

ClientboundSetEquipmentPacket

This commit is contained in:
mat 2022-06-17 16:27:58 -05:00
parent 69e1125ecb
commit d0fc7d0eff
8 changed files with 118 additions and 37 deletions

View file

@ -4951,4 +4951,4 @@ make_block_states! {
reinforced_deepslate => BlockBehavior::default(), {
},
}
}
}

View file

@ -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::<u32, BlockState>(state_id)
}
/// 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::<u32, BlockState>(state_id)
}
#[inline]
pub fn is_valid_state(state_id: u32) -> bool {
state_id <= Self::max_state()
}
#[inline]
pub fn is_valid_state(state_id: u32) -> bool {
state_id <= Self::max_state()
}
}
impl TryFrom<u32> for BlockState {
type Error = ();
type Error = ();
/// Safely converts a state id to a block state.
fn try_from(state_id: u32) -> Result<Self, Self::Error> {
if Self::is_valid_state(state_id) {
Ok(unsafe { Self::from_u32_unsafe(state_id) })
} else {
Err(())
}
}
/// Safely converts a state id to a block state.
fn try_from(state_id: u32) -> Result<Self, Self::Error> {
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());
}
}

View file

@ -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<Self, String> {
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<Self> {
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,
}
}
}

View file

@ -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,

View file

@ -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.")
}
}

View file

@ -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()

View file

@ -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')

View file

@ -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: `(.*)`.\*'