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

use az-registry in az-protocol

This commit is contained in:
mat 2022-09-05 11:44:48 -05:00
parent 4301a2f2d4
commit fcb5bdf042
19 changed files with 143 additions and 50 deletions

4
Cargo.lock generated
View file

@ -106,6 +106,7 @@ name = "azalea-block"
version = "0.1.0"
dependencies = [
"azalea-block-macros",
"azalea-buf",
]
[[package]]
@ -235,6 +236,7 @@ dependencies = [
"async-compression",
"async-recursion",
"azalea-auth",
"azalea-block",
"azalea-brigadier",
"azalea-buf",
"azalea-chat",
@ -242,6 +244,7 @@ dependencies = [
"azalea-crypto",
"azalea-nbt",
"azalea-protocol-macros",
"azalea-registry",
"azalea-world",
"byteorder",
"bytes",
@ -268,6 +271,7 @@ dependencies = [
name = "azalea-registry"
version = "0.1.0"
dependencies = [
"azalea-buf",
"azalea-registry-macros",
]

View file

@ -11,3 +11,4 @@ version = "0.1.0"
[dependencies]
azalea-block-macros = {path = "./azalea-block-macros", version = "^0.1.0"}
azalea-buf = {path = "../azalea-buf", version = "^0.1.0"}

View file

@ -1,10 +1,13 @@
mod behavior;
mod blocks;
use azalea_buf::{BufReadError, McBufReadable, McBufVarReadable, McBufVarWritable, McBufWritable};
pub use behavior::BlockBehavior;
pub use blocks::*;
use std::mem;
use std::{
io::{Read, Write},
mem,
};
impl BlockState {
/// Transmutes a u32 to a block state.
@ -35,6 +38,20 @@ impl TryFrom<u32> for BlockState {
}
}
impl McBufReadable for BlockState {
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
let state_id = u32::var_read_from(buf)?;
Self::try_from(state_id).map_err(|_| BufReadError::UnexpectedEnumVariant {
id: state_id as i32,
})
}
}
impl McBufWritable for BlockState {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
u32::var_write_into(&(*self as u32), buf)
}
}
#[cfg(test)]
mod tests {
use super::*;

View file

@ -74,8 +74,22 @@ fn create_impl_mcbufreadable(ident: &Ident, data: &Data) -> proc_macro2::TokenSt
variant_discrim += 1;
}
}
let reader = match variant.fields {
syn::Fields::Named(_) => {
panic!("writing named fields in enums is not supported")
}
syn::Fields::Unnamed(_) => quote! {
Ok(Self::#variant_name(azalea_buf::McBufReadable::read_from(buf)?))
},
syn::Fields::Unit => quote! {
Ok(Self::#variant_name)
},
};
match_contents.extend(quote! {
#variant_discrim => Ok(Self::#variant_name),
#variant_discrim => {
#reader
},
});
}
@ -141,11 +155,75 @@ fn create_impl_mcbufwritable(ident: &Ident, data: &Data) -> proc_macro2::TokenSt
}
}
}
syn::Data::Enum(syn::DataEnum { .. }) => {
quote! {
impl azalea_buf::McBufWritable for #ident {
fn write_into(&self, buf: &mut impl std::io::Write) -> Result<(), std::io::Error> {
azalea_buf::McBufVarWritable::var_write_into(&(*self as u32), buf)
syn::Data::Enum(syn::DataEnum { variants, .. }) => {
// remember whether it's a data variant so we can do an optimization later
let mut is_data_enum = false;
let mut match_arms = quote!();
let mut variant_discrim: u32 = 0;
for variant in variants {
// figure out the discriminant
if let Some(discriminant) = &variant.discriminant {
variant_discrim = match &discriminant.1 {
syn::Expr::Lit(e) => match &e.lit {
syn::Lit::Int(i) => i.base10_parse().unwrap(),
_ => panic!("Error parsing enum discriminant as int"),
},
syn::Expr::Unary(_) => {
panic!("Negative enum discriminants are not supported")
}
_ => {
panic!(
"Error parsing enum discriminant as literal (is {:?})",
discriminant.1
)
}
};
} else {
variant_discrim += 1;
}
match &variant.fields {
syn::Fields::Named(_) => {
panic!("Enum variants with named fields are not supported yet");
}
syn::Fields::Unit => {
let variant_name = &variant.ident;
match_arms.extend(quote! {
Self::#variant_name => {
azalea_buf::McBufVarWritable::var_write_into(&#variant_discrim, buf)?;
}
});
}
syn::Fields::Unnamed(_) => {
is_data_enum = true;
let variant_name = &variant.ident;
match_arms.extend(quote! {
Self::#variant_name(data) => {
azalea_buf::McBufVarWritable::var_write_into(&#variant_discrim, buf)?;
azalea_buf::McBufWritable::write_into(data, buf)?;
}
});
}
}
}
if is_data_enum {
quote! {
impl azalea_buf::McBufWritable for #ident {
fn write_into(&self, buf: &mut impl std::io::Write) -> Result<(), std::io::Error> {
match self {
#match_arms
}
Ok(())
}
}
}
} else {
// optimization: if it doesn't have data we can just do `as u32`
quote! {
impl azalea_buf::McBufWritable for #ident {
fn write_into(&self, buf: &mut impl std::io::Write) -> Result<(), std::io::Error> {
azalea_buf::McBufVarWritable::var_write_into(&(*self as u32), buf)
}
}
}
}

View file

@ -11,6 +11,7 @@ version = "0.1.0"
async-compression = {version = "^0.3.8", features = ["tokio", "zlib"], optional = true}
async-recursion = "1.0.0"
azalea-auth = {path = "../azalea-auth", version = "^0.1.0"}
azalea-block = {path = "../azalea-block", default-features = false, version = "^0.1.0"}
azalea-brigadier = {path = "../azalea-brigadier", version = "^0.1.0"}
azalea-buf = {path = "../azalea-buf", version = "^0.1.0"}
azalea-chat = {path = "../azalea-chat", version = "^0.1.1"}
@ -18,6 +19,7 @@ azalea-core = {path = "../azalea-core", optional = true, version = "^0.1.0"}
azalea-crypto = {path = "../azalea-crypto", version = "^0.1.0"}
azalea-nbt = {path = "../azalea-nbt", version = "^0.1.0"}
azalea-protocol-macros = {path = "./azalea-protocol-macros", version = "^0.1.0"}
azalea-registry = {path = "../azalea-registry", version = "^0.1.0"}
azalea-world = {path = "../azalea-world", version = "^0.1.0"}
byteorder = "^1.4.3"
bytes = "^1.1.0"

View file

@ -10,9 +10,7 @@ pub struct ClientboundAddEntityPacket {
#[var]
pub id: u32,
pub uuid: Uuid,
// TODO: have an entity type enum/struct
#[var]
pub entity_type: i32,
pub entity_type: azalea_registry::EntityType,
pub x: f64,
pub y: f64,
pub z: f64,

View file

@ -9,10 +9,14 @@ pub struct ClientboundAwardStatsPacket {
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, McBuf)]
pub struct Stat {
// TODO: make these good enums and stuff
#[var]
pub stat_type: u32,
#[var]
pub statistic_id: u32,
pub enum Stat {
Mined(azalea_registry::Block),
Crafted(azalea_registry::Item),
Used(azalea_registry::Item),
Broken(azalea_registry::Item),
PickedUp(azalea_registry::Item),
Dropped(azalea_registry::Item),
Killed(azalea_registry::EntityType),
KilledBy(azalea_registry::EntityType),
Custom(azalea_registry::CustomStat),
}

View file

@ -5,8 +5,6 @@ use azalea_protocol_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundBlockEntityDataPacket {
pub pos: BlockPos,
// TODO: in vanilla this uses the block entity registry, we should have an enum in azalea-entity for this
#[var]
pub block_entity_type: u32,
pub block_entity_type: azalea_registry::BlockEntityType,
pub tag: azalea_nbt::Tag,
}

View file

@ -1,3 +1,4 @@
use azalea_block::BlockState;
use azalea_buf::McBuf;
use azalea_core::BlockPos;
use azalea_protocol_macros::ClientboundGamePacket;
@ -7,7 +8,5 @@ pub struct ClientboundBlockEventPacket {
pub pos: BlockPos,
pub b0: u8,
pub b1: u8,
// TODO: this is a BlockState, see ClientboundBlockUpdatePacket for more info
#[var]
pub block: u32,
pub block: BlockState,
}

View file

@ -1,3 +1,4 @@
use azalea_block::BlockState;
use azalea_buf::McBuf;
use azalea_core::BlockPos;
use azalea_protocol_macros::ClientboundGamePacket;
@ -5,8 +6,5 @@ use azalea_protocol_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundBlockUpdatePacket {
pub pos: BlockPos,
// TODO: in vanilla this is a BlockState, but here we just have it as a number.
// perhaps we could make a crate that only handles block states? right now blockstates are handled in azalea-block
#[var]
pub block_state: u32,
pub block_state: BlockState,
}

View file

@ -3,9 +3,7 @@ use azalea_protocol_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundCooldownPacket {
// TODO: make azalea-items or something and use that
#[var]
pub item: u32,
pub item: azalea_registry::Item,
#[var]
pub duration: u32,
}

View file

@ -6,8 +6,6 @@ use azalea_protocol_macros::ClientboundGamePacket;
pub struct ClientboundOpenScreenPacket {
#[var]
pub container_id: u32,
// TODO: have an enum of this
#[var]
pub menu_type: u32,
pub menu_type: azalea_registry::Menu,
pub title: Component,
}

View file

@ -5,7 +5,5 @@ use azalea_protocol_macros::ClientboundGamePacket;
pub struct ClientboundRemoveMobEffectPacket {
#[var]
pub entity_id: u32,
// TODO: have this use an enum
#[var]
pub effect: u32,
pub effect: azalea_registry::MobEffect,
}

View file

@ -4,9 +4,7 @@ use azalea_protocol_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundSoundEntityPacket {
// TODO: sound enum/registry
#[var]
pub sound: u32,
pub sound: azalea_registry::SoundEvent,
pub source: SoundSource,
#[var]
pub id: u32,

View file

@ -3,9 +3,7 @@ use azalea_protocol_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundSoundPacket {
// TODO: sound enum/registry
#[var]
pub sound: u32,
pub sound: azalea_registry::SoundEvent,
pub source: SoundSource,
pub x: i32,
pub y: i32,

View file

@ -5,9 +5,7 @@ use azalea_protocol_macros::ClientboundGamePacket;
pub struct ClientboundUpdateMobEffectPacket {
#[var]
pub entity_id: u32,
// TODO: have an enum for this
#[var]
pub effect: u32,
pub effect: azalea_registry::MobEffect,
pub effect_amplifier: u8,
#[var]
pub effect_duration_ticks: u32,

View file

@ -26,7 +26,6 @@ pub struct ShapelessRecipe {
}
#[derive(Clone, Debug)]
pub struct ShapedRecipe {
// TODO: make own McBufReadable and McBufWritable for this
width: usize,
height: usize,
group: String,

View file

@ -8,4 +8,5 @@ version = "0.1.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
azalea-buf = {path = "../azalea-buf", version = "^0.1.0"}
azalea-registry-macros = {path = "./azalea-registry-macros", version = "^0.1.0"}

View file

@ -67,7 +67,7 @@ pub fn registry(input: TokenStream) -> TokenStream {
});
}
generated.extend(quote! {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, azalea_buf::McBuf)]
#[repr(u32)]
pub enum #name {
#enum_items
@ -75,12 +75,16 @@ pub fn registry(input: TokenStream) -> TokenStream {
});
let max_id = input.items.len() as u32;
let doc_0 = format!("Transmutes a u32 to a {}.", name);
let doc_1 = format!("The `id` should be at most {}.", max_id);
generated.extend(quote! {
impl #name {
/// Transmutes a u32 to a #name.
#[doc = #doc_0]
///
/// # Safety
/// The `id` should be at most #max_id.
#[doc = #doc_1]
#[inline]
pub unsafe fn from_u32_unchecked(id: u32) -> Self {
std::mem::transmute::<u32, #name>(id)
@ -93,11 +97,13 @@ pub fn registry(input: TokenStream) -> TokenStream {
}
});
let doc_0 = format!("Safely transmutes a u32 to a {}.", name);
generated.extend(quote! {
impl TryFrom<u32> for #name {
type Error = ();
/// Safely converts a state id to a block state.
#[doc = #doc_0]
fn try_from(id: u32) -> Result<Self, Self::Error> {
if Self::is_valid_id(id) {
Ok(unsafe { Self::from_u32_unchecked(id) })