From f9528a9f9a9e73b1d657af7c78d743067307d843 Mon Sep 17 00:00:00 2001 From: mat Date: Tue, 26 Apr 2022 15:13:47 +0000 Subject: [PATCH] work on adding more stuff for recipes --- Cargo.lock | 1 + azalea-core/Cargo.toml | 1 + azalea-core/src/lib.rs | 3 + azalea-core/src/slot.rs | 16 +++ azalea-protocol/src/mc_buf/read.rs | 24 +++- .../game/clientbound_update_recipes_packet.rs | 130 +++++++++++++++++- 6 files changed, 167 insertions(+), 8 deletions(-) create mode 100644 azalea-core/src/slot.rs diff --git a/Cargo.lock b/Cargo.lock index 8be7aa31..144a840b 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -111,6 +111,7 @@ name = "azalea-core" version = "0.1.0" dependencies = [ "azalea-chat", + "azalea-nbt", "uuid", ] diff --git a/azalea-core/Cargo.toml b/azalea-core/Cargo.toml index b0139999..d652a46e 100755 --- a/azalea-core/Cargo.toml +++ b/azalea-core/Cargo.toml @@ -7,4 +7,5 @@ version = "0.1.0" [dependencies] azalea-chat = {path = "../azalea-chat"} +azalea-nbt = {path = "../azalea-nbt"} uuid = "^0.8.2" diff --git a/azalea-core/src/lib.rs b/azalea-core/src/lib.rs index cdf07c43..6f52e7e9 100755 --- a/azalea-core/src/lib.rs +++ b/azalea-core/src/lib.rs @@ -4,3 +4,6 @@ pub mod difficulty; pub mod game_type; pub mod resource_location; pub mod serializable_uuid; + +mod slot; +pub use slot::{Slot, SlotData}; diff --git a/azalea-core/src/slot.rs b/azalea-core/src/slot.rs new file mode 100644 index 00000000..2e581586 --- /dev/null +++ b/azalea-core/src/slot.rs @@ -0,0 +1,16 @@ +// TODO: have an azalea-inventory crate and put this there + +#[derive(Debug, Clone)] +pub enum Slot { + Present(SlotData), + Empty, +} + +#[derive(Debug, Clone)] +pub struct SlotData { + pub id: i32, + // TODO: is this really a u8? is it a i8? is it a varint? + // wiki.vg says it's a "byte" + pub count: u8, + pub nbt: azalea_nbt::Tag, +} diff --git a/azalea-protocol/src/mc_buf/read.rs b/azalea-protocol/src/mc_buf/read.rs index 3d50e5aa..1e7db1dd 100755 --- a/azalea-protocol/src/mc_buf/read.rs +++ b/azalea-protocol/src/mc_buf/read.rs @@ -1,11 +1,12 @@ +use crate::mc_buf::ByteArray; use async_trait::async_trait; use azalea_chat::component::Component; use azalea_core::{ - difficulty::Difficulty, game_type::GameType, resource_location::ResourceLocation, + difficulty::Difficulty, game_type::GameType, resource_location::ResourceLocation, Slot, + SlotData, }; use serde::Deserialize; use tokio::io::{AsyncRead, AsyncReadExt}; -use crate::mc_buf::ByteArray; use super::MAX_STRING_LENGTH; @@ -252,7 +253,6 @@ impl McBufReadable for Vec { } } - #[async_trait] impl McBufReadable for ByteArray { async fn read_into(buf: &mut R) -> Result @@ -469,3 +469,21 @@ impl McBufReadable for Component { Ok(component) } } + +// Slot +#[async_trait] +impl McBufReadable for Slot { + async fn read_into(buf: &mut R) -> Result + where + R: AsyncRead + std::marker::Unpin + std::marker::Send, + { + let present = buf.read_boolean().await?; + if !present { + return Ok(Slot::Empty); + } + let id = buf.read_varint().await?; + let count = buf.read_byte().await?; + let nbt = buf.read_nbt().await?; + Ok(Slot::Present(SlotData { id, count, nbt })) + } +} diff --git a/azalea-protocol/src/packets/game/clientbound_update_recipes_packet.rs b/azalea-protocol/src/packets/game/clientbound_update_recipes_packet.rs index 8f9deae8..558b74c7 100644 --- a/azalea-protocol/src/packets/game/clientbound_update_recipes_packet.rs +++ b/azalea-protocol/src/packets/game/clientbound_update_recipes_packet.rs @@ -1,14 +1,134 @@ +use async_trait::async_trait; use azalea_chat::component::Component; -use azalea_core::resource_location::ResourceLocation; +use azalea_core::{resource_location::ResourceLocation, Slot}; use packet_macros::GamePacket; +use tokio::io::AsyncRead; + +use crate::mc_buf::{McBufReadable, McBufWritable, Readable, Writable}; #[derive(Clone, Debug, GamePacket)] pub struct ClientboundUpdateRecipesPacket { pub recipes: Vec, } -struct Recipe { - type_: ResourceLocation, - identifier: ResourceLocation, - // data +#[derive(Clone, Debug)] +pub struct Recipe { + pub identifier: ResourceLocation, + pub data: RecipeData, +} + +#[derive(Clone, Debug)] +pub enum RecipeData { + CraftingShapeless { + /// Used to group similar recipes together in the recipe book. + /// Tag is present in recipe JSON + group: String, + // ingredients + ingredients: Vec, + result: Slot, + }, +} + +#[derive(Clone, Debug)] +pub struct Ingredient { + pub allowed: Vec, +} + +impl McBufWritable for Recipe { + fn write_into(&self, buf: &mut Vec) -> Result<(), std::io::Error> { + todo!() + } +} +#[async_trait] +impl McBufReadable for Recipe { + async fn read_into(buf: &mut R) -> Result + where + R: AsyncRead + std::marker::Unpin + std::marker::Send, + { + let recipe_type = buf.read_resource_location().await?; + let identifier = buf.read_resource_location().await?; + + // rust doesn't let us match ResourceLocation so we have to do a big + // if-else chain :( + let data = if recipe_type == ResourceLocation::new("minecraft:crafting_shapeless").unwrap() + { + let group = buf.read_utf().await?; + let ingredients = Vec::::read_into(buf).await?; + let result = Slot::read_into(buf).await?; + + RecipeData::CraftingShapeless { + group, + ingredients, + result, + } + } else { + panic!(); + }; + + let recipe = Recipe { identifier, data }; + + Ok(recipe) + } +} + +impl McBufWritable for Ingredient { + fn write_into(&self, buf: &mut Vec) -> Result<(), std::io::Error> { + todo!() + } +} +#[async_trait] +impl McBufReadable for Ingredient { + async fn read_into(buf: &mut R) -> Result + where + R: AsyncRead + std::marker::Unpin + std::marker::Send, + { + let ingredient = Ingredient { + allowed: Vec::::read_into(buf).await?, + }; + Ok(ingredient) + } +} + +impl McBufWritable for Vec { + fn write_into(&self, buf: &mut Vec) -> Result<(), std::io::Error> { + buf.write_varint(self.len() as i32)?; + for recipe in self { + recipe.write_into(buf)?; + } + Ok(()) + } +} +#[async_trait] +impl McBufReadable for Vec { + async fn read_into(buf: &mut R) -> Result + where + R: AsyncRead + std::marker::Unpin + std::marker::Send, + { + let recipe_count = buf.read_varint().await?; + let mut recipes = Vec::with_capacity(recipe_count as usize); + for _ in 0..recipe_count { + recipes.push(Recipe::read_into(buf).await?); + } + Ok(recipes) + } +} + +impl McBufWritable for Vec { + fn write_into(&self, buf: &mut Vec) -> Result<(), std::io::Error> { + buf.write_varint(self.len() as i32)?; + for ingredient in self { + ingredient.write_into(buf)?; + } + Ok(()) + } +} + +#[async_trait] +impl McBufReadable for Vec { + async fn read_into(buf: &mut R) -> Result + where + R: AsyncRead + std::marker::Unpin + std::marker::Send, + { + todo!() + } }