1
2
Fork 0
mirror of https://github.com/mat-1/azalea.git synced 2025-08-02 23:44:38 +00:00
azalea/azalea-protocol/src/packets/game/clientbound_declare_commands_packet.rs

242 lines
7.6 KiB
Rust
Executable file

use super::GamePacket;
use azalea_buf::McBuf;
use azalea_buf::McBufVarReadable;
use azalea_buf::{McBufReadable, McBufWritable, Readable, Writable};
use azalea_core::ResourceLocation;
use packet_macros::GamePacket;
use std::{
hash::Hash,
io::{Read, Write},
};
#[derive(Clone, Debug, McBuf, GamePacket)]
pub struct ClientboundDeclareCommandsPacket {
pub entries: Vec<BrigadierNodeStub>,
#[var]
pub root_index: i32,
}
#[derive(Hash, Debug, Clone)]
pub struct BrigadierNodeStub {}
#[derive(Debug, Clone)]
pub struct BrigadierNumber<T> {
min: Option<T>,
max: Option<T>,
}
impl<T: McBufReadable> McBufReadable for BrigadierNumber<T> {
fn read_into(buf: &mut impl Read) -> Result<Self, String> {
let flags = buf.read_byte()?;
let min = if flags & 0x01 != 0 {
Some(T::read_into(buf)?)
} else {
None
};
let max = if flags & 0x02 != 0 {
Some(T::read_into(buf)?)
} else {
None
};
Ok(BrigadierNumber { min, max })
}
}
impl<T: McBufWritable> McBufWritable for BrigadierNumber<T> {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
let mut flags = 0;
if self.min.is_some() {
flags |= 0x01;
}
if self.max.is_some() {
flags |= 0x02;
}
buf.write_byte(flags)?;
if let Some(min) = &self.min {
min.write_into(buf)?;
}
if let Some(max) = &self.max {
max.write_into(buf)?;
}
Ok(())
}
}
#[derive(Debug, Clone, Copy, McBuf)]
pub enum BrigadierString {
/// Reads a single word
SingleWord = 0,
// If it starts with a ", keeps reading until another " (allowing escaping with \). Otherwise behaves the same as SINGLE_WORD
QuotablePhrase = 1,
// Reads the rest of the content after the cursor. Quotes will not be removed.
GreedyPhrase = 2,
}
#[derive(Debug, Clone)]
pub enum BrigadierParser {
Bool,
Double(BrigadierNumber<f64>),
Float(BrigadierNumber<f32>),
Integer(BrigadierNumber<i32>),
Long(BrigadierNumber<i64>),
String(BrigadierString),
Entity { single: bool, players_only: bool },
GameProfile,
BlockPos,
ColumnPos,
Vec3,
Vec2,
BlockState,
BlockPredicate,
ItemStack,
ItemPredicate,
Color,
Component,
Message,
Nbt,
NbtPath,
Objective,
ObjectiveCriteira,
Operation,
Particle,
Rotation,
Angle,
ScoreboardSlot,
ScoreHolder { allows_multiple: bool },
Swizzle,
Team,
ItemSlot,
ResourceLocation,
MobEffect,
Function,
EntityAnchor,
IntRange,
FloatRange,
ItemEnchantment,
EntitySummon,
Dimension,
Uuid,
NbtTag,
NbtCompoundTag,
Time,
ResourceOrTag { registry_key: ResourceLocation },
Resource { registry_key: ResourceLocation },
TemplateMirror,
TemplateRotation,
}
impl McBufReadable for BrigadierParser {
fn read_into(buf: &mut impl Read) -> Result<Self, String> {
let parser_type = u32::var_read_into(buf)?;
match parser_type {
0 => Ok(BrigadierParser::Bool),
1 => Ok(BrigadierParser::Float(BrigadierNumber::read_into(buf)?)),
2 => Ok(BrigadierParser::Double(BrigadierNumber::read_into(buf)?)),
3 => Ok(BrigadierParser::Integer(BrigadierNumber::read_into(buf)?)),
4 => Ok(BrigadierParser::Long(BrigadierNumber::read_into(buf)?)),
5 => Ok(BrigadierParser::String(BrigadierString::read_into(buf)?)),
6 => {
let flags = buf.read_byte()?;
Ok(BrigadierParser::Entity {
single: flags & 0x01 != 0,
players_only: flags & 0x02 != 0,
})
}
7 => Ok(BrigadierParser::GameProfile),
8 => Ok(BrigadierParser::BlockPos),
9 => Ok(BrigadierParser::ColumnPos),
10 => Ok(BrigadierParser::Vec3),
11 => Ok(BrigadierParser::Vec2),
12 => Ok(BrigadierParser::BlockState),
13 => Ok(BrigadierParser::BlockPredicate),
14 => Ok(BrigadierParser::ItemStack),
15 => Ok(BrigadierParser::ItemPredicate),
16 => Ok(BrigadierParser::Color),
17 => Ok(BrigadierParser::Component),
18 => Ok(BrigadierParser::Message),
19 => Ok(BrigadierParser::NbtCompoundTag),
20 => Ok(BrigadierParser::NbtTag),
21 => Ok(BrigadierParser::NbtPath),
22 => Ok(BrigadierParser::Objective),
23 => Ok(BrigadierParser::ObjectiveCriteira),
24 => Ok(BrigadierParser::Operation),
25 => Ok(BrigadierParser::Particle),
26 => Ok(BrigadierParser::Angle),
27 => Ok(BrigadierParser::Rotation),
28 => Ok(BrigadierParser::ScoreboardSlot),
29 => {
let flags = buf.read_byte()?;
Ok(BrigadierParser::ScoreHolder {
allows_multiple: flags & 0x01 != 0,
})
}
30 => Ok(BrigadierParser::Swizzle),
31 => Ok(BrigadierParser::Team),
32 => Ok(BrigadierParser::ItemSlot),
33 => Ok(BrigadierParser::ResourceLocation),
34 => Ok(BrigadierParser::MobEffect),
35 => Ok(BrigadierParser::Function),
36 => Ok(BrigadierParser::EntityAnchor),
37 => Ok(BrigadierParser::IntRange),
38 => Ok(BrigadierParser::FloatRange),
39 => Ok(BrigadierParser::ItemEnchantment),
40 => Ok(BrigadierParser::EntitySummon),
41 => Ok(BrigadierParser::Dimension),
42 => Ok(BrigadierParser::Time),
43 => Ok(BrigadierParser::ResourceOrTag {
registry_key: ResourceLocation::read_into(buf)?,
}),
44 => Ok(BrigadierParser::Resource {
registry_key: ResourceLocation::read_into(buf)?,
}),
45 => Ok(BrigadierParser::TemplateMirror),
46 => Ok(BrigadierParser::TemplateRotation),
47 => Ok(BrigadierParser::Uuid),
_ => Err(format!("Unknown BrigadierParser type: {}", parser_type)),
}
}
}
// TODO: BrigadierNodeStub should have more stuff
impl McBufReadable for BrigadierNodeStub {
fn read_into(buf: &mut impl Read) -> Result<Self, String> {
let flags = u8::read_into(buf)?;
if flags > 31 {
println!(
"Warning: The flags from a Brigadier node are over 31 ({flags}; {flags:#b}). This is probably a bug.",
);
}
let node_type = flags & 0x03;
let _is_executable = flags & 0x04 != 0;
let has_redirect = flags & 0x08 != 0;
let has_suggestions_type = flags & 0x10 != 0;
let _children = buf.read_int_id_list()?;
let _redirect_node = if has_redirect { buf.read_varint()? } else { 0 };
// argument node
if node_type == 2 {
let _name = buf.read_utf()?;
let _parser = BrigadierParser::read_into(buf)?;
let _suggestions_type = if has_suggestions_type {
Some(ResourceLocation::read_into(buf)?)
} else {
None
};
return Ok(BrigadierNodeStub {});
}
// literal node
if node_type == 1 {
let _name = buf.read_utf()?;
return Ok(BrigadierNodeStub {});
}
Ok(BrigadierNodeStub {})
// return Err("Unknown node type".to_string());
}
}
impl McBufWritable for BrigadierNodeStub {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
todo!()
}
}