diff --git a/azalea-protocol/src/packets/game/c_sound.rs b/azalea-protocol/src/packets/game/c_sound.rs index 771617698..8ec028a70 100755 --- a/azalea-protocol/src/packets/game/c_sound.rs +++ b/azalea-protocol/src/packets/game/c_sound.rs @@ -1,11 +1,13 @@ use azalea_buf::AzBuf; +use azalea_core::resource_location::ResourceLocation; use azalea_protocol_macros::ClientboundGamePacket; use azalea_registry::SoundEvent; #[derive(Clone, Debug, AzBuf, ClientboundGamePacket)] pub struct ClientboundSound { - pub sound: SoundEvent, + pub sound: azalea_registry::Holder, pub source: SoundSource, + // this can't be a BlockPos because it serializes differently :( pub x: i32, pub y: i32, pub z: i32, @@ -14,6 +16,12 @@ pub struct ClientboundSound { pub seed: u64, } +#[derive(Clone, Debug, AzBuf)] +pub struct CustomSound { + pub location: ResourceLocation, + pub fixed_range: Option, +} + #[derive(AzBuf, Clone, Copy, Debug)] pub enum SoundSource { Master = 0, @@ -27,3 +35,30 @@ pub enum SoundSource { Ambient = 8, Voice = 9, } + +#[cfg(test)] +mod tests { + use std::io::Cursor; + + use azalea_buf::AzaleaRead; + + use crate::packets::game::ClientboundSound; + + #[test] + fn test_read_write_custom_sound() { + let contents = [ + 0, 21, 109, 105, 110, 101, 99, 114, 97, 102, 116, 58, 97, 115, 102, 97, 115, 100, 102, + 115, 100, 102, 103, 0, 8, 0, 0, 0, 63, 255, 255, 254, 32, 0, 0, 0, 82, 66, 200, 0, 0, + 63, 128, 0, 0, 71, 94, 219, 133, 200, 13, 150, 31, + ]; + let mut buf = Cursor::new(contents.as_slice()); + let packet = ClientboundSound::azalea_read(&mut buf).unwrap(); + println!("{:?}", packet); + + assert_eq!(buf.position(), contents.len() as u64); + + let mut buf = Vec::new(); + packet.write(&mut buf).unwrap(); + assert_eq!(buf, contents); + } +} diff --git a/azalea-registry/src/lib.rs b/azalea-registry/src/lib.rs index ffead5b48..4a6df6aa0 100755 --- a/azalea-registry/src/lib.rs +++ b/azalea-registry/src/lib.rs @@ -90,7 +90,6 @@ pub enum HolderSet { contents: Vec, }, } - impl AzaleaRead for HolderSet { @@ -145,6 +144,55 @@ impl De } } +/// A reference to either a registry or a custom value (usually something with a +/// ResourceLocation). +pub enum Holder { + Reference(R), + Direct(Direct), +} +impl AzaleaRead for Holder { + fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result { + let id = u32::azalea_read_var(buf)?; + if id == 0 { + Ok(Self::Direct(Direct::azalea_read(buf)?)) + } else { + let Some(value) = R::from_u32(id - 1) else { + return Err(BufReadError::UnexpectedEnumVariant { + id: (id - 1) as i32, + }); + }; + Ok(Self::Reference(value)) + } + } +} +impl AzaleaWrite for Holder { + fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> { + match self { + Self::Reference(value) => (value.to_u32() + 1).azalea_write_var(buf), + Self::Direct(value) => { + 0u32.azalea_write_var(buf)?; + value.azalea_write(buf) + } + } + } +} +impl Debug for Holder { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Reference(value) => f.debug_tuple("Reference").field(value).finish(), + Self::Direct(value) => f.debug_tuple("Direct").field(value).finish(), + } + } +} +impl Clone for Holder { + fn clone(&self) -> Self { + match self { + Self::Reference(value) => Self::Reference(value.clone()), + Self::Direct(value) => Self::Direct(value.clone()), + } + } +} + registry! { /// The AI code that's currently being executed for the entity. enum Activity {