aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock6
-rwxr-xr-xazalea-brigadier/Cargo.toml5
-rwxr-xr-xazalea-brigadier/src/exceptions/builtin_exceptions.rs6
-rwxr-xr-xazalea-brigadier/src/exceptions/command_syntax_exception.rs11
-rwxr-xr-xazalea-brigadier/src/lib.rs1
-rwxr-xr-xazalea-brigadier/src/message.rs14
-rwxr-xr-xazalea-brigadier/src/suggestion/mod.rs31
-rwxr-xr-xazalea-brigadier/src/suggestion/suggestions.rs74
-rwxr-xr-xazalea-core/src/slot.rs23
-rwxr-xr-xazalea-nbt/Cargo.toml3
-rwxr-xr-xazalea-nbt/README.md2
-rwxr-xr-xazalea-nbt/src/encode.rs4
-rwxr-xr-xazalea-nbt/src/tag.rs4
-rwxr-xr-xazalea-protocol/Cargo.toml22
-rwxr-xr-xazalea-protocol/src/packets/game/clientbound_command_suggestions_packet.rs48
-rwxr-xr-xazalea-protocol/src/packets/game/clientbound_commands_packet.rs259
-rwxr-xr-xazalea-protocol/src/packets/game/clientbound_update_recipes_packet.rs146
17 files changed, 563 insertions, 96 deletions
diff --git a/Cargo.lock b/Cargo.lock
index f8a5fb7b..747a262b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -37,6 +37,7 @@ dependencies = [
"cfg-if",
"getrandom",
"once_cell",
+ "serde",
"version_check",
]
@@ -170,6 +171,10 @@ dependencies = [
[[package]]
name = "azalea-brigadier"
version = "0.4.0"
+dependencies = [
+ "azalea-buf",
+ "azalea-chat",
+]
[[package]]
name = "azalea-buf"
@@ -274,6 +279,7 @@ dependencies = [
"log",
"num-derive",
"num-traits",
+ "serde",
]
[[package]]
diff --git a/azalea-brigadier/Cargo.toml b/azalea-brigadier/Cargo.toml
index 0a5d56c5..43e71b3c 100755
--- a/azalea-brigadier/Cargo.toml
+++ b/azalea-brigadier/Cargo.toml
@@ -9,3 +9,8 @@ version = "0.4.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.4.0", optional = true}
+azalea-chat = {path = "../azalea-chat", version = "^0.4.0", optional = true}
+
+[features]
+azalea-buf = ["dep:azalea-buf", "dep:azalea-chat"]
diff --git a/azalea-brigadier/src/exceptions/builtin_exceptions.rs b/azalea-brigadier/src/exceptions/builtin_exceptions.rs
index d95ee237..c3c3c900 100755
--- a/azalea-brigadier/src/exceptions/builtin_exceptions.rs
+++ b/azalea-brigadier/src/exceptions/builtin_exceptions.rs
@@ -1,6 +1,6 @@
use std::fmt;
-use crate::{message::Message, string_reader::StringReader};
+use crate::string_reader::StringReader;
use super::command_syntax_exception::CommandSyntaxException;
@@ -148,12 +148,12 @@ impl fmt::Debug for BuiltInExceptions {
impl BuiltInExceptions {
pub fn create(self) -> CommandSyntaxException {
- let message = Message::from(format!("{self:?}"));
+ let message = format!("{self:?}");
CommandSyntaxException::create(self, message)
}
pub fn create_with_context(self, reader: &StringReader) -> CommandSyntaxException {
- let message = Message::from(format!("{self:?}"));
+ let message = format!("{self:?}");
CommandSyntaxException::new(self, message, reader.string(), reader.cursor())
}
}
diff --git a/azalea-brigadier/src/exceptions/command_syntax_exception.rs b/azalea-brigadier/src/exceptions/command_syntax_exception.rs
index 14376a87..0254820d 100755
--- a/azalea-brigadier/src/exceptions/command_syntax_exception.rs
+++ b/azalea-brigadier/src/exceptions/command_syntax_exception.rs
@@ -1,5 +1,4 @@
use super::builtin_exceptions::BuiltInExceptions;
-use crate::message::Message;
use std::{
cmp,
fmt::{self, Write},
@@ -8,7 +7,7 @@ use std::{
#[derive(Clone, PartialEq)]
pub struct CommandSyntaxException {
pub type_: BuiltInExceptions,
- message: Message,
+ message: String,
input: Option<String>,
cursor: Option<usize>,
}
@@ -16,7 +15,7 @@ pub struct CommandSyntaxException {
const CONTEXT_AMOUNT: usize = 10;
impl CommandSyntaxException {
- pub fn new(type_: BuiltInExceptions, message: Message, input: &str, cursor: usize) -> Self {
+ pub fn new(type_: BuiltInExceptions, message: String, input: &str, cursor: usize) -> Self {
Self {
type_,
message,
@@ -25,7 +24,7 @@ impl CommandSyntaxException {
}
}
- pub fn create(type_: BuiltInExceptions, message: Message) -> Self {
+ pub fn create(type_: BuiltInExceptions, message: String) -> Self {
Self {
type_,
message,
@@ -35,7 +34,7 @@ impl CommandSyntaxException {
}
pub fn message(&self) -> String {
- let mut message = self.message.string();
+ let mut message = self.message.clone();
let context = self.context();
if let Some(context) = context {
write!(
@@ -49,7 +48,7 @@ impl CommandSyntaxException {
message
}
- pub fn raw_message(&self) -> &Message {
+ pub fn raw_message(&self) -> &String {
&self.message
}
diff --git a/azalea-brigadier/src/lib.rs b/azalea-brigadier/src/lib.rs
index 3c37b7f3..cf2ce571 100755
--- a/azalea-brigadier/src/lib.rs
+++ b/azalea-brigadier/src/lib.rs
@@ -3,7 +3,6 @@ pub mod builder;
pub mod command_dispatcher;
pub mod context;
pub mod exceptions;
-pub mod message;
pub mod modifier;
pub mod parse_results;
pub mod string_reader;
diff --git a/azalea-brigadier/src/message.rs b/azalea-brigadier/src/message.rs
deleted file mode 100755
index 75e07d4e..00000000
--- a/azalea-brigadier/src/message.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-#[derive(Debug, Clone, Hash, PartialEq, Eq)]
-pub struct Message(String);
-
-impl Message {
- pub fn string(&self) -> String {
- self.0.to_string()
- }
-}
-
-impl From<String> for Message {
- fn from(s: String) -> Self {
- Self(s)
- }
-}
diff --git a/azalea-brigadier/src/suggestion/mod.rs b/azalea-brigadier/src/suggestion/mod.rs
index 4c9a9547..114a4c47 100755
--- a/azalea-brigadier/src/suggestion/mod.rs
+++ b/azalea-brigadier/src/suggestion/mod.rs
@@ -1,16 +1,26 @@
mod suggestions;
-use crate::{context::StringRange, message::Message};
+use crate::context::StringRange;
+#[cfg(feature = "azalea-buf")]
+use azalea_buf::McBufWritable;
+#[cfg(feature = "azalea-buf")]
+use azalea_chat::Component;
+#[cfg(feature = "azalea-buf")]
+use std::io::Write;
pub use suggestions::*;
+/// A suggestion given to the user for what they might want to type next.
+///
+/// The `M` generic is the type of the tooltip, so for example a `String` or
+/// just `()` if you don't care about it.
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
-pub struct Suggestion {
- pub range: StringRange,
+pub struct Suggestion<M = String> {
pub text: String,
- pub tooltip: Option<Message>,
+ pub range: StringRange,
+ pub tooltip: Option<M>,
}
-impl Suggestion {
+impl<M: Clone> Suggestion<M> {
pub fn apply(&self, input: &str) -> String {
if self.range.start() == 0 && self.range.end() == input.len() {
return input.to_string();
@@ -27,7 +37,7 @@ impl Suggestion {
result
}
- pub fn expand(&self, command: &str, range: &StringRange) -> Suggestion {
+ pub fn expand(&self, command: &str, range: &StringRange) -> Suggestion<M> {
if range == &self.range {
return self.clone();
}
@@ -46,3 +56,12 @@ impl Suggestion {
}
}
}
+
+#[cfg(feature = "azalea-buf")]
+impl McBufWritable for Suggestion<Component> {
+ fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
+ self.text.write_into(buf)?;
+ self.tooltip.write_into(buf)?;
+ Ok(())
+ }
+}
diff --git a/azalea-brigadier/src/suggestion/suggestions.rs b/azalea-brigadier/src/suggestion/suggestions.rs
index 1fe361f1..06ef9661 100755
--- a/azalea-brigadier/src/suggestion/suggestions.rs
+++ b/azalea-brigadier/src/suggestion/suggestions.rs
@@ -1,15 +1,23 @@
use super::Suggestion;
use crate::context::StringRange;
-use std::collections::HashSet;
+#[cfg(feature = "azalea-buf")]
+use azalea_buf::{
+ BufReadError, McBuf, McBufReadable, McBufVarReadable, McBufVarWritable, McBufWritable,
+};
+#[cfg(feature = "azalea-buf")]
+use azalea_chat::Component;
+#[cfg(feature = "azalea-buf")]
+use std::io::{Cursor, Write};
+use std::{collections::HashSet, hash::Hash};
-#[derive(Debug, Clone, Default, Eq, PartialEq, Hash)]
-pub struct Suggestions {
+#[derive(Debug, Clone, Eq, PartialEq, Hash)]
+pub struct Suggestions<M = String> {
pub range: StringRange,
- pub suggestions: Vec<Suggestion>,
+ pub suggestions: Vec<Suggestion<M>>,
}
-impl Suggestions {
- pub fn merge(command: &str, input: &[Suggestions]) -> Self {
+impl<M: Clone + Eq + Hash> Suggestions<M> {
+ pub fn merge(command: &str, input: &[Suggestions<M>]) -> Self {
if input.is_empty() {
return Suggestions::default();
} else if input.len() == 1 {
@@ -24,7 +32,7 @@ impl Suggestions {
Suggestions::create(command, &texts)
}
- pub fn create(command: &str, suggestions: &HashSet<Suggestion>) -> Self {
+ pub fn create(command: &str, suggestions: &HashSet<Suggestion<M>>) -> Self {
if suggestions.is_empty() {
return Suggestions::default();
};
@@ -39,7 +47,7 @@ impl Suggestions {
for suggestion in suggestions {
texts.insert(suggestion.expand(command, &range));
}
- let mut sorted: Vec<Suggestion> = texts.into_iter().collect();
+ let mut sorted = texts.into_iter().collect::<Vec<_>>();
sorted.sort_by(|a, b| a.text.cmp(&b.text));
Suggestions {
range,
@@ -47,3 +55,53 @@ impl Suggestions {
}
}
}
+
+// this can't be derived because that'd require the generic to have `Default`
+// too even if it's not actually necessary
+impl<M> Default for Suggestions<M> {
+ fn default() -> Self {
+ Self {
+ range: StringRange::default(),
+ suggestions: Vec::new(),
+ }
+ }
+}
+
+#[cfg(feature = "azalea-buf")]
+impl McBufReadable for Suggestions<Component> {
+ fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
+ #[derive(McBuf)]
+ struct StandaloneSuggestion {
+ pub text: String,
+ pub tooltip: Option<Component>,
+ }
+
+ let start = u32::var_read_from(buf)? as usize;
+ let length = u32::var_read_from(buf)? as usize;
+ let range = StringRange::between(start, start + length);
+
+ // the range of a Suggestion depends on the Suggestions containing it,
+ // so we can't just `impl McBufReadable for Suggestion`
+ let mut suggestions = Vec::<StandaloneSuggestion>::read_from(buf)?
+ .into_iter()
+ .map(|s| Suggestion {
+ text: s.text,
+ tooltip: s.tooltip,
+ range: range.clone(),
+ })
+ .collect::<Vec<_>>();
+ suggestions.sort_by(|a, b| a.text.cmp(&b.text));
+
+ Ok(Suggestions { range, suggestions })
+ }
+}
+
+#[cfg(feature = "azalea-buf")]
+impl McBufWritable for Suggestions<Component> {
+ fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
+ (self.range.start() as u32).var_write_into(buf)?;
+ (self.range.length() as u32).var_write_into(buf)?;
+ self.suggestions.write_into(buf)?;
+ Ok(())
+ }
+}
diff --git a/azalea-core/src/slot.rs b/azalea-core/src/slot.rs
index f1cd4f0b..4406e08d 100755
--- a/azalea-core/src/slot.rs
+++ b/azalea-core/src/slot.rs
@@ -1,6 +1,7 @@
// TODO: have an azalea-inventory or azalea-container crate and put this there
use azalea_buf::{BufReadError, McBuf, McBufReadable, McBufWritable};
+use azalea_nbt::Tag;
use std::io::{Cursor, Write};
#[derive(Debug, Clone, Default)]
@@ -13,29 +14,27 @@ pub enum Slot {
#[derive(Debug, Clone, McBuf)]
pub struct SlotData {
#[var]
- pub id: i32,
+ pub id: u32,
pub count: u8,
- pub nbt: azalea_nbt::Tag,
+ pub nbt: Tag,
}
impl McBufReadable for Slot {
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
- let present = bool::read_from(buf)?;
- if !present {
- return Ok(Slot::Empty);
- }
- let slot = SlotData::read_from(buf)?;
- Ok(Slot::Present(slot))
+ let slot = Option::<SlotData>::read_from(buf)?;
+ Ok(slot.map_or(Slot::Empty, Slot::Present))
}
}
impl McBufWritable for Slot {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
match self {
- Slot::Empty => 0u8.write_into(buf)?,
- Slot::Present(i) => i.write_into(buf)?,
- }
-
+ Slot::Empty => false.write_into(buf)?,
+ Slot::Present(i) => {
+ true.write_into(buf)?;
+ i.write_into(buf)?;
+ }
+ };
Ok(())
}
}
diff --git a/azalea-nbt/Cargo.toml b/azalea-nbt/Cargo.toml
index 11cad33d..1ff52cdd 100755
--- a/azalea-nbt/Cargo.toml
+++ b/azalea-nbt/Cargo.toml
@@ -9,13 +9,14 @@ repository = "https://github.com/mat-1/azalea/tree/main/azalea-nbt"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
-ahash = "^0.8.0"
+ahash = { version = "^0.8.0", features = ["serde"]}
azalea-buf = {path = "../azalea-buf", version = "^0.4.0" }
byteorder = "^1.4.3"
flate2 = "^1.0.23"
log = "0.4.17"
num-derive = "^0.3.3"
num-traits = "^0.2.14"
+serde = {version = "^1.0.148", features = ["derive"]}
[dev-dependencies]
criterion = {version = "^0.3.5", features = ["html_reports"]}
diff --git a/azalea-nbt/README.md b/azalea-nbt/README.md
index 4d5cecc4..19498cf3 100755
--- a/azalea-nbt/README.md
+++ b/azalea-nbt/README.md
@@ -1,5 +1,3 @@
# Azalea NBT
A fast NBT serializer and deserializer.
-
-TODO: serde support for fast registry_holder parsing in azalea-client
diff --git a/azalea-nbt/src/encode.rs b/azalea-nbt/src/encode.rs
index 49c31192..87464fd9 100755
--- a/azalea-nbt/src/encode.rs
+++ b/azalea-nbt/src/encode.rs
@@ -193,6 +193,10 @@ impl Tag {
write_compound(writer, value, false)?;
Ok(())
}
+ Tag::End => {
+ 0u8.write_into(writer)?;
+ Ok(())
+ }
_ => Err(Error::InvalidTag),
}
}
diff --git a/azalea-nbt/src/tag.rs b/azalea-nbt/src/tag.rs
index de57b0a2..2bebe156 100755
--- a/azalea-nbt/src/tag.rs
+++ b/azalea-nbt/src/tag.rs
@@ -1,6 +1,8 @@
use ahash::AHashMap;
+use serde::{Deserialize, Serialize};
-#[derive(Clone, Debug, PartialEq)]
+#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
+#[serde(untagged)]
pub enum Tag {
End, // 0
Byte(i8), // 1
diff --git a/azalea-protocol/Cargo.toml b/azalea-protocol/Cargo.toml
index f9cf7d86..32ec5b90 100755
--- a/azalea-protocol/Cargo.toml
+++ b/azalea-protocol/Cargo.toml
@@ -11,17 +11,17 @@ version = "0.4.0"
[dependencies]
async-compression = {version = "^0.3.8", features = ["tokio", "zlib"], optional = true}
async-recursion = "1.0.0"
-azalea-auth = {path = "../azalea-auth", version = "^0.4.0" }
-azalea-block = {path = "../azalea-block", default-features = false, version = "^0.4.0" }
-azalea-brigadier = {path = "../azalea-brigadier", version = "^0.4.0" }
-azalea-buf = {path = "../azalea-buf", version = "^0.4.0" }
-azalea-chat = {path = "../azalea-chat", version = "^0.4.0" }
-azalea-core = {path = "../azalea-core", optional = true, version = "^0.4.0" }
-azalea-crypto = {path = "../azalea-crypto", version = "^0.4.0" }
-azalea-nbt = {path = "../azalea-nbt", version = "^0.4.0" }
-azalea-protocol-macros = {path = "./azalea-protocol-macros", version = "^0.4.0" }
-azalea-registry = {path = "../azalea-registry", version = "^0.4.0" }
-azalea-world = {path = "../azalea-world", version = "^0.4.0" }
+azalea-auth = {path = "../azalea-auth", version = "^0.4.0"}
+azalea-block = {path = "../azalea-block", default-features = false, version = "^0.4.0"}
+azalea-brigadier = {path = "../azalea-brigadier", version = "^0.4.0", features = ["azalea-buf"]}
+azalea-buf = {path = "../azalea-buf", version = "^0.4.0"}
+azalea-chat = {path = "../azalea-chat", version = "^0.4.0"}
+azalea-core = {path = "../azalea-core", optional = true, version = "^0.4.0"}
+azalea-crypto = {path = "../azalea-crypto", version = "^0.4.0"}
+azalea-nbt = {path = "../azalea-nbt", version = "^0.4.0"}
+azalea-protocol-macros = {path = "./azalea-protocol-macros", version = "^0.4.0"}
+azalea-registry = {path = "../azalea-registry", version = "^0.4.0"}
+azalea-world = {path = "../azalea-world", version = "^0.4.0"}
byteorder = "^1.4.3"
bytes = "^1.1.0"
flate2 = "1.0.23"
diff --git a/azalea-protocol/src/packets/game/clientbound_command_suggestions_packet.rs b/azalea-protocol/src/packets/game/clientbound_command_suggestions_packet.rs
index c6f426a9..652ce78a 100755
--- a/azalea-protocol/src/packets/game/clientbound_command_suggestions_packet.rs
+++ b/azalea-protocol/src/packets/game/clientbound_command_suggestions_packet.rs
@@ -1,32 +1,36 @@
-// use azalea_brigadier::context::StringRange;
-use azalea_buf::{
- // BufReadError, McBuf, McBufReadable, McBufVarReadable, McBufVarWritable, McBufWritable,
- BufReadError,
- McBufReadable,
- McBufWritable,
-};
+use azalea_brigadier::suggestion::Suggestions;
+use azalea_buf::McBuf;
+use azalea_chat::Component;
use azalea_protocol_macros::ClientboundGamePacket;
-use std::io::{Cursor, Write};
-#[derive(Clone, Debug, ClientboundGamePacket)]
+#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundCommandSuggestionsPacket {
#[var]
pub id: u32,
- // pub suggestions: Suggestions,
+ pub suggestions: Suggestions<Component>,
}
-impl McBufReadable for ClientboundCommandSuggestionsPacket {
- fn read_from(_buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
- // let id = u32::var_read_from(buf)?;
- // let start = u32::var_read_from(buf)? as usize;
- // let length = u32::var_read_from(buf)? as usize;
- // let stringrange = StringRange::between(start, start + length);
- todo!("Suggestions aren't implemented in azalea-brigadier yet")
- }
-}
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use azalea_brigadier::{context::StringRange, suggestion::Suggestion};
+ use azalea_buf::{McBufReadable, McBufWritable};
+ use std::io::Cursor;
-impl McBufWritable for ClientboundCommandSuggestionsPacket {
- fn write_into(&self, _buf: &mut impl Write) -> Result<(), std::io::Error> {
- todo!()
+ #[test]
+ fn test_suggestions() {
+ let suggestions = Suggestions {
+ range: StringRange::new(0, 5),
+ suggestions: vec![Suggestion {
+ text: "foo".to_string(),
+ range: StringRange::new(1, 4),
+ tooltip: Some(Component::from("bar".to_string())),
+ }],
+ };
+ let mut buf = Vec::new();
+ suggestions.write_into(&mut buf).unwrap();
+ let mut cursor = Cursor::new(&buf[..]);
+ let suggestions = Suggestions::read_from(&mut cursor).unwrap();
+ assert_eq!(suggestions, suggestions);
}
}
diff --git a/azalea-protocol/src/packets/game/clientbound_commands_packet.rs b/azalea-protocol/src/packets/game/clientbound_commands_packet.rs
index 2505d2d9..dcaf8d66 100755
--- a/azalea-protocol/src/packets/game/clientbound_commands_packet.rs
+++ b/azalea-protocol/src/packets/game/clientbound_commands_packet.rs
@@ -1,7 +1,7 @@
use azalea_buf::BufReadError;
use azalea_buf::McBuf;
use azalea_buf::McBufVarReadable;
-use azalea_buf::{McBufReadable, McBufWritable};
+use azalea_buf::{McBufReadable, McBufVarWritable, McBufWritable};
use azalea_core::ResourceLocation;
use azalea_protocol_macros::ClientboundGamePacket;
use log::warn;
@@ -25,8 +25,13 @@ pub struct BrigadierNodeStub {
#[derive(Debug, Clone)]
pub struct BrigadierNumber<T> {
- min: Option<T>,
- max: Option<T>,
+ pub min: Option<T>,
+ pub max: Option<T>,
+}
+impl<T> BrigadierNumber<T> {
+ pub fn new(min: Option<T>, max: Option<T>) -> BrigadierNumber<T> {
+ BrigadierNumber { min, max }
+ }
}
impl<T: McBufReadable> McBufReadable for BrigadierNumber<T> {
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
@@ -119,7 +124,6 @@ pub enum BrigadierParser {
Dimension,
Uuid,
NbtTag,
- NbtCompoundTag,
Time,
ResourceOrTag { registry_key: ResourceLocation },
Resource { registry_key: ResourceLocation },
@@ -157,7 +161,7 @@ impl McBufReadable for BrigadierParser {
16 => Ok(BrigadierParser::Color),
17 => Ok(BrigadierParser::Component),
18 => Ok(BrigadierParser::Message),
- 19 => Ok(BrigadierParser::NbtCompoundTag),
+ 19 => Ok(BrigadierParser::Nbt),
20 => Ok(BrigadierParser::NbtTag),
21 => Ok(BrigadierParser::NbtPath),
22 => Ok(BrigadierParser::Objective),
@@ -202,6 +206,181 @@ impl McBufReadable for BrigadierParser {
}
}
+impl McBufWritable for BrigadierParser {
+ fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
+ match &self {
+ BrigadierParser::Bool => {
+ u32::var_write_into(&0, buf)?;
+ }
+ BrigadierParser::Float(f) => {
+ u32::var_write_into(&1, buf)?;
+ f.write_into(buf)?;
+ }
+ BrigadierParser::Double(d) => {
+ u32::var_write_into(&2, buf)?;
+ d.write_into(buf)?;
+ }
+ BrigadierParser::Integer(i) => {
+ u32::var_write_into(&3, buf)?;
+ i.write_into(buf)?;
+ }
+ BrigadierParser::Long(l) => {
+ u32::var_write_into(&4, buf)?;
+ l.write_into(buf)?;
+ }
+ BrigadierParser::String(s) => {
+ u32::var_write_into(&5, buf)?;
+ s.write_into(buf)?;
+ }
+ BrigadierParser::Entity {
+ single,
+ players_only,
+ } => {
+ u32::var_write_into(&6, buf)?;
+ let mut bitmask: u8 = 0x00;
+ if *single {
+ bitmask |= 0x01;
+ }
+ if *players_only {
+ bitmask |= 0x02;
+ }
+ bitmask.write_into(buf)?;
+ }
+ BrigadierParser::GameProfile => {
+ u32::var_write_into(&7, buf)?;
+ }
+ BrigadierParser::BlockPos => {
+ u32::var_write_into(&8, buf)?;
+ }
+ BrigadierParser::ColumnPos => {
+ u32::var_write_into(&9, buf)?;
+ }
+ BrigadierParser::Vec3 => {
+ u32::var_write_into(&10, buf)?;
+ }
+ BrigadierParser::Vec2 => {
+ u32::var_write_into(&11, buf)?;
+ }
+ BrigadierParser::BlockState => {
+ u32::var_write_into(&12, buf)?;
+ }
+ BrigadierParser::BlockPredicate => {
+ u32::var_write_into(&13, buf)?;
+ }
+ BrigadierParser::ItemStack => {
+ u32::var_write_into(&14, buf)?;
+ }
+ BrigadierParser::ItemPredicate => {
+ u32::var_write_into(&15, buf)?;
+ }
+ BrigadierParser::Color => {
+ u32::var_write_into(&16, buf)?;
+ }
+ BrigadierParser::Component => {
+ u32::var_write_into(&17, buf)?;
+ }
+ BrigadierParser::Message => {
+ u32::var_write_into(&18, buf)?;
+ }
+ BrigadierParser::Nbt => {
+ u32::var_write_into(&19, buf)?;
+ }
+ BrigadierParser::NbtTag => {
+ u32::var_write_into(&20, buf)?;
+ }
+ BrigadierParser::NbtPath => {
+ u32::var_write_into(&21, buf)?;
+ }
+ BrigadierParser::Objective => {
+ u32::var_write_into(&22, buf)?;
+ }
+ BrigadierParser::ObjectiveCriteira => {
+ u32::var_write_into(&23, buf)?;
+ }
+ BrigadierParser::Operation => {
+ u32::var_write_into(&24, buf)?;
+ }
+ BrigadierParser::Particle => {
+ u32::var_write_into(&25, buf)?;
+ }
+ BrigadierParser::Angle => {
+ u32::var_write_into(&26, buf)?;
+ }
+ BrigadierParser::Rotation => {
+ u32::var_write_into(&27, buf)?;
+ }
+ BrigadierParser::ScoreboardSlot => {
+ u32::var_write_into(&28, buf)?;
+ }
+ BrigadierParser::ScoreHolder { allows_multiple } => {
+ u32::var_write_into(&29, buf)?;
+ if *allows_multiple {
+ buf.write_all(&[0x01])?;
+ } else {
+ buf.write_all(&[0x00])?;
+ }
+ }
+ BrigadierParser::Swizzle => {
+ u32::var_write_into(&30, buf)?;
+ }
+ BrigadierParser::Team => {
+ u32::var_write_into(&31, buf)?;
+ }
+ BrigadierParser::ItemSlot => {
+ u32::var_write_into(&32, buf)?;
+ }
+ BrigadierParser::ResourceLocation => {
+ u32::var_write_into(&33, buf)?;
+ }
+ BrigadierParser::MobEffect => {
+ u32::var_write_into(&34, buf)?;
+ }
+ BrigadierParser::Function => {
+ u32::var_write_into(&35, buf)?;
+ }
+ BrigadierParser::EntityAnchor => {
+ u32::var_write_into(&36, buf)?;
+ }
+ BrigadierParser::IntRange => {
+ u32::var_write_into(&37, buf)?;
+ }
+ BrigadierParser::FloatRange => {
+ u32::var_write_into(&38, buf)?;
+ }
+ BrigadierParser::ItemEnchantment => {
+ u32::var_write_into(&39, buf)?;
+ }
+ BrigadierParser::EntitySummon => {
+ u32::var_write_into(&40, buf)?;
+ }
+ BrigadierParser::Dimension => {
+ u32::var_write_into(&41, buf)?;
+ }
+ BrigadierParser::Time => {
+ u32::var_write_into(&42, buf)?;
+ }
+ BrigadierParser::ResourceOrTag { registry_key } => {
+ u32::var_write_into(&43, buf)?;
+ registry_key.write_into(buf)?;
+ }
+ BrigadierParser::Resource { registry_key } => {
+ u32::var_write_into(&44, buf)?;
+ registry_key.write_into(buf)?;
+ }
+ BrigadierParser::TemplateMirror => {
+ u32::var_write_into(&45, buf)?;
+ }
+ BrigadierParser::TemplateRotation => {
+ u32::var_write_into(&46, buf)?;
+ }
+ BrigadierParser::Uuid => {
+ u32::var_write_into(&47, buf)?;
+ }
+ }
+ Ok(())
+ }
+}
+
// TODO: BrigadierNodeStub should have more stuff
impl McBufReadable for BrigadierNodeStub {
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
@@ -264,8 +443,74 @@ impl McBufReadable for BrigadierNodeStub {
}
impl McBufWritable for BrigadierNodeStub {
- fn write_into(&self, _buf: &mut impl Write) -> Result<(), std::io::Error> {
- todo!()
+ fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
+ match &self.node_type {
+ NodeType::Root => {
+ let mut flags = 0x00;
+ if self.is_executable {
+ flags |= 0x04;
+ }
+ if self.redirect_node.is_some() {
+ flags |= 0x08;
+ }
+ flags.var_write_into(buf)?;
+
+ self.children.var_write_into(buf)?;
+
+ if let Some(redirect) = self.redirect_node {
+ redirect.var_write_into(buf)?;
+ }
+ }
+ NodeType::Literal { name } => {
+ let mut flags = 0x01;
+ if self.is_executable {
+ flags |= 0x04;
+ }
+ if self.redirect_node.is_some() {
+ flags |= 0x08;
+ }
+ flags.var_write_into(buf)?;
+
+ self.children.var_write_into(buf)?;
+
+ if let Some(redirect) = self.redirect_node {
+ redirect.var_write_into(buf)?;
+ }
+
+ name.write_into(buf)?;
+ }
+ NodeType::Argument {
+ name,
+ parser,
+ suggestions_type,
+ } => {
+ let mut flags = 0x02;
+ if self.is_executable {
+ flags |= 0x04;
+ }
+ if self.redirect_node.is_some() {
+ flags |= 0x08;
+ }
+ if suggestions_type.is_some() {
+ flags |= 0x10;
+ }
+ flags.var_write_into(buf)?;
+
+ self.children.var_write_into(buf)?;
+
+ if let Some(redirect) = self.redirect_node {
+ redirect.var_write_into(buf)?;
+ }
+
+ name.write_into(buf)?;
+ parser.write_into(buf)?;
+
+ if let Some(suggestion) = suggestions_type {
+ suggestion.write_into(buf)?;
+ }
+ }
+ }
+ Ok(())
}
}
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 db31ef78..9c325d29 100755
--- a/azalea-protocol/src/packets/game/clientbound_update_recipes_packet.rs
+++ b/azalea-protocol/src/packets/game/clientbound_update_recipes_packet.rs
@@ -121,8 +121,150 @@ pub struct Ingredient {
}
impl McBufWritable for Recipe {
- fn write_into(&self, _buf: &mut impl Write) -> Result<(), std::io::Error> {
- todo!()
+ fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
+ match &self.data {
+ RecipeData::CraftingShapeless(recipe) => {
+ ResourceLocation::new("minecraft:crafting_shapeless")
+ .unwrap()
+ .write_into(buf)?;
+ self.identifier.write_into(buf)?;
+ recipe.write_into(buf)?;
+ }
+ RecipeData::CraftingShaped(recipe) => {
+ ResourceLocation::new("minecraft:crafting_shaped")
+ .unwrap()
+ .write_into(buf)?;
+ self.identifier.write_into(buf)?;
+ recipe.write_into(buf)?;
+ }
+ RecipeData::CraftingSpecialArmorDye => {
+ ResourceLocation::new("minecraft:crafting_special_armordye")
+ .unwrap()
+ .write_into(buf)?;
+ self.identifier.write_into(buf)?;
+ }
+ RecipeData::CraftingSpecialBookCloning => {
+ ResourceLocation::new("minecraft:crafting_special_bookcloning")
+ .unwrap()
+ .write_into(buf)?;
+ self.identifier.write_into(buf)?;
+ }
+ RecipeData::CraftingSpecialMapCloning => {
+ ResourceLocation::new("minecraft:crafting_special_mapcloning")
+ .unwrap()
+ .write_into(buf)?;
+ self.identifier.write_into(buf)?;
+ }
+ RecipeData::CraftingSpecialMapExtending => {
+ ResourceLocation::new("minecraft:crafting_special_mapextending")
+ .unwrap()
+ .write_into(buf)?;
+ self.identifier.write_into(buf)?;
+ }
+ RecipeData::CraftingSpecialFireworkRocket => {
+ ResourceLocation::new("minecraft:crafting_special_firework_rocket")
+ .unwrap()
+ .write_into(buf)?;
+ self.identifier.write_into(buf)?;
+ }
+ RecipeData::CraftingSpecialFireworkStar => {
+ ResourceLocation::new("minecraft:crafting_special_firework_star")
+ .unwrap()
+ .write_into(buf)?;
+ self.identifier.write_into(buf)?;
+ }
+ RecipeData::CraftingSpecialFireworkStarFade => {
+ ResourceLocation::new("minecraft:crafting_special_firework_star_fade")
+ .unwrap()
+ .write_into(buf)?;
+ self.identifier.write_into(buf)?;
+ }
+ RecipeData::CraftingSpecialRepairItem => {
+ ResourceLocation::new("minecraft:crafting_special_repairitem")
+ .unwrap()
+ .write_into(buf)?;
+ self.identifier.write_into(buf)?;
+ }
+ RecipeData::CraftingSpecialTippedArrow => {
+ ResourceLocation::new("minecraft:crafting_special_tippedarrow")
+ .unwrap()
+ .write_into(buf)?;
+ self.identifier.write_into(buf)?;
+ }
+ RecipeData::CraftingSpecialBannerDuplicate => {
+ ResourceLocation::new("minecraft:crafting_special_bannerduplicate")
+ .unwrap()
+ .write_into(buf)?;
+ self.identifier.write_into(buf)?;
+ }
+ RecipeData::CraftingSpecialBannerAddPattern => {
+ ResourceLocation::new("minecraft:crafting_special_banneraddpattern")
+ .unwrap()
+ .write_into(buf)?;
+ self.identifier.write_into(buf)?;
+ }
+ RecipeData::CraftingSpecialShieldDecoration => {
+ ResourceLocation::new("minecraft:crafting_special_shielddecoration")
+ .unwrap()
+ .write_into(buf)?;
+ self.identifier.write_into(buf)?;
+ }
+ RecipeData::CraftingSpecialShulkerBoxColoring => {
+ ResourceLocation::new("minecraft:crafting_special_shulkerboxcoloring")
+ .unwrap()
+ .write_into(buf)?;
+ self.identifier.write_into(buf)?;
+ }
+ RecipeData::CraftingSpecialSuspiciousStew => {
+ ResourceLocation::new("minecraft:crafting_special_suspiciousstew")
+ .unwrap()
+ .write_into(buf)?;
+ self.identifier.write_into(buf)?;
+ }
+ RecipeData::Smelting(recipe) => {
+ ResourceLocation::new("minecraft:smelting")
+ .unwrap()
+ .write_into(buf)?;
+ self.identifier.write_into(buf)?;
+ recipe.write_into(buf)?;
+ }
+ RecipeData::Blasting(recipe) => {
+ ResourceLocation::new("minecraft:blasting")
+ .unwrap()
+ .write_into(buf)?;
+ self.identifier.write_into(buf)?;
+ recipe.write_into(buf)?;
+ }
+ RecipeData::Smoking(recipe) => {
+ ResourceLocation::new("minecraft:smoking")
+ .unwrap()
+ .write_into(buf)?;
+ self.identifier.write_into(buf)?;
+ recipe.write_into(buf)?;
+ }
+ RecipeData::CampfireCooking(recipe) => {
+ ResourceLocation::new("minecraft:campfire_cooking")
+ .unwrap()
+ .write_into(buf)?;
+ self.identifier.write_into(buf)?;
+ recipe.write_into(buf)?;
+ }
+ RecipeData::Stonecutting(recipe) => {
+ ResourceLocation::new("minecraft:stonecutting")
+ .unwrap()
+ .write_into(buf)?;
+ self.identifier.write_into(buf)?;
+ recipe.write_into(buf)?;
+ }
+ RecipeData::Smithing(recipe) => {
+ ResourceLocation::new("minecraft:smithing")
+ .unwrap()
+ .write_into(buf)?;
+ self.identifier.write_into(buf)?;
+ recipe.write_into(buf)?;
+ }
+ };
+ Ok(())
}
}