mirror of
https://github.com/mat-1/azalea.git
synced 2025-08-02 06:16:04 +00:00
ClientboundSetEquipmentPacket
This commit is contained in:
parent
69e1125ecb
commit
d0fc7d0eff
8 changed files with 118 additions and 37 deletions
|
@ -4951,4 +4951,4 @@ make_block_states! {
|
|||
reinforced_deepslate => BlockBehavior::default(), {
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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,
|
||||
|
|
|
@ -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.")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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: `(.*)`.\*'
|
||||
|
|
Loading…
Add table
Reference in a new issue