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

Implement ALL packets (#16)

* add a couple more packets and improve codegen

* enums in packet codegen

* fix enums and MORE PACKETS

* make unsigned numbers the default

* codegen can make hashmaps

* UnsizedByteArray in codegen

* Vec and Option

* enum codgen works in more situations

* ServerboundInteractPacket

* Fix error with new error system

* More packets

* more packets

* more packets

* guess what was added

* yeah it's more packets

* add more packets

* packets

* start adding ClientboundBossEventPacket

* finish boss event packet

* improve codegen for linux

* start on command suggestions packet

* rename declare_commands to commands

* más paquetes

* fix generating custom payload packet

* more packets

* mehr Pakete

* improve codegen for movement packets

* rename move packets to have "packet" at the end

* fix some unused variable warns

* addere plus facis

* pli da pakoj

* plus de paquets

* più pacchetti

* make ChatFormatting a macro in azalea-chat

* change a match to matches! macro

* update SetPlayerTeam to use ChatFormatting

* ClientboundSetScorePacket & fix clippy warnings

* finish game state 🎉

* add remaining packets for other states

* fix error in ping.rs
This commit is contained in:
mat 2022-08-20 15:17:07 -05:00 committed by GitHub
parent ac4d675d44
commit dbb2092ac0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
129 changed files with 2799 additions and 222 deletions

View file

@ -18,7 +18,7 @@ fn create_impl_mcbufreadable(ident: &Ident, data: &Data) -> proc_macro2::TokenSt
// do a different buf.write_* for each field depending on the type
// if it's a string, use buf.write_string
match field_type {
syn::Type::Path(_) => {
syn::Type::Path(_) | syn::Type::Array(_) => {
if f.attrs.iter().any(|a| a.path.is_ident("var")) {
quote! {
let #field_name = azalea_buf::McBufVarReadable::var_read_from(buf)?;
@ -112,7 +112,7 @@ fn create_impl_mcbufwritable(ident: &Ident, data: &Data) -> proc_macro2::TokenSt
// do a different buf.write_* for each field depending on the type
// if it's a string, use buf.write_string
match field_type {
syn::Type::Path(_) => {
syn::Type::Path(_) | syn::Type::Array(_) => {
if f.attrs.iter().any(|attr| attr.path.is_ident("var")) {
quote! {
azalea_buf::McBufVarWritable::var_write_into(&self.#field_name, buf)?;

View file

@ -24,6 +24,8 @@ pub enum BufReadError {
InvalidUtf8,
#[error("Unexpected enum variant {id}")]
UnexpectedEnumVariant { id: i32 },
#[error("Unexpected enum variant {id}")]
UnexpectedStringEnumVariant { id: String },
#[error("{0}")]
Custom(String),
#[cfg(feature = "serde_json")]
@ -281,6 +283,19 @@ impl<K: McBufReadable + Send + Eq + Hash, V: McBufReadable + Send> McBufReadable
}
}
impl<K: McBufReadable + Send + Eq + Hash, V: McBufVarReadable + Send> McBufVarReadable
for HashMap<K, V>
{
default fn var_read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
let length = buf.read_varint()? as usize;
let mut contents = HashMap::with_capacity(length);
for _ in 0..length {
contents.insert(K::read_from(buf)?, V::var_read_from(buf)?);
}
Ok(contents)
}
}
impl McBufReadable for Vec<u8> {
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
buf.read_byte_array()
@ -386,3 +401,27 @@ impl<T: McBufReadable> McBufReadable for Option<T> {
})
}
}
impl<T: McBufVarReadable> McBufVarReadable for Option<T> {
default fn var_read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
let present = buf.read_boolean()?;
Ok(if present {
Some(T::var_read_from(buf)?)
} else {
None
})
}
}
// [String; 4]
impl<T: McBufReadable, const N: usize> McBufReadable for [T; N] {
default fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
let mut contents = Vec::with_capacity(N);
for _ in 0..N {
contents.push(T::read_from(buf)?);
}
contents.try_into().map_err(|_| {
panic!("Panic is not possible since the Vec is the same size as the array")
})
}
}

View file

@ -155,6 +155,18 @@ impl<K: McBufWritable, V: McBufWritable> McBufWritable for HashMap<K, V> {
}
}
impl<K: McBufWritable, V: McBufVarWritable> McBufVarWritable for HashMap<K, V> {
default fn var_write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
u32::var_write_into(&(self.len() as u32), buf)?;
for (key, value) in self {
key.write_into(buf)?;
value.var_write_into(buf)?;
}
Ok(())
}
}
impl McBufWritable for Vec<u8> {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
buf.write_byte_array(self)
@ -284,3 +296,25 @@ impl<T: McBufWritable> McBufWritable for Option<T> {
Ok(())
}
}
impl<T: McBufVarWritable> McBufVarWritable for Option<T> {
default fn var_write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
if let Some(s) = self {
buf.write_boolean(true)?;
s.var_write_into(buf)?;
} else {
buf.write_boolean(false)?;
};
Ok(())
}
}
// [T; N]
impl<T: McBufWritable, const N: usize> McBufWritable for [T; N] {
default fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
for i in self {
i.write_into(buf)?;
}
Ok(())
}
}

View file

@ -18,7 +18,7 @@ pub enum Component {
lazy_static! {
pub static ref DEFAULT_STYLE: Style = Style {
color: Some(ChatFormatting::WHITE.try_into().unwrap()),
color: Some(ChatFormatting::White.try_into().unwrap()),
..Style::default()
};
}

View file

@ -1,5 +1,6 @@
use std::{collections::HashMap, fmt};
use azalea_buf::McBuf;
use serde_json::Value;
#[derive(Clone, PartialEq, Eq, Debug)]
@ -28,15 +29,15 @@ impl TextColor {
}
lazy_static! {
static ref LEGACY_FORMAT_TO_COLOR: HashMap<&'static ChatFormatting<'static>, TextColor> = {
static ref LEGACY_FORMAT_TO_COLOR: HashMap<&'static ChatFormatting, TextColor> = {
let mut legacy_format_to_color = HashMap::new();
for formatter in &ChatFormatting::FORMATTERS {
if !formatter.is_format && *formatter != ChatFormatting::RESET {
if !formatter.is_format() && *formatter != ChatFormatting::Reset {
legacy_format_to_color.insert(
formatter,
TextColor {
value: formatter.color.unwrap(),
name: Some(formatter.name.to_string()),
value: formatter.color().unwrap(),
name: Some(formatter.name().to_string()),
},
);
}
@ -52,15 +53,6 @@ lazy_static! {
};
}
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub struct ChatFormatting<'a> {
pub name: &'a str,
pub code: char,
pub is_format: bool,
pub id: i32,
pub color: Option<u32>,
}
pub struct Ansi {}
impl Ansi {
pub const BOLD: &'static str = "\u{1b}[1m";
@ -80,91 +72,172 @@ impl Ansi {
}
}
impl<'a> ChatFormatting<'a> {
pub const BLACK: ChatFormatting<'a> = ChatFormatting::new("BLACK", '0', false, 0, Some(0));
pub const DARK_BLUE: ChatFormatting<'a> =
ChatFormatting::new("DARK_BLUE", '1', false, 1, Some(170));
pub const DARK_GREEN: ChatFormatting<'a> =
ChatFormatting::new("DARK_GREEN", '2', false, 2, Some(43520));
pub const DARK_AQUA: ChatFormatting<'a> =
ChatFormatting::new("DARK_AQUA", '3', false, 3, Some(43690));
pub const DARK_RED: ChatFormatting<'a> =
ChatFormatting::new("DARK_RED", '4', false, 4, Some(1114112));
pub const DARK_PURPLE: ChatFormatting<'a> =
ChatFormatting::new("DARK_PURPLE", '5', false, 5, Some(11141290));
pub const GOLD: ChatFormatting<'a> = ChatFormatting::new("GOLD", '6', false, 6, Some(16755200));
pub const GRAY: ChatFormatting<'a> = ChatFormatting::new("GRAY", '7', false, 7, Some(11184810));
pub const DARK_GRAY: ChatFormatting<'a> =
ChatFormatting::new("DARK_GRAY", '8', false, 8, Some(5592405));
pub const BLUE: ChatFormatting<'a> = ChatFormatting::new("BLUE", '9', false, 9, Some(5592575));
pub const GREEN: ChatFormatting<'a> =
ChatFormatting::new("GREEN", 'a', false, 10, Some(5635925));
pub const AQUA: ChatFormatting<'a> = ChatFormatting::new("AQUA", 'b', false, 11, Some(5636095));
pub const RED: ChatFormatting<'a> = ChatFormatting::new("RED", 'c', false, 12, Some(16733525));
pub const LIGHT_PURPLE: ChatFormatting<'a> =
ChatFormatting::new("LIGHT_PURPLE", 'd', false, 13, Some(16733695));
pub const YELLOW: ChatFormatting<'a> =
ChatFormatting::new("YELLOW", 'e', false, 14, Some(16777045));
pub const WHITE: ChatFormatting<'a> =
ChatFormatting::new("WHITE", 'f', false, 15, Some(16777215));
pub const OBFUSCATED: ChatFormatting<'a> =
ChatFormatting::new("OBFUSCATED", 'k', true, -1, None);
pub const STRIKETHROUGH: ChatFormatting<'a> =
ChatFormatting::new("STRIKETHROUGH", 'm', true, -1, None);
pub const BOLD: ChatFormatting<'a> = ChatFormatting::new("BOLD", 'l', true, -1, None);
pub const UNDERLINE: ChatFormatting<'a> = ChatFormatting::new("UNDERLINE", 'n', true, -1, None);
pub const ITALIC: ChatFormatting<'a> = ChatFormatting::new("ITALIC", 'o', true, -1, None);
pub const RESET: ChatFormatting<'a> = ChatFormatting::new("RESET", 'r', true, -1, None);
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, McBuf)]
pub enum ChatFormatting {
Black,
DarkBlue,
DarkGreen,
DarkAqua,
DarkRed,
DarkPurple,
Gold,
Gray,
DarkGray,
Blue,
Green,
Aqua,
Red,
LightPurple,
Yellow,
White,
Obfuscated,
Strikethrough,
Bold,
Underline,
Italic,
Reset,
}
pub const FORMATTERS: [ChatFormatting<'a>; 22] = [
ChatFormatting::BLACK,
ChatFormatting::DARK_BLUE,
ChatFormatting::DARK_GREEN,
ChatFormatting::DARK_AQUA,
ChatFormatting::DARK_RED,
ChatFormatting::DARK_PURPLE,
ChatFormatting::GOLD,
ChatFormatting::GRAY,
ChatFormatting::DARK_GRAY,
ChatFormatting::BLUE,
ChatFormatting::GREEN,
ChatFormatting::AQUA,
ChatFormatting::RED,
ChatFormatting::LIGHT_PURPLE,
ChatFormatting::YELLOW,
ChatFormatting::WHITE,
ChatFormatting::OBFUSCATED,
ChatFormatting::STRIKETHROUGH,
ChatFormatting::BOLD,
ChatFormatting::UNDERLINE,
ChatFormatting::ITALIC,
ChatFormatting::RESET,
impl ChatFormatting {
pub const FORMATTERS: [ChatFormatting; 22] = [
ChatFormatting::Black,
ChatFormatting::DarkBlue,
ChatFormatting::DarkGreen,
ChatFormatting::DarkAqua,
ChatFormatting::DarkRed,
ChatFormatting::DarkPurple,
ChatFormatting::Gold,
ChatFormatting::Gray,
ChatFormatting::DarkGray,
ChatFormatting::Blue,
ChatFormatting::Green,
ChatFormatting::Aqua,
ChatFormatting::Red,
ChatFormatting::LightPurple,
ChatFormatting::Yellow,
ChatFormatting::White,
ChatFormatting::Obfuscated,
ChatFormatting::Strikethrough,
ChatFormatting::Bold,
ChatFormatting::Underline,
ChatFormatting::Italic,
ChatFormatting::Reset,
];
const fn new(
name: &str,
code: char,
is_format: bool,
id: i32,
color: Option<u32>,
) -> ChatFormatting {
ChatFormatting {
name,
code,
is_format,
id,
color,
pub fn name(&self) -> &'static str {
match self {
ChatFormatting::Black => "BLACK",
ChatFormatting::DarkBlue => "DARK_BLUE",
ChatFormatting::DarkGreen => "DARK_GREEN",
ChatFormatting::DarkAqua => "DARK_AQUA",
ChatFormatting::DarkRed => "DARK_RED",
ChatFormatting::DarkPurple => "DARK_PURPLE",
ChatFormatting::Gold => "GOLD",
ChatFormatting::Gray => "GRAY",
ChatFormatting::DarkGray => "DARK_GRAY",
ChatFormatting::Blue => "BLUE",
ChatFormatting::Green => "GREEN",
ChatFormatting::Aqua => "AQUA",
ChatFormatting::Red => "RED",
ChatFormatting::LightPurple => "LIGHT_PURPLE",
ChatFormatting::Yellow => "YELLOW",
ChatFormatting::White => "WHITE",
ChatFormatting::Obfuscated => "OBFUSCATED",
ChatFormatting::Strikethrough => "STRIKETHROUGH",
ChatFormatting::Bold => "BOLD",
ChatFormatting::Underline => "UNDERLINE",
ChatFormatting::Italic => "ITALIC",
ChatFormatting::Reset => "RESET",
}
}
pub fn from_code(code: char) -> Option<&'static ChatFormatting<'static>> {
for formatter in &ChatFormatting::FORMATTERS {
if formatter.code == code {
return Some(formatter);
pub fn code(&self) -> char {
match self {
ChatFormatting::Black => '0',
ChatFormatting::DarkBlue => '1',
ChatFormatting::DarkGreen => '2',
ChatFormatting::DarkAqua => '3',
ChatFormatting::DarkRed => '4',
ChatFormatting::DarkPurple => '5',
ChatFormatting::Gold => '6',
ChatFormatting::Gray => '7',
ChatFormatting::DarkGray => '8',
ChatFormatting::Blue => '9',
ChatFormatting::Green => 'a',
ChatFormatting::Aqua => 'b',
ChatFormatting::Red => 'c',
ChatFormatting::LightPurple => 'd',
ChatFormatting::Yellow => 'e',
ChatFormatting::White => 'f',
ChatFormatting::Obfuscated => 'k',
ChatFormatting::Strikethrough => 'm',
ChatFormatting::Bold => 'l',
ChatFormatting::Underline => 'n',
ChatFormatting::Italic => 'o',
ChatFormatting::Reset => 'r',
}
}
None
pub fn from_code(code: char) -> Option<ChatFormatting> {
match code {
'0' => Some(ChatFormatting::Black),
'1' => Some(ChatFormatting::DarkBlue),
'2' => Some(ChatFormatting::DarkGreen),
'3' => Some(ChatFormatting::DarkAqua),
'4' => Some(ChatFormatting::DarkRed),
'5' => Some(ChatFormatting::DarkPurple),
'6' => Some(ChatFormatting::Gold),
'7' => Some(ChatFormatting::Gray),
'8' => Some(ChatFormatting::DarkGray),
'9' => Some(ChatFormatting::Blue),
'a' => Some(ChatFormatting::Green),
'b' => Some(ChatFormatting::Aqua),
'c' => Some(ChatFormatting::Red),
'd' => Some(ChatFormatting::LightPurple),
'e' => Some(ChatFormatting::Yellow),
'f' => Some(ChatFormatting::White),
'k' => Some(ChatFormatting::Obfuscated),
'm' => Some(ChatFormatting::Strikethrough),
'l' => Some(ChatFormatting::Bold),
'n' => Some(ChatFormatting::Underline),
'o' => Some(ChatFormatting::Italic),
'r' => Some(ChatFormatting::Reset),
_ => None,
}
}
pub fn is_format(&self) -> bool {
matches!(
self,
ChatFormatting::Obfuscated
| ChatFormatting::Strikethrough
| ChatFormatting::Bold
| ChatFormatting::Underline
| ChatFormatting::Italic
| ChatFormatting::Reset
)
}
pub fn color(&self) -> Option<u32> {
match self {
ChatFormatting::Black => Some(0),
ChatFormatting::DarkBlue => Some(170),
ChatFormatting::DarkGreen => Some(43520),
ChatFormatting::DarkAqua => Some(43690),
ChatFormatting::DarkRed => Some(1114112),
ChatFormatting::DarkPurple => Some(11141290),
ChatFormatting::Gold => Some(16755200),
ChatFormatting::Gray => Some(11184810),
ChatFormatting::DarkGray => Some(5592405),
ChatFormatting::Blue => Some(5592575),
ChatFormatting::Green => Some(5635925),
ChatFormatting::Aqua => Some(5636095),
ChatFormatting::Red => Some(16733525),
ChatFormatting::LightPurple => Some(16733695),
ChatFormatting::Yellow => Some(16777045),
ChatFormatting::White => Some(16777215),
_ => None,
}
}
}
@ -189,15 +262,15 @@ impl fmt::Display for TextColor {
}
// from ChatFormatting to TextColor
impl TryFrom<ChatFormatting<'_>> for TextColor {
impl TryFrom<ChatFormatting> for TextColor {
type Error = String;
fn try_from(formatter: ChatFormatting<'_>) -> Result<Self, Self::Error> {
if formatter.is_format {
return Err(format!("{} is not a color", formatter.name));
fn try_from(formatter: ChatFormatting) -> Result<Self, Self::Error> {
if formatter.is_format() {
return Err(format!("{} is not a color", formatter.name()));
}
let color = formatter.color.unwrap_or(0);
Ok(Self::new(color, Some(formatter.name.to_string())))
let color = formatter.color().unwrap_or(0);
Ok(Self::new(color, Some(formatter.name().to_string())))
}
}
@ -363,21 +436,15 @@ impl Style {
/// Apply a ChatFormatting to this style
pub fn apply_formatting(&mut self, formatting: &ChatFormatting) {
match *formatting {
ChatFormatting::BOLD => self.bold = Some(true),
ChatFormatting::ITALIC => self.italic = Some(true),
ChatFormatting::UNDERLINE => self.underlined = Some(true),
ChatFormatting::STRIKETHROUGH => self.strikethrough = Some(true),
ChatFormatting::OBFUSCATED => self.obfuscated = Some(true),
ChatFormatting::RESET => self.reset = true,
ChatFormatting {
name: _,
code: _,
is_format: _,
id: _,
color,
} => {
ChatFormatting::Bold => self.bold = Some(true),
ChatFormatting::Italic => self.italic = Some(true),
ChatFormatting::Underline => self.underlined = Some(true),
ChatFormatting::Strikethrough => self.strikethrough = Some(true),
ChatFormatting::Obfuscated => self.obfuscated = Some(true),
ChatFormatting::Reset => self.reset = true,
formatter => {
// if it's a color, set it
if let Some(color) = color {
if let Some(color) = formatter.color() {
self.color = Some(TextColor::from_rgb(color));
}
}
@ -455,7 +522,7 @@ mod tests {
format!(
"{reset}{italic}{white}",
reset = Ansi::RESET,
white = Ansi::rgb(ChatFormatting::WHITE.color.unwrap()),
white = Ansi::rgb(ChatFormatting::White.color().unwrap()),
italic = Ansi::ITALIC
)
)
@ -465,15 +532,15 @@ mod tests {
fn test_from_code() {
assert_eq!(
ChatFormatting::from_code('a').unwrap(),
&ChatFormatting::GREEN
ChatFormatting::Green
);
}
#[test]
fn test_apply_formatting() {
let mut style = Style::default();
style.apply_formatting(&ChatFormatting::BOLD);
style.apply_formatting(&ChatFormatting::RED);
style.apply_formatting(&ChatFormatting::Bold);
style.apply_formatting(&ChatFormatting::Red);
assert_eq!(style.color, Some(TextColor::from_rgb(16733525)));
}
}

View file

@ -29,7 +29,7 @@ pub fn legacy_color_code_to_text_component(legacy_color_code: &str) -> TextCompo
let style = &mut components.last_mut().unwrap().base.style;
// if the formatter is a reset, then we need to reset the style to the default
style.apply_formatting(formatter);
style.apply_formatting(&formatter);
}
i += 1;
} else {
@ -93,9 +93,9 @@ mod tests {
component.to_ansi(None),
format!(
"{GREEN}Hypixel Network {RED}[1.8-1.18]\n{BOLD}{AQUA}HAPPY HOLIDAYS{RESET}",
GREEN = Ansi::rgb(ChatFormatting::GREEN.color.unwrap()),
RED = Ansi::rgb(ChatFormatting::RED.color.unwrap()),
AQUA = Ansi::rgb(ChatFormatting::AQUA.color.unwrap()),
GREEN = Ansi::rgb(ChatFormatting::Green.color().unwrap()),
RED = Ansi::rgb(ChatFormatting::Red.color().unwrap()),
AQUA = Ansi::rgb(ChatFormatting::Aqua.color().unwrap()),
BOLD = Ansi::BOLD,
RESET = Ansi::RESET
)
@ -111,11 +111,11 @@ mod tests {
"{BOLD}Hello {RESET}{DARK_BLUE}w{DARK_GREEN}o{DARK_AQUA}r{DARK_RED}l{DARK_PURPLE}d{RESET}",
BOLD = Ansi::BOLD,
RESET = Ansi::RESET,
DARK_BLUE = Ansi::rgb(ChatFormatting::DARK_BLUE.color.unwrap()),
DARK_GREEN = Ansi::rgb(ChatFormatting::DARK_GREEN.color.unwrap()),
DARK_AQUA = Ansi::rgb(ChatFormatting::DARK_AQUA.color.unwrap()),
DARK_RED = Ansi::rgb(ChatFormatting::DARK_RED.color.unwrap()),
DARK_PURPLE = Ansi::rgb(ChatFormatting::DARK_PURPLE.color.unwrap())
DARK_BLUE = Ansi::rgb(ChatFormatting::DarkBlue.color().unwrap()),
DARK_GREEN = Ansi::rgb(ChatFormatting::DarkGreen.color().unwrap()),
DARK_AQUA = Ansi::rgb(ChatFormatting::DarkAqua.color().unwrap()),
DARK_RED = Ansi::rgb(ChatFormatting::DarkRed.color().unwrap()),
DARK_PURPLE = Ansi::rgb(ChatFormatting::DarkPurple.color().unwrap())
)
);
}

View file

@ -59,7 +59,7 @@ fn complex_ansi_test() {
bold = Ansi::BOLD,
italic = Ansi::ITALIC,
underlined = Ansi::UNDERLINED,
red = Ansi::rgb(ChatFormatting::RED.color.unwrap()),
red = Ansi::rgb(ChatFormatting::Red.color().unwrap()),
reset = Ansi::RESET,
strikethrough = Ansi::STRIKETHROUGH,
abcdef = Ansi::rgb(TextColor::parse("#abcdef".to_string()).unwrap().value),

View file

@ -11,7 +11,7 @@ use azalea_protocol::{
serverbound_accept_teleportation_packet::ServerboundAcceptTeleportationPacket,
serverbound_custom_payload_packet::ServerboundCustomPayloadPacket,
serverbound_keep_alive_packet::ServerboundKeepAlivePacket,
serverbound_move_player_packet_pos_rot::ServerboundMovePlayerPacketPosRot,
serverbound_move_player_pos_rot_packet::ServerboundMovePlayerPacketPosRot,
ClientboundGamePacket, ServerboundGamePacket,
},
handshake::client_intention_packet::ClientIntentionPacket,
@ -339,7 +339,7 @@ impl Client {
ClientboundGamePacket::ClientboundChangeDifficultyPacket(p) => {
println!("Got difficulty packet {:?}", p);
}
ClientboundGamePacket::ClientboundDeclareCommandsPacket(_p) => {
ClientboundGamePacket::ClientboundCommandsPacket(_p) => {
println!("Got declare commands packet");
}
ClientboundGamePacket::ClientboundPlayerAbilitiesPacket(p) => {
@ -562,7 +562,7 @@ impl Client {
.move_entity_with_delta(p.entity_id, &p.delta)
.map_err(|e| HandleError::Other(e.into()))?;
}
ClientboundGamePacket::ClientboundMoveEntityPosrotPacket(p) => {
ClientboundGamePacket::ClientboundMoveEntityPosRotPacket(p) => {
let mut dimension_lock = client.dimension.lock()?;
let dimension = dimension_lock.as_mut().unwrap();

View file

@ -1,6 +1,6 @@
use crate::Client;
use azalea_core::EntityPos;
use azalea_protocol::packets::game::serverbound_move_player_packet_pos_rot::ServerboundMovePlayerPacketPosRot;
use azalea_protocol::packets::game::serverbound_move_player_pos_rot_packet::ServerboundMovePlayerPacketPosRot;
use azalea_world::MoveEntityError;
use thiserror::Error;

View file

@ -52,7 +52,12 @@ pub async fn ping_server(
let packet = conn.read().await?;
loop {
match packet {
ClientboundStatusPacket::ClientboundStatusResponsePacket(p) => Ok(p),
ClientboundStatusPacket::ClientboundStatusResponsePacket(p) => return Ok(p),
ClientboundStatusPacket::ClientboundPongResponsePacket(_) => {
// we should never get this packet since we didn't send a ping
}
}
}
}

View file

@ -0,0 +1,12 @@
use azalea_buf::McBuf;
use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundAddExperienceOrbPacket {
#[var]
pub id: u32,
pub x: f64,
pub y: f64,
pub z: f64,
pub value: u16,
}

View file

@ -0,0 +1,18 @@
use azalea_buf::McBuf;
use packet_macros::ClientboundGamePacket;
use std::collections::HashMap;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundAwardStatsPacket {
#[var]
pub stats: HashMap<Stat, i32>,
}
#[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,
}

View file

@ -0,0 +1,13 @@
use azalea_buf::McBuf;
use azalea_core::BlockPos;
use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundBlockDestructionPacket {
/// The ID of the entity breaking the block.
#[var]
pub id: u32,
pub pos: BlockPos,
/// 09 to set it, any other value to remove it.
pub progress: u8,
}

View file

@ -0,0 +1,12 @@
use azalea_buf::McBuf;
use azalea_core::BlockPos;
use packet_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 tag: azalea_nbt::Tag,
}

View file

@ -0,0 +1,13 @@
use azalea_buf::McBuf;
use azalea_core::BlockPos;
use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
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,
}

View file

@ -6,8 +6,7 @@ use packet_macros::ClientboundGamePacket;
pub struct ClientboundBlockUpdatePacket {
pub pos: BlockPos,
// TODO: in vanilla this is a BlockState, but here we just have it as a number.
// however, we can't add azalea-world as a dependency because it depends on us.
// we could have a crate that contains encoding/decoding and the definitions?
// perhaps we could make a crate that only handles block states? right now blockstates are handled in azalea-block
#[var]
pub block_state: u32,
}

View file

@ -0,0 +1,143 @@
use std::io::{Read, Write};
use azalea_buf::{
BufReadError, McBuf, McBufReadable, McBufVarReadable, McBufVarWritable, McBufWritable,
};
use azalea_chat::component::Component;
use packet_macros::ClientboundGamePacket;
use uuid::Uuid;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundBossEventPacket {
pub id: Uuid,
pub operation: Operation,
}
#[derive(Clone, Debug)]
pub enum Operation {
Add(AddOperation),
Remove,
UpdateProgress(f32),
UpdateName(Component),
UpdateStyle(Style),
UpdateProperties(Properties),
}
impl McBufReadable for Operation {
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
let operation_id = u32::var_read_from(buf)?;
Ok(match operation_id {
0 => Operation::Add(AddOperation::read_from(buf)?),
1 => Operation::Remove,
2 => Operation::UpdateProgress(f32::read_from(buf)?),
3 => Operation::UpdateName(Component::read_from(buf)?),
4 => Operation::UpdateStyle(Style::read_from(buf)?),
5 => Operation::UpdateProperties(Properties::read_from(buf)?),
_ => {
return Err(BufReadError::UnexpectedEnumVariant {
id: operation_id as i32,
})
}
})
}
}
impl McBufWritable for Operation {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
match self {
Operation::Add(add) => {
0u32.var_write_into(buf)?;
add.write_into(buf)?;
}
Operation::Remove => {
1u32.var_write_into(buf)?;
}
Operation::UpdateProgress(progress) => {
2u32.var_write_into(buf)?;
progress.write_into(buf)?;
}
Operation::UpdateName(name) => {
3u32.var_write_into(buf)?;
name.write_into(buf)?;
}
Operation::UpdateStyle(style) => {
4u32.var_write_into(buf)?;
style.write_into(buf)?;
}
Operation::UpdateProperties(properties) => {
5u32.var_write_into(buf)?;
properties.write_into(buf)?;
}
}
Ok(())
}
}
#[derive(Clone, Debug, McBuf)]
pub struct AddOperation {
name: Component,
progress: f32,
style: Style,
properties: Properties,
}
#[derive(Clone, Debug, McBuf)]
pub struct Style {
color: BossBarColor,
overlay: BossBarOverlay,
}
#[derive(McBuf, Clone, Copy, Debug)]
pub enum BossBarColor {
Pink = 0,
Blue = 1,
Red = 2,
Green = 3,
Yellow = 4,
Purple = 5,
White = 6,
}
#[derive(McBuf, Clone, Copy, Debug)]
pub enum BossBarOverlay {
Progress = 0,
Notched6 = 1,
Notched10 = 2,
Notched12 = 3,
Notched20 = 4,
}
#[derive(Clone, Debug)]
pub struct Properties {
pub darken_screen: bool,
pub play_music: bool,
pub create_world_fog: bool,
}
impl McBufReadable for Properties {
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
let byte = u8::read_from(buf)?;
Ok(Self {
darken_screen: byte & 1 != 0,
play_music: byte & 2 != 0,
create_world_fog: byte & 4 != 0,
})
}
}
impl McBufWritable for Properties {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
let mut byte = 0;
if self.darken_screen {
byte |= 1;
}
if self.play_music {
byte |= 2;
}
if self.create_world_fog {
byte |= 4;
}
u8::write_into(&byte, buf)?;
Ok(())
}
}

View file

@ -0,0 +1,32 @@
// use azalea_brigadier::context::StringRange;
use azalea_buf::{
// BufReadError, McBuf, McBufReadable, McBufVarReadable, McBufVarWritable, McBufWritable,
BufReadError,
McBufReadable,
McBufWritable,
};
use packet_macros::ClientboundGamePacket;
use std::io::{Read, Write};
#[derive(Clone, Debug, ClientboundGamePacket)]
pub struct ClientboundCommandSuggestionsPacket {
#[var]
pub id: u32,
// pub suggestions: Suggestions,
}
impl McBufReadable for ClientboundCommandSuggestionsPacket {
fn read_from(_buf: &mut impl Read) -> 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")
}
}
impl McBufWritable for ClientboundCommandSuggestionsPacket {
fn write_into(&self, _buf: &mut impl Write) -> Result<(), std::io::Error> {
todo!()
}
}

View file

@ -10,7 +10,7 @@ use std::{
};
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundDeclareCommandsPacket {
pub struct ClientboundCommandsPacket {
pub entries: Vec<BrigadierNodeStub>,
#[var]
pub root_index: i32,

View file

@ -0,0 +1,9 @@
use azalea_buf::McBuf;
use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundContainerSetDataPacket {
pub container_id: u8,
pub id: u16,
pub value: u16,
}

View file

@ -0,0 +1,12 @@
use azalea_buf::McBuf;
use azalea_core::Slot;
use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundContainerSetSlotPacket {
pub container_id: u8,
#[var]
pub state_id: u32,
pub slot: u16,
pub item_stack: Slot,
}

View file

@ -0,0 +1,11 @@
use azalea_buf::McBuf;
use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundCooldownPacket {
// TODO: make azalea-items or something and use that
#[var]
pub item: u32,
#[var]
pub duration: u32,
}

View file

@ -7,7 +7,7 @@ pub struct ClientboundCustomChatCompletionsPacket {
pub entries: Vec<String>,
}
#[derive(Clone, Debug, McBuf, Copy)]
#[derive(McBuf, Clone, Copy, Debug)]
pub enum Action {
Add = 0,
Remove = 1,

View file

@ -0,0 +1,20 @@
use azalea_buf::McBuf;
use azalea_core::ResourceLocation;
use packet_macros::ClientboundGamePacket;
use super::clientbound_sound_packet::SoundSource;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundCustomSoundPacket {
pub name: ResourceLocation,
pub source: SoundSource,
/// x position multiplied by 8
pub x: i32,
/// y position multiplied by 8
pub y: i32,
/// z position multiplied by 8
pub z: i32,
pub volume: f32,
pub pitch: f32,
pub seed: u64,
}

View file

@ -1,7 +1,6 @@
use azalea_buf::McBuf;
use packet_macros::ClientboundGamePacket;
// we can't identify the status in azalea-protocol since they vary depending on the entity
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundEntityEventPacket {
pub entity_id: u32,

View file

@ -0,0 +1,118 @@
use azalea_buf::{BufReadError, McBufReadable, McBufVarReadable, McBufVarWritable, McBufWritable};
use azalea_core::BlockPos;
use packet_macros::ClientboundGamePacket;
use std::io::{Read, Write};
#[derive(Clone, Debug, PartialEq, ClientboundGamePacket)]
pub struct ClientboundExplodePacket {
pub x: f32,
pub y: f32,
pub z: f32,
pub power: f32,
pub to_blow: Vec<BlockPos>,
pub knockback_x: f32,
pub knockback_y: f32,
pub knockback_z: f32,
}
impl McBufReadable for ClientboundExplodePacket {
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
let x = f32::read_from(buf)?;
let y = f32::read_from(buf)?;
let z = f32::read_from(buf)?;
let power = f32::read_from(buf)?;
let x_floor = x.floor() as i32;
let y_floor = y.floor() as i32;
let z_floor = z.floor() as i32;
let to_blow_len = u32::var_read_from(buf)?;
let mut to_blow = Vec::with_capacity(to_blow_len as usize);
for _ in 0..to_blow_len {
// the bytes are offsets from the main x y z
let x = x_floor + i8::read_from(buf)? as i32;
let y = y_floor + i8::read_from(buf)? as i32;
let z = z_floor + i8::read_from(buf)? as i32;
to_blow.push(BlockPos { x, y, z });
}
let knockback_x = f32::read_from(buf)?;
let knockback_y = f32::read_from(buf)?;
let knockback_z = f32::read_from(buf)?;
Ok(Self {
x,
y,
z,
power,
to_blow,
knockback_x,
knockback_y,
knockback_z,
})
}
}
impl McBufWritable for ClientboundExplodePacket {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
self.x.write_into(buf)?;
self.y.write_into(buf)?;
self.z.write_into(buf)?;
self.power.write_into(buf)?;
let to_blow_len = self.to_blow.len() as u32;
to_blow_len.var_write_into(buf)?;
let x_floor = self.x.floor() as i32;
let y_floor = self.y.floor() as i32;
let z_floor = self.z.floor() as i32;
for pos in &self.to_blow {
let x = (pos.x - x_floor) as i8;
let y = (pos.y - y_floor) as i8;
let z = (pos.z - z_floor) as i8;
x.write_into(buf)?;
y.write_into(buf)?;
z.write_into(buf)?;
}
self.knockback_x.write_into(buf)?;
self.knockback_y.write_into(buf)?;
self.knockback_z.write_into(buf)?;
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_read_write() {
let packet = ClientboundExplodePacket {
x: 123_456.0,
y: 789_012.0,
z: 345_678.0,
power: 1_000.0,
to_blow: vec![
BlockPos {
x: 123_456 + 1,
y: 789_012 + 2,
z: 345_678 - 127,
},
BlockPos {
x: 123_456 + 4,
y: 789_012 - 5,
z: 345_678 + 6,
},
],
knockback_x: 1_000.0,
knockback_y: 2_000.0,
knockback_z: 3_000.0,
};
let mut buf = Vec::new();
packet.write_into(&mut buf).unwrap();
let packet2 = ClientboundExplodePacket::read_from(&mut buf.as_slice()).unwrap();
assert_eq!(packet, packet2);
}
}

View file

@ -0,0 +1,8 @@
use azalea_buf::McBuf;
use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundForgetLevelChunkPacket {
pub x: i32,
pub z: i32,
}

View file

@ -0,0 +1,10 @@
use azalea_buf::McBuf;
use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundHorseScreenOpenPacket {
pub container_id: u8,
#[var]
pub size: u32,
pub entity_id: u32,
}

View file

@ -4,8 +4,8 @@ use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundLevelEventPacket {
pub type_: i32,
pub event_type: u32,
pub pos: BlockPos,
pub data: i32,
pub data: u32,
pub global_event: bool,
}

View file

@ -3,7 +3,9 @@ use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundLightUpdatePacket {
#[var]
pub x: i32,
#[var]
pub z: i32,
pub light_data: ClientboundLightUpdatePacketData,
}

View file

@ -16,9 +16,9 @@ pub struct ClientboundLoginPacket {
#[var]
pub max_players: i32,
#[var]
pub chunk_radius: i32,
pub chunk_radius: u32,
#[var]
pub simulation_distance: i32,
pub simulation_distance: u32,
pub reduced_debug_info: bool,
pub show_death_screen: bool,
pub is_debug: bool,

View file

@ -0,0 +1,119 @@
use std::io::{Read, Write};
use azalea_buf::{BufReadError, McBuf};
use azalea_buf::{McBufReadable, McBufVarReadable, McBufVarWritable, McBufWritable};
use azalea_chat::component::Component;
use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, ClientboundGamePacket)]
pub struct ClientboundMapItemDataPacket {
// #[var]
pub map_id: u32,
pub scale: u8,
pub locked: bool,
pub decorations: Vec<MapDecoration>,
pub color_patch: Option<MapPatch>,
}
impl McBufReadable for ClientboundMapItemDataPacket {
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
let map_id = u32::var_read_from(buf)?;
let scale = u8::read_from(buf)?;
let locked = bool::read_from(buf)?;
let decorations = Vec::<MapDecoration>::read_from(buf)?;
let width = u8::read_from(buf)?;
let color_patch = if width == 0 {
None
} else {
let height = u8::read_from(buf)?;
let start_x = u8::read_from(buf)?;
let start_y = u8::read_from(buf)?;
let map_colors = Vec::<u8>::read_from(buf)?;
Some(MapPatch {
width,
height,
start_x,
start_y,
map_colors,
})
};
Ok(Self {
map_id,
scale,
locked,
decorations,
color_patch,
})
}
}
impl McBufWritable for ClientboundMapItemDataPacket {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
self.map_id.var_write_into(buf)?;
self.scale.write_into(buf)?;
self.locked.write_into(buf)?;
self.decorations.write_into(buf)?;
if let Some(color_patch) = &self.color_patch {
color_patch.width.write_into(buf)?;
color_patch.height.write_into(buf)?;
color_patch.start_x.write_into(buf)?;
color_patch.start_y.write_into(buf)?;
color_patch.map_colors.write_into(buf)?;
} else {
0u8.write_into(buf)?;
}
Ok(())
}
}
#[derive(Clone, Debug, McBuf)]
pub struct MapDecoration {
pub decoration_type: DecorationType,
pub x: i8,
pub y: i8,
/// Minecraft does & 15 on this value, azalea-protocol doesn't. I don't think it matters.
pub rot: i8,
pub name: Option<Component>,
}
#[derive(Debug, Clone)]
pub struct MapPatch {
pub start_x: u8,
pub start_y: u8,
pub width: u8,
pub height: u8,
pub map_colors: Vec<u8>,
}
#[derive(Clone, Copy, Debug, McBuf)]
pub enum DecorationType {
Player,
Frame,
RedMarker,
BlueMarker,
TargetX,
TargetPoint,
PlayerOffMap,
PlayerOffLimits,
Mansion,
Monument,
BannerWhite,
BannerOrange,
BannerMagenta,
BannerLightBlue,
BannerYellow,
BannerLime,
BannerPink,
BannerGray,
BannerLightGray,
BannerCyan,
BannerPurple,
BannerBlue,
BannerBrown,
BannerGreen,
BannerRed,
BannerBlack,
RedX,
}

View file

@ -0,0 +1,30 @@
use azalea_buf::McBuf;
use azalea_core::Slot;
use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundMerchantOffersPacket {
#[var]
pub container_id: u32,
pub offers: Vec<MerchantOffer>,
#[var]
pub villager_level: u32,
#[var]
pub villager_xp: u32,
pub show_progress: bool,
pub can_restock: bool,
}
#[derive(Clone, Debug, McBuf)]
pub struct MerchantOffer {
pub base_cost_a: Slot,
pub result: Slot,
pub cost_b: Slot,
pub out_of_stock: bool,
pub uses: u32,
pub max_uses: u32,
pub xp: u32,
pub special_price_diff: i32,
pub price_multiplier: f32,
pub demand: u32,
}

View file

@ -4,7 +4,7 @@ use packet_macros::ClientboundGamePacket;
/// This packet is sent by the server when an entity moves less then 8 blocks.
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundMoveEntityPosrotPacket {
pub struct ClientboundMoveEntityPosRotPacket {
#[var]
pub entity_id: u32,
pub delta: PositionDelta8,

View file

@ -4,7 +4,7 @@ use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundMoveEntityRotPacket {
#[var]
pub entity_id: i32,
pub entity_id: u32,
pub y_rot: i8,
pub x_rot: i8,
pub on_ground: bool,

View file

@ -0,0 +1,11 @@
use azalea_buf::McBuf;
use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundMoveVehiclePacket {
pub x: f64,
pub y: f64,
pub z: f64,
pub y_rot: f32,
pub x_rot: f32,
}

View file

@ -0,0 +1,8 @@
use super::serverbound_interact_packet::InteractionHand;
use azalea_buf::McBuf;
use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundOpenBookPacket {
pub hand: InteractionHand,
}

View file

@ -0,0 +1,13 @@
use azalea_buf::McBuf;
use azalea_chat::component::Component;
use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundOpenScreenPacket {
#[var]
pub container_id: u32,
// TODO: have an enum of this
#[var]
pub menu_type: u32,
pub title: Component,
}

View file

@ -0,0 +1,8 @@
use azalea_buf::McBuf;
use azalea_core::BlockPos;
use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundOpenSignEditorPacket {
pub pos: BlockPos,
}

View file

@ -0,0 +1,7 @@
use azalea_buf::McBuf;
use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundPingPacket {
pub id: u32,
}

View file

@ -0,0 +1,9 @@
use azalea_buf::McBuf;
use azalea_core::ResourceLocation;
use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundPlaceGhostRecipePacket {
pub container_id: u8,
pub recipe: ResourceLocation,
}

View file

@ -0,0 +1,9 @@
use azalea_buf::McBuf;
use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundPlayerCombatEndPacket {
#[var]
pub duration: u32,
pub killer_id: u32,
}

View file

@ -0,0 +1,5 @@
use azalea_buf::McBuf;
use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundPlayerCombatEnterPacket {}

View file

@ -0,0 +1,11 @@
use azalea_buf::McBuf;
use azalea_chat::component::Component;
use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundPlayerCombatKillPacket {
#[var]
pub player_id: u32,
pub killer_id: u32,
pub message: Component,
}

View file

@ -0,0 +1,24 @@
use azalea_buf::McBuf;
use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundPlayerLookAtPacket {
pub from_anchor: Anchor,
pub x: f64,
pub y: f64,
pub z: f64,
pub entity: Option<AtEntity>,
}
#[derive(McBuf, Clone, Copy, Debug)]
pub enum Anchor {
Feet = 0,
Eyes = 1,
}
#[derive(McBuf, Clone, Debug)]
pub struct AtEntity {
#[var]
pub entity: u32,
pub to_anchor: Anchor,
}

View file

@ -0,0 +1,11 @@
use azalea_buf::McBuf;
use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundRemoveMobEffectPacket {
#[var]
pub entity_id: u32,
// TODO: have this use an enum
#[var]
pub effect: u32,
}

View file

@ -0,0 +1,11 @@
use azalea_buf::McBuf;
use azalea_chat::component::Component;
use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundResourcePackPacket {
pub url: String,
pub hash: String,
pub required: bool,
pub prompt: Option<Component>,
}

View file

@ -0,0 +1,16 @@
use azalea_buf::McBuf;
use azalea_core::{GameType, GlobalPos, OptionalGameType, ResourceLocation};
use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundRespawnPacket {
pub dimension_type: ResourceLocation,
pub dimension: ResourceLocation,
pub seed: u64,
pub player_game_type: GameType,
pub previous_player_game_type: OptionalGameType,
pub is_debug: bool,
pub is_flat: bool,
pub keep_all_player_data: bool,
pub last_death_location: Option<GlobalPos>,
}

View file

@ -0,0 +1,8 @@
use azalea_buf::McBuf;
use azalea_core::ResourceLocation;
use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundSelectAdvancementsTabPacket {
pub tab: Option<ResourceLocation>,
}

View file

@ -0,0 +1,8 @@
use azalea_buf::McBuf;
use azalea_chat::component::Component;
use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundSetActionBarTextPacket {
pub text: Component,
}

View file

@ -0,0 +1,8 @@
use azalea_buf::McBuf;
use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundSetBorderCenterPacket {
pub new_center_x: f64,
pub new_center_z: f64,
}

View file

@ -0,0 +1,10 @@
use azalea_buf::McBuf;
use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundSetBorderLerpSizePacket {
pub old_size: f64,
pub new_size: f64,
#[var]
pub lerp_time: u64,
}

View file

@ -0,0 +1,7 @@
use azalea_buf::McBuf;
use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundSetBorderSizePacket {
pub size: f64,
}

View file

@ -0,0 +1,8 @@
use azalea_buf::McBuf;
use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundSetBorderWarningDelayPacket {
#[var]
pub warning_delay: u32,
}

View file

@ -0,0 +1,8 @@
use azalea_buf::McBuf;
use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundSetBorderWarningDistancePacket {
#[var]
pub warning_blocks: u32,
}

View file

@ -0,0 +1,8 @@
use azalea_buf::McBuf;
use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundSetCameraPacket {
#[var]
pub camera_id: u32,
}

View file

@ -0,0 +1,8 @@
use azalea_buf::McBuf;
use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundSetChunkCacheRadiusPacket {
#[var]
pub radius: u32,
}

View file

@ -0,0 +1,8 @@
use azalea_buf::McBuf;
use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundSetDisplayObjectivePacket {
pub slot: u8,
pub objective_name: String,
}

View file

@ -6,5 +6,5 @@ use packet_macros::ClientboundGamePacket;
pub struct ClientboundSetEntityDataPacket {
#[var]
pub id: u32,
pub metadata: EntityMetadata,
pub packed_items: EntityMetadata,
}

View file

@ -0,0 +1,11 @@
use azalea_buf::McBuf;
use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundSetEntityMotionPacket {
#[var]
pub id: u32,
pub xa: i16,
pub ya: i16,
pub za: i16,
}

View file

@ -0,0 +1,59 @@
use azalea_buf::{BufReadError, McBuf, McBufReadable, McBufWritable};
use azalea_chat::component::Component;
use packet_macros::ClientboundGamePacket;
use std::io::{Read, Write};
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundSetObjectivePacket {
pub objective_name: String,
pub method: Method,
}
#[derive(Clone, Debug)]
pub enum Method {
Add(DisplayInfo),
Remove,
Change(DisplayInfo),
}
impl McBufReadable for Method {
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
Ok(match u8::read_from(buf)? {
0 => Method::Add(DisplayInfo::read_from(buf)?),
1 => Method::Remove,
2 => Method::Change(DisplayInfo::read_from(buf)?),
id => return Err(BufReadError::UnexpectedEnumVariant { id: id as i32 }),
})
}
}
impl McBufWritable for Method {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
match self {
Method::Add(info) => {
0u8.write_into(buf)?;
info.write_into(buf)?;
}
Method::Remove => {
1u8.write_into(buf)?;
}
Method::Change(info) => {
2u8.write_into(buf)?;
info.write_into(buf)?;
}
}
Ok(())
}
}
#[derive(McBuf, Clone, Debug)]
pub struct DisplayInfo {
pub display_name: Component,
pub render_type: RenderType,
}
#[derive(McBuf, Copy, Clone, Debug)]
pub enum RenderType {
Integer,
Hearts,
}

View file

@ -0,0 +1,10 @@
use azalea_buf::McBuf;
use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundSetPassengersPacket {
#[var]
pub vehicle: u32,
#[var]
pub passengers: Vec<u32>,
}

View file

@ -0,0 +1,80 @@
use std::io::{Read, Write};
use azalea_buf::{BufReadError, McBuf, McBufReadable, McBufWritable};
use azalea_chat::{component::Component, style::ChatFormatting};
use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundSetPlayerTeamPacket {
pub name: String,
pub method: Method,
}
#[derive(Clone, Debug)]
pub enum Method {
Add((Parameters, PlayerList)),
Remove,
Change(Parameters),
Join(PlayerList),
Leave(PlayerList),
}
impl McBufReadable for Method {
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
Ok(match u8::read_from(buf)? {
0 => Method::Add((Parameters::read_from(buf)?, PlayerList::read_from(buf)?)),
1 => Method::Remove,
2 => Method::Change(Parameters::read_from(buf)?),
3 => Method::Join(PlayerList::read_from(buf)?),
4 => Method::Leave(PlayerList::read_from(buf)?),
id => return Err(BufReadError::UnexpectedEnumVariant { id: id as i32 }),
})
}
}
impl McBufWritable for Method {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
match self {
Method::Add((parameters, playerlist)) => {
0u8.write_into(buf)?;
parameters.write_into(buf)?;
playerlist.write_into(buf)?;
}
Method::Remove => {
1u8.write_into(buf)?;
}
Method::Change(parameters) => {
2u8.write_into(buf)?;
parameters.write_into(buf)?;
}
Method::Join(playerlist) => {
3u8.write_into(buf)?;
playerlist.write_into(buf)?;
}
Method::Leave(playerlist) => {
4u8.write_into(buf)?;
playerlist.write_into(buf)?;
}
}
Ok(())
}
}
#[derive(McBuf, Clone, Debug)]
pub struct Parameters {
pub display_name: Component,
pub options: u8,
pub nametag_visibility: String,
pub collision_rule: String,
pub color: ChatFormatting,
pub player_prefix: Component,
pub player_suffix: Component,
}
#[derive(McBuf, Copy, Clone, Debug)]
pub enum RenderType {
Integer,
Hearts,
}
type PlayerList = Vec<String>;

View file

@ -0,0 +1,61 @@
use azalea_buf::{BufReadError, McBufReadable, McBufVarReadable, McBufVarWritable, McBufWritable};
use packet_macros::ClientboundGamePacket;
use std::{
io::{Read, Write},
ops::Not,
};
#[derive(Clone, Debug, ClientboundGamePacket)]
pub struct ClientboundSetScorePacket {
pub owner: String,
pub method: Method,
pub objective_name: Option<String>,
}
impl McBufReadable for ClientboundSetScorePacket {
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
let owner = String::read_from(buf)?;
let method_id = u32::var_read_from(buf)?;
let objective_name = String::read_from(buf)?;
let objective_name = objective_name.is_empty().not().then_some(objective_name);
// if it's change, read the score
let method = match method_id {
0 => Method::Change {
score: u32::var_read_from(buf)?,
},
1 => Method::Remove,
id => return Err(BufReadError::UnexpectedEnumVariant { id: id as i32 }),
};
Ok(ClientboundSetScorePacket {
owner,
method,
objective_name,
})
}
}
impl McBufWritable for ClientboundSetScorePacket {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
self.owner.write_into(buf)?;
match self.method {
Method::Change { .. } => 0u32,
Method::Remove => 1u32,
}
.var_write_into(buf)?;
// convert None to an empty string
self.objective_name
.as_ref()
.unwrap_or(&"".to_string())
.write_into(buf)?;
if let Method::Change { score } = self.method {
score.var_write_into(buf)?;
}
Ok(())
}
}
#[derive(Clone, Copy, Debug)]
pub enum Method {
Change { score: u32 },
Remove,
}

View file

@ -0,0 +1,8 @@
use azalea_buf::McBuf;
use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundSetSimulationDistancePacket {
#[var]
pub simulation_distance: u32,
}

View file

@ -0,0 +1,8 @@
use azalea_buf::McBuf;
use azalea_chat::component::Component;
use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundSetSubtitleTextPacket {
pub text: Component,
}

View file

@ -0,0 +1,8 @@
use azalea_buf::McBuf;
use azalea_chat::component::Component;
use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundSetTitleTextPacket {
pub text: Component,
}

View file

@ -0,0 +1,9 @@
use azalea_buf::McBuf;
use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundSetTitlesAnimationPacket {
pub fade_in: u32,
pub stay: u32,
pub fade_out: u32,
}

View file

@ -0,0 +1,16 @@
use super::clientbound_sound_packet::SoundSource;
use azalea_buf::McBuf;
use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundSoundEntityPacket {
// TODO: sound enum/registry
#[var]
pub sound: u32,
pub source: SoundSource,
#[var]
pub id: u32,
pub volume: f32,
pub pitch: f32,
pub seed: u64,
}

View file

@ -3,8 +3,8 @@ use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundSoundPacket {
// TODO: sound enum/registry
#[var]
// TODO: use the sound registry instead of just being a u32
pub sound: u32,
pub source: SoundSource,
pub x: i32,
@ -12,11 +12,10 @@ pub struct ClientboundSoundPacket {
pub z: i32,
pub volume: f32,
pub pitch: f32,
/// Seed used to pick sound varient.
pub seed: u64,
}
#[derive(Clone, Debug, Copy, McBuf)]
#[derive(McBuf, Clone, Copy, Debug)]
pub enum SoundSource {
Master = 0,
Music = 1,

View file

@ -0,0 +1,51 @@
use std::io::{Read, Write};
use azalea_buf::{BufReadError, McBufReadable, McBufWritable};
use azalea_core::ResourceLocation;
use packet_macros::ClientboundGamePacket;
use super::clientbound_sound_packet::SoundSource;
#[derive(Clone, Debug, ClientboundGamePacket)]
pub struct ClientboundStopSoundPacket {
pub source: Option<SoundSource>,
pub name: Option<ResourceLocation>,
}
impl McBufReadable for ClientboundStopSoundPacket {
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
let byte = u8::read_from(buf)?;
let source = if byte & 1 != 0 {
Some(SoundSource::read_from(buf)?)
} else {
None
};
let name = if byte & 2 != 0 {
Some(ResourceLocation::read_from(buf)?)
} else {
None
};
Ok(Self { source, name })
}
}
impl McBufWritable for ClientboundStopSoundPacket {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
let mut byte = 0u8;
if self.source.is_some() {
byte |= 1;
}
if self.name.is_some() {
byte |= 2;
}
byte.write_into(buf)?;
if let Some(source) = &self.source {
source.write_into(buf)?;
}
if let Some(name) = &self.name {
name.write_into(buf)?;
}
Ok(())
}
}

View file

@ -0,0 +1,9 @@
use azalea_buf::McBuf;
use azalea_chat::component::Component;
use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundTabListPacket {
pub header: Component,
pub footer: Component,
}

View file

@ -0,0 +1,9 @@
use azalea_buf::McBuf;
use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundTagQueryPacket {
#[var]
pub transaction_id: u32,
pub tag: azalea_nbt::Tag,
}

View file

@ -0,0 +1,12 @@
use azalea_buf::McBuf;
use packet_macros::ClientboundGamePacket;
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
pub struct ClientboundTakeItemEntityPacket {
#[var]
pub item_id: u32,
#[var]
pub player_id: u32,
#[var]
pub amount: u32,
}

View file

@ -1,19 +1,33 @@
pub mod clientbound_add_entity_packet;
pub mod clientbound_add_experience_orb_packet;
pub mod clientbound_add_player_packet;
pub mod clientbound_animate_packet;
pub mod clientbound_award_stats_packet;
pub mod clientbound_block_changed_ack_packet;
pub mod clientbound_block_destruction_packet;
pub mod clientbound_block_entity_data_packet;
pub mod clientbound_block_event_packet;
pub mod clientbound_block_update_packet;
pub mod clientbound_boss_event_packet;
pub mod clientbound_change_difficulty_packet;
pub mod clientbound_chat_preview_packet;
pub mod clientbound_command_suggestions_packet;
pub mod clientbound_commands_packet;
pub mod clientbound_container_set_content_packet;
pub mod clientbound_container_set_data_packet;
pub mod clientbound_container_set_slot_packet;
pub mod clientbound_cooldown_packet;
pub mod clientbound_custom_chat_completions_packet;
pub mod clientbound_custom_payload_packet;
pub mod clientbound_declare_commands_packet;
pub mod clientbound_custom_sound_packet;
pub mod clientbound_delete_chat_packet;
pub mod clientbound_disconnect_packet;
pub mod clientbound_entity_event_packet;
pub mod clientbound_entity_velocity_packet;
pub mod clientbound_explode_packet;
pub mod clientbound_forget_level_chunk_packet;
pub mod clientbound_game_event_packet;
pub mod clientbound_horse_screen_open_packet;
pub mod clientbound_initialize_border_packet;
pub mod clientbound_keep_alive_packet;
pub mod clientbound_level_chunk_with_light_packet;
@ -21,31 +35,70 @@ pub mod clientbound_level_event_packet;
pub mod clientbound_level_particles_packet;
pub mod clientbound_light_update_packet;
pub mod clientbound_login_packet;
pub mod clientbound_map_item_data_packet;
pub mod clientbound_merchant_offers_packet;
pub mod clientbound_move_entity_pos_packet;
pub mod clientbound_move_entity_posrot_packet;
pub mod clientbound_move_entity_pos_rot_packet;
pub mod clientbound_move_entity_rot_packet;
pub mod clientbound_move_vehicle_packet;
pub mod clientbound_open_book_packet;
pub mod clientbound_open_screen_packet;
pub mod clientbound_open_sign_editor_packet;
pub mod clientbound_ping_packet;
pub mod clientbound_place_ghost_recipe_packet;
pub mod clientbound_player_abilities_packet;
pub mod clientbound_player_chat_header_packet;
pub mod clientbound_player_chat_packet;
pub mod clientbound_player_combat_end_packet;
pub mod clientbound_player_combat_enter_packet;
pub mod clientbound_player_combat_kill_packet;
pub mod clientbound_player_info_packet;
pub mod clientbound_player_look_at_packet;
pub mod clientbound_player_position_packet;
pub mod clientbound_recipe_packet;
pub mod clientbound_remove_entities_packet;
pub mod clientbound_remove_mob_effect_packet;
pub mod clientbound_resource_pack_packet;
pub mod clientbound_respawn_packet;
pub mod clientbound_rotate_head_packet;
pub mod clientbound_section_blocks_update_packet;
pub mod clientbound_select_advancements_tab_packet;
pub mod clientbound_server_data_packet;
pub mod clientbound_set_action_bar_text_packet;
pub mod clientbound_set_border_center_packet;
pub mod clientbound_set_border_lerp_size_packet;
pub mod clientbound_set_border_size_packet;
pub mod clientbound_set_border_warning_delay_packet;
pub mod clientbound_set_border_warning_distance_packet;
pub mod clientbound_set_camera_packet;
pub mod clientbound_set_carried_item_packet;
pub mod clientbound_set_chunk_cache_center_packet;
pub mod clientbound_set_chunk_cache_radius_packet;
pub mod clientbound_set_default_spawn_position_packet;
pub mod clientbound_set_display_chat_preview_packet;
pub mod clientbound_set_display_objective_packet;
pub mod clientbound_set_entity_data_packet;
pub mod clientbound_set_entity_link_packet;
pub mod clientbound_set_entity_motion_packet;
pub mod clientbound_set_equipment_packet;
pub mod clientbound_set_experience_packet;
pub mod clientbound_set_health_packet;
pub mod clientbound_set_objective_packet;
pub mod clientbound_set_passengers_packet;
pub mod clientbound_set_player_team_packet;
pub mod clientbound_set_score_packet;
pub mod clientbound_set_simulation_distance_packet;
pub mod clientbound_set_subtitle_text_packet;
pub mod clientbound_set_time_packet;
pub mod clientbound_set_title_text_packet;
pub mod clientbound_set_titles_animation_packet;
pub mod clientbound_sound_entity_packet;
pub mod clientbound_sound_packet;
pub mod clientbound_stop_sound_packet;
pub mod clientbound_system_chat_packet;
pub mod clientbound_tab_list_packet;
pub mod clientbound_tag_query_packet;
pub mod clientbound_take_item_entity_packet;
pub mod clientbound_teleport_entity_packet;
pub mod clientbound_update_advancements_packet;
pub mod clientbound_update_attributes_packet;
@ -54,16 +107,56 @@ pub mod clientbound_update_recipes_packet;
pub mod clientbound_update_tags_packet;
pub mod clientbound_update_view_distance_packet;
pub mod serverbound_accept_teleportation_packet;
pub mod serverbound_block_entity_tag_query;
pub mod serverbound_change_difficulty_packet;
pub mod serverbound_chat_ack_packet;
pub mod serverbound_chat_command_packet;
pub mod serverbound_chat_packet;
pub mod serverbound_chat_preview_packet;
pub mod serverbound_client_command_packet;
pub mod serverbound_client_information_packet;
pub mod serverbound_command_suggestion_packet;
pub mod serverbound_container_button_click_packet;
pub mod serverbound_container_click_packet;
pub mod serverbound_container_close_packet;
pub mod serverbound_custom_payload_packet;
pub mod serverbound_edit_book_packet;
pub mod serverbound_entity_tag_query;
pub mod serverbound_interact_packet;
pub mod serverbound_jigsaw_generate_packet;
pub mod serverbound_keep_alive_packet;
pub mod serverbound_move_player_packet_pos;
pub mod serverbound_move_player_packet_pos_rot;
pub mod serverbound_move_player_packet_rot;
pub mod serverbound_move_player_packet_status_only;
pub mod serverbound_lock_difficulty_packet;
pub mod serverbound_move_player_pos_packet;
pub mod serverbound_move_player_pos_rot_packet;
pub mod serverbound_move_player_rot_packet;
pub mod serverbound_move_player_status_only_packet;
pub mod serverbound_move_vehicle_packet;
pub mod serverbound_paddle_boat_packet;
pub mod serverbound_pick_item_packet;
pub mod serverbound_place_recipe_packet;
pub mod serverbound_player_abilities_packet;
pub mod serverbound_player_action_packet;
pub mod serverbound_player_command_packet;
pub mod serverbound_player_input_packet;
pub mod serverbound_pong_packet;
pub mod serverbound_recipe_book_change_settings_packet;
pub mod serverbound_recipe_book_seen_recipe_packet;
pub mod serverbound_rename_item_packet;
pub mod serverbound_resource_pack_packet;
pub mod serverbound_seen_advancements_packet;
pub mod serverbound_select_trade_packet;
pub mod serverbound_set_beacon_packet;
pub mod serverbound_set_carried_item_packet;
pub mod serverbound_set_command_block_packet;
pub mod serverbound_set_command_minecart_packet;
pub mod serverbound_set_creative_mode_slot_packet;
pub mod serverbound_set_jigsaw_block_packet;
pub mod serverbound_set_structure_block_packet;
pub mod serverbound_sign_update_packet;
pub mod serverbound_swing_packet;
pub mod serverbound_teleport_to_entity_packet;
pub mod serverbound_use_item_on_packet;
pub mod serverbound_use_item_packet;
use packet_macros::declare_state_packets;
@ -71,33 +164,87 @@ declare_state_packets!(
GamePacket,
Serverbound => {
0x00: serverbound_accept_teleportation_packet::ServerboundAcceptTeleportationPacket,
0x01: serverbound_block_entity_tag_query::ServerboundBlockEntityTagQuery,
0x02: serverbound_change_difficulty_packet::ServerboundChangeDifficultyPacket,
0x03: serverbound_chat_ack_packet::ServerboundChatAckPacket,
0x04: serverbound_chat_command_packet::ServerboundChatCommandPacket,
0x05: serverbound_chat_packet::ServerboundChatPacket,
0x06: serverbound_chat_preview_packet::ServerboundChatPreviewPacket,
0x07: serverbound_client_command_packet::ServerboundClientCommandPacket,
0x08: serverbound_client_information_packet::ServerboundClientInformationPacket,
0x09: serverbound_command_suggestion_packet::ServerboundCommandSuggestionPacket,
0x0a: serverbound_container_button_click_packet::ServerboundContainerButtonClickPacket,
0x0b: serverbound_container_click_packet::ServerboundContainerClickPacket,
0x0c: serverbound_container_close_packet::ServerboundContainerClosePacket,
0x0d: serverbound_custom_payload_packet::ServerboundCustomPayloadPacket,
0x0e: serverbound_edit_book_packet::ServerboundEditBookPacket,
0x0f: serverbound_entity_tag_query::ServerboundEntityTagQuery,
0x10: serverbound_interact_packet::ServerboundInteractPacket,
0x11: serverbound_jigsaw_generate_packet::ServerboundJigsawGeneratePacket,
0x12: serverbound_keep_alive_packet::ServerboundKeepAlivePacket,
0x14: serverbound_move_player_packet_pos::ServerboundMovePlayerPacketPos,
0x15: serverbound_move_player_packet_pos_rot::ServerboundMovePlayerPacketPosRot,
0x16: serverbound_move_player_packet_rot::ServerboundMovePlayerPacketRot,
0x17: serverbound_move_player_packet_status_only::ServerboundMovePlayerPacketStatusOnly,
0x13: serverbound_lock_difficulty_packet::ServerboundLockDifficultyPacket,
0x14: serverbound_move_player_pos_packet::ServerboundMovePlayerPacketPos,
0x15: serverbound_move_player_pos_rot_packet::ServerboundMovePlayerPacketPosRot,
0x16: serverbound_move_player_rot_packet::ServerboundMovePlayerPacketRot,
0x17: serverbound_move_player_status_only_packet::ServerboundMovePlayerPacketStatusOnly,
0x18: serverbound_move_vehicle_packet::ServerboundMoveVehiclePacket,
0x19: serverbound_paddle_boat_packet::ServerboundPaddleBoatPacket,
0x1a: serverbound_pick_item_packet::ServerboundPickItemPacket,
0x1b: serverbound_place_recipe_packet::ServerboundPlaceRecipePacket,
0x1c: serverbound_player_abilities_packet::ServerboundPlayerAbilitiesPacket,
0x1d: serverbound_player_action_packet::ServerboundPlayerActionPacket,
0x1e: serverbound_player_command_packet::ServerboundPlayerCommandPacket,
0x1f: serverbound_player_input_packet::ServerboundPlayerInputPacket,
0x20: serverbound_pong_packet::ServerboundPongPacket,
0x21: serverbound_recipe_book_change_settings_packet::ServerboundRecipeBookChangeSettingsPacket,
0x22: serverbound_recipe_book_seen_recipe_packet::ServerboundRecipeBookSeenRecipePacket,
0x23: serverbound_rename_item_packet::ServerboundRenameItemPacket,
0x24: serverbound_resource_pack_packet::ServerboundResourcePackPacket,
0x25: serverbound_seen_advancements_packet::ServerboundSeenAdvancementsPacket,
0x26: serverbound_select_trade_packet::ServerboundSelectTradePacket,
0x27: serverbound_set_beacon_packet::ServerboundSetBeaconPacket,
0x28: serverbound_set_carried_item_packet::ServerboundSetCarriedItemPacket,
0x29: serverbound_set_command_block_packet::ServerboundSetCommandBlockPacket,
0x2a: serverbound_set_command_minecart_packet::ServerboundSetCommandMinecartPacket,
0x2b: serverbound_set_creative_mode_slot_packet::ServerboundSetCreativeModeSlotPacket,
0x2c: serverbound_set_jigsaw_block_packet::ServerboundSetJigsawBlockPacket,
0x2d: serverbound_set_structure_block_packet::ServerboundSetStructureBlockPacket,
0x2e: serverbound_sign_update_packet::ServerboundSignUpdatePacket,
0x2f: serverbound_swing_packet::ServerboundSwingPacket,
0x30: serverbound_teleport_to_entity_packet::ServerboundTeleportToEntityPacket,
0x31: serverbound_use_item_on_packet::ServerboundUseItemOnPacket,
0x32: serverbound_use_item_packet::ServerboundUseItemPacket,
},
Clientbound => {
0x00: clientbound_add_entity_packet::ClientboundAddEntityPacket,
0x01: clientbound_add_experience_orb_packet::ClientboundAddExperienceOrbPacket,
0x02: clientbound_add_player_packet::ClientboundAddPlayerPacket,
0x03: clientbound_animate_packet::ClientboundAnimatePacket,
0x04: clientbound_award_stats_packet::ClientboundAwardStatsPacket,
0x05: clientbound_block_changed_ack_packet::ClientboundBlockChangedAckPacket,
0x06: clientbound_block_destruction_packet::ClientboundBlockDestructionPacket,
0x07: clientbound_block_entity_data_packet::ClientboundBlockEntityDataPacket,
0x08: clientbound_block_event_packet::ClientboundBlockEventPacket,
0x09: clientbound_block_update_packet::ClientboundBlockUpdatePacket,
0x0a: clientbound_boss_event_packet::ClientboundBossEventPacket,
0x0b: clientbound_change_difficulty_packet::ClientboundChangeDifficultyPacket,
0x0c: clientbound_chat_preview_packet::ClientboundChatPreviewPacket,
0x0f: clientbound_declare_commands_packet::ClientboundDeclareCommandsPacket,
0x0e: clientbound_command_suggestions_packet::ClientboundCommandSuggestionsPacket,
0x0f: clientbound_commands_packet::ClientboundCommandsPacket,
0x11: clientbound_container_set_content_packet::ClientboundContainerSetContentPacket,
0x12: clientbound_container_set_data_packet::ClientboundContainerSetDataPacket,
0x13: clientbound_container_set_slot_packet::ClientboundContainerSetSlotPacket,
0x14: clientbound_cooldown_packet::ClientboundCooldownPacket,
0x15: clientbound_custom_chat_completions_packet::ClientboundCustomChatCompletionsPacket,
0x16: clientbound_custom_payload_packet::ClientboundCustomPayloadPacket,
0x17: clientbound_custom_sound_packet::ClientboundCustomSoundPacket,
0x18: clientbound_delete_chat_packet::ClientboundDeleteChatPacket,
0x19: clientbound_disconnect_packet::ClientboundDisconnectPacket,
0x1a: clientbound_entity_event_packet::ClientboundEntityEventPacket,
0x1b: clientbound_explode_packet::ClientboundExplodePacket,
0x1c: clientbound_forget_level_chunk_packet::ClientboundForgetLevelChunkPacket,
0x1d: clientbound_game_event_packet::ClientboundGameEventPacket,
0x1e: clientbound_horse_screen_open_packet::ClientboundHorseScreenOpenPacket,
0x1f: clientbound_initialize_border_packet::ClientboundInitializeBorderPacket,
0x20: clientbound_keep_alive_packet::ClientboundKeepAlivePacket,
0x21: clientbound_level_chunk_with_light_packet::ClientboundLevelChunkWithLightPacket,
@ -105,33 +252,72 @@ declare_state_packets!(
0x23: clientbound_level_particles_packet::ClientboundLevelParticlesPacket,
0x24: clientbound_light_update_packet::ClientboundLightUpdatePacket,
0x25: clientbound_login_packet::ClientboundLoginPacket,
0x26: clientbound_map_item_data_packet::ClientboundMapItemDataPacket,
0x27: clientbound_merchant_offers_packet::ClientboundMerchantOffersPacket,
0x28: clientbound_move_entity_pos_packet::ClientboundMoveEntityPosPacket,
0x29: clientbound_move_entity_posrot_packet::ClientboundMoveEntityPosrotPacket,
0x29: clientbound_move_entity_pos_rot_packet::ClientboundMoveEntityPosRotPacket,
0x2a: clientbound_move_entity_rot_packet::ClientboundMoveEntityRotPacket,
0x2b: clientbound_move_vehicle_packet::ClientboundMoveVehiclePacket,
0x2c: clientbound_open_book_packet::ClientboundOpenBookPacket,
0x2d: clientbound_open_screen_packet::ClientboundOpenScreenPacket,
0x2e: clientbound_open_sign_editor_packet::ClientboundOpenSignEditorPacket,
0x2f: clientbound_ping_packet::ClientboundPingPacket,
0x30: clientbound_place_ghost_recipe_packet::ClientboundPlaceGhostRecipePacket,
0x31: clientbound_player_abilities_packet::ClientboundPlayerAbilitiesPacket,
0x32: clientbound_player_chat_header_packet::ClientboundPlayerChatHeaderPacket,
0x33: clientbound_player_chat_packet::ClientboundPlayerChatPacket,
0x34: clientbound_player_combat_end_packet::ClientboundPlayerCombatEndPacket,
0x35: clientbound_player_combat_enter_packet::ClientboundPlayerCombatEnterPacket,
0x36: clientbound_player_combat_kill_packet::ClientboundPlayerCombatKillPacket,
0x37: clientbound_player_info_packet::ClientboundPlayerInfoPacket,
0x38: clientbound_player_look_at_packet::ClientboundPlayerLookAtPacket,
0x39: clientbound_player_position_packet::ClientboundPlayerPositionPacket,
0x3a: clientbound_recipe_packet::ClientboundRecipePacket,
0x3b: clientbound_remove_entities_packet::ClientboundRemoveEntitiesPacket,
0x3c: clientbound_remove_mob_effect_packet::ClientboundRemoveMobEffectPacket,
0x3d: clientbound_resource_pack_packet::ClientboundResourcePackPacket,
0x3e: clientbound_respawn_packet::ClientboundRespawnPacket,
0x3f: clientbound_rotate_head_packet::ClientboundRotateHeadPacket,
0x40: clientbound_section_blocks_update_packet::ClientboundSectionBlocksUpdatePacket,
0x41: clientbound_select_advancements_tab_packet::ClientboundSelectAdvancementsTabPacket,
0x42: clientbound_server_data_packet::ClientboundServerDataPacket,
0x43: clientbound_set_action_bar_text_packet::ClientboundSetActionBarTextPacket,
0x44: clientbound_set_border_center_packet::ClientboundSetBorderCenterPacket,
0x45: clientbound_set_border_lerp_size_packet::ClientboundSetBorderLerpSizePacket,
0x46: clientbound_set_border_size_packet::ClientboundSetBorderSizePacket,
0x47: clientbound_set_border_warning_delay_packet::ClientboundSetBorderWarningDelayPacket,
0x48: clientbound_set_border_warning_distance_packet::ClientboundSetBorderWarningDistancePacket,
0x49: clientbound_set_camera_packet::ClientboundSetCameraPacket,
0x4a: clientbound_set_carried_item_packet::ClientboundSetCarriedItemPacket,
0x4b: clientbound_set_chunk_cache_center_packet::ClientboundSetChunkCacheCenterPacket,
0x4c: clientbound_update_view_distance_packet::ClientboundUpdateViewDistancePacket,
0x4c: clientbound_set_chunk_cache_radius_packet::ClientboundSetChunkCacheRadiusPacket,
0x4d: clientbound_set_default_spawn_position_packet::ClientboundSetDefaultSpawnPositionPacket,
0x4e: clientbound_set_display_chat_preview_packet::ClientboundSetDisplayChatPreviewPacket,
0x4f: clientbound_set_display_objective_packet::ClientboundSetDisplayObjectivePacket,
0x50: clientbound_set_entity_data_packet::ClientboundSetEntityDataPacket,
0x51: clientbound_set_entity_link_packet::ClientboundSetEntityLinkPacket,
0x52: clientbound_entity_velocity_packet::ClientboundEntityVelocityPacket,
0x52: clientbound_set_entity_motion_packet::ClientboundSetEntityMotionPacket,
0x53: clientbound_set_equipment_packet::ClientboundSetEquipmentPacket,
0x54: clientbound_set_experience_packet::ClientboundSetExperiencePacket,
0x55: clientbound_set_health_packet::ClientboundSetHealthPacket,
0x56: clientbound_set_objective_packet::ClientboundSetObjectivePacket,
0x57: clientbound_set_passengers_packet::ClientboundSetPassengersPacket,
0x58: clientbound_set_player_team_packet::ClientboundSetPlayerTeamPacket,
0x59: clientbound_set_score_packet::ClientboundSetScorePacket,
0x5a: clientbound_set_simulation_distance_packet::ClientboundSetSimulationDistancePacket,
0x5b: clientbound_set_subtitle_text_packet::ClientboundSetSubtitleTextPacket,
0x5c: clientbound_set_time_packet::ClientboundSetTimePacket,
0x5d: clientbound_set_title_text_packet::ClientboundSetTitleTextPacket,
0x5e: clientbound_set_titles_animation_packet::ClientboundSetTitlesAnimationPacket,
0x5f: clientbound_sound_entity_packet::ClientboundSoundEntityPacket,
0x60: clientbound_sound_packet::ClientboundSoundPacket,
0x61: clientbound_stop_sound_packet::ClientboundStopSoundPacket,
0x62: clientbound_system_chat_packet::ClientboundSystemChatPacket,
0x63: clientbound_tab_list_packet::ClientboundTabListPacket,
0x64: clientbound_tag_query_packet::ClientboundTagQueryPacket,
0x65: clientbound_take_item_entity_packet::ClientboundTakeItemEntityPacket,
0x66: clientbound_teleport_entity_packet::ClientboundTeleportEntityPacket,
0x67: clientbound_update_advancements_packet::ClientboundUpdateAdvancementsPacket,
0x68: clientbound_update_attributes_packet::ClientboundUpdateAttributesPacket,

View file

@ -0,0 +1,10 @@
use azalea_buf::McBuf;
use azalea_core::BlockPos;
use packet_macros::ServerboundGamePacket;
#[derive(Clone, Debug, McBuf, ServerboundGamePacket)]
pub struct ServerboundBlockEntityTagQuery {
#[var]
pub transaction_id: i32,
pub pos: BlockPos,
}

View file

@ -0,0 +1,8 @@
use azalea_buf::McBuf;
use azalea_core::Difficulty;
use packet_macros::ServerboundGamePacket;
#[derive(Clone, Debug, McBuf, ServerboundGamePacket)]
pub struct ServerboundChangeDifficultyPacket {
pub difficulty: Difficulty,
}

View file

@ -0,0 +1,13 @@
use azalea_buf::McBuf;
use packet_macros::ServerboundGamePacket;
#[derive(Clone, Debug, McBuf, ServerboundGamePacket)]
pub struct ServerboundClientCommandPacket {
pub action: Action,
}
#[derive(McBuf, Clone, Copy, Debug)]
pub enum Action {
PerformRespawn = 0,
RequestStats = 1,
}

View file

@ -0,0 +1,27 @@
use azalea_buf::McBuf;
use packet_macros::ServerboundGamePacket;
#[derive(Clone, Debug, McBuf, ServerboundGamePacket)]
pub struct ServerboundClientInformationPacket {
pub language: String,
pub view_distance: u8,
pub chat_visibility: ChatVisiblity,
pub chat_colors: bool,
pub model_customisation: u8,
pub main_hand: HumanoidArm,
pub text_filtering_enabled: bool,
pub allows_listing: bool,
}
#[derive(McBuf, Clone, Copy, Debug)]
pub enum ChatVisiblity {
Full = 0,
System = 1,
Hidden = 2,
}
#[derive(McBuf, Clone, Copy, Debug)]
pub enum HumanoidArm {
Left = 0,
Right = 1,
}

View file

@ -0,0 +1,9 @@
use azalea_buf::McBuf;
use packet_macros::ServerboundGamePacket;
#[derive(Clone, Debug, McBuf, ServerboundGamePacket)]
pub struct ServerboundCommandSuggestionPacket {
#[var]
pub id: u32,
pub command: String,
}

View file

@ -0,0 +1,8 @@
use azalea_buf::McBuf;
use packet_macros::ServerboundGamePacket;
#[derive(Clone, Debug, McBuf, ServerboundGamePacket)]
pub struct ServerboundContainerButtonClickPacket {
pub container_id: u8,
pub button_id: u8,
}

View file

@ -0,0 +1,26 @@
use azalea_buf::McBuf;
use azalea_core::Slot;
use packet_macros::ServerboundGamePacket;
use std::collections::HashMap;
#[derive(Clone, Debug, McBuf, ServerboundGamePacket)]
pub struct ServerboundContainerClickPacket {
pub container_id: u8,
#[var]
pub state_id: u32,
pub slot_num: u16,
pub button_num: u8,
pub click_type: ClickType,
pub changed_slots: HashMap<u16, Slot>,
}
#[derive(McBuf, Clone, Copy, Debug)]
pub enum ClickType {
Pickup = 0,
QuickMove = 1,
Swap = 2,
Clone = 3,
Throw = 4,
QuickCraft = 5,
PickupAll = 6,
}

View file

@ -0,0 +1,7 @@
use azalea_buf::McBuf;
use packet_macros::ServerboundGamePacket;
#[derive(Clone, Debug, McBuf, ServerboundGamePacket)]
pub struct ServerboundContainerClosePacket {
pub container_id: u8,
}

View file

@ -0,0 +1,10 @@
use azalea_buf::McBuf;
use packet_macros::ServerboundGamePacket;
#[derive(Clone, Debug, McBuf, ServerboundGamePacket)]
pub struct ServerboundEditBookPacket {
#[var]
pub slot: u32,
pub pages: Vec<String>,
pub title: Option<String>,
}

View file

@ -0,0 +1,10 @@
use azalea_buf::McBuf;
use packet_macros::ServerboundGamePacket;
#[derive(Clone, Debug, McBuf, ServerboundGamePacket)]
pub struct ServerboundEntityTagQuery {
#[var]
pub transaction_id: u32,
#[var]
pub entity_id: u32,
}

View file

@ -0,0 +1,85 @@
use crate::packets::BufReadError;
use azalea_buf::McBufVarReadable;
use azalea_buf::{McBuf, McBufReadable, McBufVarWritable, McBufWritable};
use azalea_core::EntityPos;
use packet_macros::ServerboundGamePacket;
use std::io::{Read, Write};
#[derive(Clone, Debug, McBuf, ServerboundGamePacket)]
pub struct ServerboundInteractPacket {
#[var]
pub entity_id: u32,
pub action: ActionType,
/// Whether the player is sneaking
pub using_secondary_action: bool,
}
#[derive(Clone, Copy, Debug)]
pub enum ActionType {
Interact {
hand: InteractionHand,
},
Attack,
InteractAt {
location: EntityPos,
hand: InteractionHand,
},
}
impl McBufWritable for ActionType {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
match self {
ActionType::Interact { hand } => {
0u32.var_write_into(buf)?;
hand.write_into(buf)?;
}
ActionType::Attack => {
1u32.var_write_into(buf)?;
}
ActionType::InteractAt { location, hand } => {
2u32.var_write_into(buf)?;
(location.x as f32).write_into(buf)?;
(location.y as f32).write_into(buf)?;
(location.z as f32).write_into(buf)?;
hand.write_into(buf)?;
}
}
Ok(())
}
}
impl McBufReadable for ActionType {
fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> {
let action_type = u32::var_read_from(buf)?;
match action_type {
0 => {
let hand = InteractionHand::read_from(buf)?;
Ok(ActionType::Interact { hand })
}
1 => Ok(ActionType::Attack),
2 => {
let x = f32::read_from(buf)?;
let y = f32::read_from(buf)?;
let z = f32::read_from(buf)?;
let hand = InteractionHand::read_from(buf)?;
Ok(ActionType::InteractAt {
location: EntityPos {
x: x as f64,
y: y as f64,
z: z as f64,
},
hand,
})
}
_ => Err(BufReadError::UnexpectedEnumVariant {
id: action_type as i32,
}),
}
}
}
#[derive(McBuf, Clone, Copy, Debug)]
pub enum InteractionHand {
MainHand = 0,
OffHand = 1,
}

View file

@ -0,0 +1,11 @@
use azalea_buf::McBuf;
use azalea_core::BlockPos;
use packet_macros::ServerboundGamePacket;
#[derive(Clone, Debug, McBuf, ServerboundGamePacket)]
pub struct ServerboundJigsawGeneratePacket {
pub pos: BlockPos,
#[var]
pub levels: u32,
pub keep_jigsaws: bool,
}

View file

@ -0,0 +1,7 @@
use azalea_buf::McBuf;
use packet_macros::ServerboundGamePacket;
#[derive(Clone, Debug, McBuf, ServerboundGamePacket)]
pub struct ServerboundLockDifficultyPacket {
pub locked: bool,
}

View file

@ -0,0 +1,11 @@
use azalea_buf::McBuf;
use packet_macros::ServerboundGamePacket;
#[derive(Clone, Debug, McBuf, ServerboundGamePacket)]
pub struct ServerboundMoveVehiclePacket {
pub x: f64,
pub y: f64,
pub z: f64,
pub y_rot: f32,
pub x_rot: f32,
}

View file

@ -0,0 +1,8 @@
use azalea_buf::McBuf;
use packet_macros::ServerboundGamePacket;
#[derive(Clone, Debug, McBuf, ServerboundGamePacket)]
pub struct ServerboundPaddleBoatPacket {
pub left: bool,
pub right: bool,
}

View file

@ -0,0 +1,8 @@
use azalea_buf::McBuf;
use packet_macros::ServerboundGamePacket;
#[derive(Clone, Debug, McBuf, ServerboundGamePacket)]
pub struct ServerboundPickItemPacket {
#[var]
pub slot: u32,
}

View file

@ -0,0 +1,10 @@
use azalea_buf::McBuf;
use azalea_core::ResourceLocation;
use packet_macros::ServerboundGamePacket;
#[derive(Clone, Debug, McBuf, ServerboundGamePacket)]
pub struct ServerboundPlaceRecipePacket {
pub container_id: u8,
pub recipe: ResourceLocation,
pub shift_down: bool,
}

View file

@ -0,0 +1,28 @@
use crate::packets::BufReadError;
use azalea_buf::{McBufReadable, McBufWritable};
use packet_macros::ServerboundGamePacket;
#[derive(Clone, Debug, ServerboundGamePacket)]
pub struct ServerboundPlayerAbilitiesPacket {
is_flying: bool,
}
impl McBufReadable for ServerboundPlayerAbilitiesPacket {
fn read_from(buf: &mut impl std::io::Read) -> Result<Self, BufReadError> {
let byte = u8::read_from(buf)?;
Ok(Self {
is_flying: byte & 2 != 0,
})
}
}
impl McBufWritable for ServerboundPlayerAbilitiesPacket {
fn write_into(&self, buf: &mut impl std::io::Write) -> Result<(), std::io::Error> {
let mut byte = 0;
if self.is_flying {
byte |= 2;
}
byte.write_into(buf)?;
Ok(())
}
}

View file

@ -0,0 +1,24 @@
use azalea_buf::McBuf;
use azalea_core::BlockPos;
use azalea_core::Direction;
use packet_macros::ServerboundGamePacket;
#[derive(Clone, Debug, McBuf, ServerboundGamePacket)]
pub struct ServerboundPlayerActionPacket {
pub action: Action,
pub pos: BlockPos,
pub direction: Direction,
#[var]
pub sequence: u32,
}
#[derive(McBuf, Clone, Copy, Debug)]
pub enum Action {
StartDestroyBlock = 0,
AbortDestroyBlock = 1,
StopDestroyBlock = 2,
DropAllItems = 3,
DropItem = 4,
ReleaseUseItem = 5,
SwapItemWithOffhand = 6,
}

View file

@ -0,0 +1,24 @@
use azalea_buf::McBuf;
use packet_macros::ServerboundGamePacket;
#[derive(Clone, Debug, McBuf, ServerboundGamePacket)]
pub struct ServerboundPlayerCommandPacket {
#[var]
pub id: u32,
pub action: Action,
#[var]
pub data: u32,
}
#[derive(McBuf, Clone, Copy, Debug)]
pub enum Action {
PressShiftKey = 0,
ReleaseShiftKey = 1,
StopSleeping = 2,
StartSprinting = 3,
StopSprinting = 4,
StartRidingJump = 5,
StopRidingJump = 6,
OpenInventory = 7,
StartFallFlying = 8,
}

View file

@ -0,0 +1,43 @@
use azalea_buf::BufReadError;
use azalea_buf::{McBufReadable, McBufWritable};
use packet_macros::ServerboundGamePacket;
#[derive(Clone, Debug, ServerboundGamePacket)]
pub struct ServerboundPlayerInputPacket {
pub xxa: f32,
pub zza: f32,
pub is_jumping: bool,
pub is_shift_key_down: bool,
}
impl McBufReadable for ServerboundPlayerInputPacket {
fn read_from(buf: &mut impl std::io::Read) -> Result<Self, BufReadError> {
let xxa = f32::read_from(buf)?;
let zza = f32::read_from(buf)?;
let byte = u8::read_from(buf)?;
let is_jumping = byte & 1 != 0;
let is_shift_key_down = byte & 2 != 0;
Ok(Self {
xxa,
zza,
is_jumping,
is_shift_key_down,
})
}
}
impl McBufWritable for ServerboundPlayerInputPacket {
fn write_into(&self, buf: &mut impl std::io::Write) -> Result<(), std::io::Error> {
self.xxa.write_into(buf)?;
self.zza.write_into(buf)?;
let mut byte = 0;
if self.is_jumping {
byte |= 1;
}
if self.is_shift_key_down {
byte |= 2;
}
byte.write_into(buf)?;
Ok(())
}
}

Some files were not shown because too many files have changed in this diff Show more