aboutsummaryrefslogtreecommitdiff
path: root/azalea-protocol/src
diff options
context:
space:
mode:
authorEightFactorial <murphkev000@gmail.com>2023-01-30 16:18:14 -0800
committerGitHub <noreply@github.com>2023-01-30 18:18:14 -0600
commit6e818852d868eea963dd2b8489ba75b65c56fb1c (patch)
treee786e919de7d4a1777d91e8e2fa890482970972d /azalea-protocol/src
parent2539f948c7a88a86b27b1878f6c28976285f348c (diff)
downloadazalea-drasl-6e818852d868eea963dd2b8489ba75b65c56fb1c.tar.xz
More packet fixes, tests, handle error (#61)
* Fix packet, fix tests, fixedbitsets * Clippy: Nightmare Mode * Fix mistake * simplify impl Display and make thing pub --------- Co-authored-by: mat <github@matdoes.dev>
Diffstat (limited to 'azalea-protocol/src')
-rwxr-xr-xazalea-protocol/src/connect.rs8
-rw-r--r--azalea-protocol/src/lib.rs20
-rwxr-xr-xazalea-protocol/src/packets/game/clientbound_boss_event_packet.rs19
-rwxr-xr-xazalea-protocol/src/packets/game/clientbound_commands_packet.rs166
-rwxr-xr-xazalea-protocol/src/packets/game/clientbound_explode_packet.rs6
-rwxr-xr-xazalea-protocol/src/packets/game/clientbound_map_item_data_packet.rs94
-rwxr-xr-xazalea-protocol/src/packets/game/clientbound_player_abilities_packet.rs23
-rw-r--r--azalea-protocol/src/packets/game/clientbound_player_chat_packet.rs11
-rwxr-xr-xazalea-protocol/src/packets/game/clientbound_player_position_packet.rs27
-rwxr-xr-xazalea-protocol/src/packets/game/clientbound_section_blocks_update_packet.rs2
-rwxr-xr-xazalea-protocol/src/packets/game/clientbound_set_equipment_packet.rs1
-rwxr-xr-xazalea-protocol/src/packets/game/clientbound_set_objective_packet.rs2
-rwxr-xr-xazalea-protocol/src/packets/game/clientbound_set_player_team_packet.rs2
-rwxr-xr-xazalea-protocol/src/packets/game/clientbound_set_score_packet.rs2
-rwxr-xr-xazalea-protocol/src/packets/game/clientbound_stop_sound_packet.rs16
-rwxr-xr-xazalea-protocol/src/packets/game/clientbound_update_advancements_packet.rs134
-rwxr-xr-xazalea-protocol/src/packets/game/serverbound_client_information_packet.rs133
-rwxr-xr-xazalea-protocol/src/packets/game/serverbound_interact_packet.rs6
-rwxr-xr-xazalea-protocol/src/packets/game/serverbound_player_abilities_packet.rs14
-rwxr-xr-xazalea-protocol/src/packets/game/serverbound_player_input_packet.rs18
-rwxr-xr-xazalea-protocol/src/packets/game/serverbound_set_command_block_packet.rs24
-rwxr-xr-xazalea-protocol/src/packets/game/serverbound_set_structure_block_packet.rs20
-rwxr-xr-xazalea-protocol/src/packets/game/serverbound_use_item_on_packet.rs12
-rwxr-xr-xazalea-protocol/src/packets/mod.rs3
-rwxr-xr-xazalea-protocol/src/read.rs65
-rwxr-xr-xazalea-protocol/src/resolver.rs1
26 files changed, 496 insertions, 333 deletions
diff --git a/azalea-protocol/src/connect.rs b/azalea-protocol/src/connect.rs
index 06b306b9..cb837ba5 100755
--- a/azalea-protocol/src/connect.rs
+++ b/azalea-protocol/src/connect.rs
@@ -189,6 +189,7 @@ where
}
/// Split the reader and writer into two objects. This doesn't allocate.
+ #[must_use]
pub fn into_split(self) -> (ReadConnection<R>, WriteConnection<W>) {
(self.reader, self.writer)
}
@@ -229,12 +230,14 @@ impl Connection<ClientboundHandshakePacket, ServerboundHandshakePacket> {
/// Change our state from handshake to login. This is the state that is used
/// for logging in.
+ #[must_use]
pub fn login(self) -> Connection<ClientboundLoginPacket, ServerboundLoginPacket> {
Connection::from(self)
}
/// Change our state from handshake to status. This is the state that is
/// used for pinging the server.
+ #[must_use]
pub fn status(self) -> Connection<ClientboundStatusPacket, ServerboundStatusPacket> {
Connection::from(self)
}
@@ -265,6 +268,7 @@ impl Connection<ClientboundLoginPacket, ServerboundLoginPacket> {
/// Change our state from login to game. This is the state that's used when
/// you're actually in the game.
+ #[must_use]
pub fn game(self) -> Connection<ClientboundGamePacket, ServerboundGamePacket> {
Connection::from(self)
}
@@ -343,12 +347,14 @@ impl Connection<ClientboundLoginPacket, ServerboundLoginPacket> {
impl Connection<ServerboundHandshakePacket, ClientboundHandshakePacket> {
/// Change our state from handshake to login. This is the state that is used
/// for logging in.
+ #[must_use]
pub fn login(self) -> Connection<ServerboundLoginPacket, ClientboundLoginPacket> {
Connection::from(self)
}
/// Change our state from handshake to status. This is the state that is
/// used for pinging the server.
+ #[must_use]
pub fn status(self) -> Connection<ServerboundStatusPacket, ClientboundStatusPacket> {
Connection::from(self)
}
@@ -379,6 +385,7 @@ impl Connection<ServerboundLoginPacket, ClientboundLoginPacket> {
/// Change our state from login to game. This is the state that's used when
/// the client is actually in the game.
+ #[must_use]
pub fn game(self) -> Connection<ServerboundGamePacket, ClientboundGamePacket> {
Connection::from(self)
}
@@ -406,6 +413,7 @@ where
{
/// Creates a `Connection` of a type from a `Connection` of another type.
/// Useful for servers or custom packets.
+ #[must_use]
pub fn from<R2, W2>(connection: Connection<R1, W1>) -> Connection<R2, W2>
where
R2: ProtocolPacket + Debug,
diff --git a/azalea-protocol/src/lib.rs b/azalea-protocol/src/lib.rs
index 3f838d2a..7c21f493 100644
--- a/azalea-protocol/src/lib.rs
+++ b/azalea-protocol/src/lib.rs
@@ -1,7 +1,7 @@
//! A low-level crate to send and receive Minecraft packets.
//!
//! You should probably use [`azalea`] or [`azalea_client`] instead, as
-//! azalea_protocol delegates much of the work, such as auth, to the user of
+//! `azalea_protocol` delegates much of the work, such as auth, to the user of
//! the crate.
//!
//! [`azalea`]: https://crates.io/crates/azalea
@@ -13,7 +13,7 @@
#![feature(error_generic_member_access)]
#![feature(provide_any)]
-use std::{net::SocketAddr, str::FromStr};
+use std::{fmt::Display, net::SocketAddr, str::FromStr};
#[cfg(feature = "connecting")]
pub mod connect;
@@ -27,7 +27,7 @@ pub mod write;
///
/// # Examples
///
-/// ServerAddress implements TryFrom<&str>, so you can use it like this:
+/// `ServerAddress` implements TryFrom<&str>, so you can use it like this:
/// ```
/// use azalea_protocol::ServerAddress;
///
@@ -45,7 +45,7 @@ impl<'a> TryFrom<&'a str> for ServerAddress {
type Error = String;
/// Convert a Minecraft server address (host:port, the port is optional) to
- /// a ServerAddress
+ /// a `ServerAddress`
fn try_from(string: &str) -> Result<Self, Self::Error> {
if string.is_empty() {
return Err("Empty string".to_string());
@@ -60,9 +60,9 @@ impl<'a> TryFrom<&'a str> for ServerAddress {
}
impl From<SocketAddr> for ServerAddress {
- /// Convert an existing SocketAddr into a ServerAddress. This just converts
- /// the ip to a string and passes along the port. The resolver will realize
- /// it's already an IP address and not do any DNS requests.
+ /// Convert an existing `SocketAddr` into a `ServerAddress`. This just
+ /// converts the ip to a string and passes along the port. The resolver
+ /// will realize it's already an IP address and not do any DNS requests.
fn from(addr: SocketAddr) -> Self {
ServerAddress {
host: addr.ip().to_string(),
@@ -71,6 +71,12 @@ impl From<SocketAddr> for ServerAddress {
}
}
+impl Display for ServerAddress {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ write!(f, "{}:{}", self.host, self.port)
+ }
+}
+
#[cfg(test)]
mod tests {
use std::io::Cursor;
diff --git a/azalea-protocol/src/packets/game/clientbound_boss_event_packet.rs b/azalea-protocol/src/packets/game/clientbound_boss_event_packet.rs
index 59378d3e..3ffbaea1 100755
--- a/azalea-protocol/src/packets/game/clientbound_boss_event_packet.rs
+++ b/azalea-protocol/src/packets/game/clientbound_boss_event_packet.rs
@@ -2,6 +2,7 @@ use azalea_buf::{
BufReadError, McBuf, McBufReadable, McBufVarReadable, McBufVarWritable, McBufWritable,
};
use azalea_chat::Component;
+use azalea_core::FixedBitSet;
use azalea_protocol_macros::ClientboundGamePacket;
use std::io::Cursor;
use std::io::Write;
@@ -116,28 +117,28 @@ pub struct Properties {
impl McBufReadable for Properties {
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
- let byte = u8::read_from(buf)?;
+ let set = FixedBitSet::<3>::read_from(buf)?;
Ok(Self {
- darken_screen: byte & 1 != 0,
- play_music: byte & 2 != 0,
- create_world_fog: byte & 4 != 0,
+ darken_screen: set.index(0),
+ play_music: set.index(1),
+ create_world_fog: set.index(2),
})
}
}
impl McBufWritable for Properties {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
- let mut byte = 0;
+ let mut set = FixedBitSet::<3>::new();
if self.darken_screen {
- byte |= 1;
+ set.set(0);
}
if self.play_music {
- byte |= 2;
+ set.set(1);
}
if self.create_world_fog {
- byte |= 4;
+ set.set(2);
}
- u8::write_into(&byte, buf)?;
+ set.write_into(buf)?;
Ok(())
}
}
diff --git a/azalea-protocol/src/packets/game/clientbound_commands_packet.rs b/azalea-protocol/src/packets/game/clientbound_commands_packet.rs
index 39e807cf..fa11a355 100755
--- a/azalea-protocol/src/packets/game/clientbound_commands_packet.rs
+++ b/azalea-protocol/src/packets/game/clientbound_commands_packet.rs
@@ -2,6 +2,7 @@ use azalea_buf::BufReadError;
use azalea_buf::McBuf;
use azalea_buf::McBufVarReadable;
use azalea_buf::{McBufReadable, McBufVarWritable, McBufWritable};
+use azalea_core::FixedBitSet;
use azalea_core::ResourceLocation;
use azalea_protocol_macros::ClientboundGamePacket;
use log::warn;
@@ -15,7 +16,7 @@ pub struct ClientboundCommandsPacket {
pub root_index: u32,
}
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, PartialEq)]
pub struct BrigadierNodeStub {
pub is_executable: bool,
pub children: Vec<u32>,
@@ -23,7 +24,7 @@ pub struct BrigadierNodeStub {
pub node_type: NodeType,
}
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, Eq)]
pub struct BrigadierNumber<T> {
pub min: Option<T>,
pub max: Option<T>,
@@ -33,15 +34,29 @@ impl<T> BrigadierNumber<T> {
BrigadierNumber { min, max }
}
}
+impl<T: PartialEq> PartialEq for BrigadierNumber<T> {
+ fn eq(&self, other: &Self) -> bool {
+ match (&self.min, &self.max, &other.min, &other.max) {
+ (Some(f_min), None, Some(s_min), None) => f_min == s_min,
+ (None, Some(f_max), None, Some(s_max)) => f_max == s_max,
+ (Some(f_min), Some(f_max), Some(s_min), Some(s_max)) => {
+ f_min == s_min && f_max == s_max
+ }
+ (None, None, None, None) => true,
+ _ => false,
+ }
+ }
+}
+
impl<T: McBufReadable> McBufReadable for BrigadierNumber<T> {
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
- let flags = u8::read_from(buf)?;
- let min = if flags & 0x01 != 0 {
+ let flags = FixedBitSet::<2>::read_from(buf)?;
+ let min = if flags.index(0) {
Some(T::read_from(buf)?)
} else {
None
};
- let max = if flags & 0x02 != 0 {
+ let max = if flags.index(1) {
Some(T::read_from(buf)?)
} else {
None
@@ -51,12 +66,12 @@ impl<T: McBufReadable> McBufReadable for BrigadierNumber<T> {
}
impl<T: McBufWritable> McBufWritable for BrigadierNumber<T> {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
- let mut flags: u8 = 0;
+ let mut flags = FixedBitSet::<2>::new();
if self.min.is_some() {
- flags |= 0x01;
+ flags.set(0);
}
if self.max.is_some() {
- flags |= 0x02;
+ flags.set(1);
}
flags.write_into(buf)?;
if let Some(min) = &self.min {
@@ -69,7 +84,7 @@ impl<T: McBufWritable> McBufWritable for BrigadierNumber<T> {
}
}
-#[derive(Debug, Clone, Copy, McBuf)]
+#[derive(Debug, Clone, Copy, McBuf, PartialEq, Eq)]
pub enum BrigadierString {
/// Reads a single word
SingleWord = 0,
@@ -80,7 +95,7 @@ pub enum BrigadierString {
GreedyPhrase = 2,
}
-#[derive(Debug, Clone, McBuf)]
+#[derive(Debug, Clone, McBuf, PartialEq)]
pub enum BrigadierParser {
Bool,
Float(BrigadierNumber<f32>),
@@ -132,28 +147,28 @@ pub enum BrigadierParser {
Uuid,
}
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EntityParser {
pub single: bool,
pub players_only: bool,
}
impl McBufReadable for EntityParser {
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
- let flags = u8::read_from(buf)?;
+ let flags = FixedBitSet::<2>::read_from(buf)?;
Ok(EntityParser {
- single: flags & 0x01 != 0,
- players_only: flags & 0x02 != 0,
+ single: flags.index(0),
+ players_only: flags.index(1),
})
}
}
impl McBufWritable for EntityParser {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
- let mut flags: u8 = 0;
+ let mut flags = FixedBitSet::<2>::new();
if self.single {
- flags |= 0x01;
+ flags.set(0);
}
if self.players_only {
- flags |= 0x02;
+ flags.set(1);
}
flags.write_into(buf)?;
Ok(())
@@ -163,17 +178,15 @@ impl McBufWritable for EntityParser {
// TODO: BrigadierNodeStub should have more stuff
impl McBufReadable for BrigadierNodeStub {
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
- let flags = u8::read_from(buf)?;
- if flags > 31 {
- warn!(
- "Warning: The flags from a Brigadier node are over 31 ({flags}; {flags:#b}). This is probably a bug.",
- );
+ let flags = FixedBitSet::<8>::read_from(buf)?;
+ if flags.index(5) || flags.index(6) || flags.index(7) {
+ warn!("Warning: The flags from a Brigadier node are over 31. 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 node_type = u8::from(flags.index(0)) + (u8::from(flags.index(1)) * 2);
+ let is_executable = flags.index(2);
+ let has_redirect = flags.index(3);
+ let has_suggestions_type = flags.index(4);
let children = Vec::<u32>::var_read_from(buf)?;
let redirect_node = if has_redirect {
@@ -224,16 +237,17 @@ impl McBufReadable for BrigadierNodeStub {
impl McBufWritable for BrigadierNodeStub {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
+ let mut flags = FixedBitSet::<4>::new();
+ if self.is_executable {
+ flags.set(2);
+ }
+ if self.redirect_node.is_some() {
+ flags.set(3);
+ }
+
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)?;
+ flags.write_into(buf)?;
self.children.var_write_into(buf)?;
@@ -242,14 +256,8 @@ impl McBufWritable for BrigadierNodeStub {
}
}
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)?;
+ flags.set(0);
+ flags.write_into(buf)?;
self.children.var_write_into(buf)?;
@@ -264,17 +272,11 @@ impl McBufWritable for BrigadierNodeStub {
parser,
suggestions_type,
} => {
- let mut flags = 0x02;
- if self.is_executable {
- flags |= 0x04;
- }
- if self.redirect_node.is_some() {
- flags |= 0x08;
- }
+ flags.set(1);
if suggestions_type.is_some() {
- flags |= 0x10;
+ flags.set(4);
}
- flags.var_write_into(buf)?;
+ flags.write_into(buf)?;
self.children.var_write_into(buf)?;
@@ -294,7 +296,7 @@ impl McBufWritable for BrigadierNodeStub {
}
}
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, PartialEq)]
pub enum NodeType {
Root,
Literal {
@@ -308,11 +310,67 @@ pub enum NodeType {
}
impl BrigadierNodeStub {
+ #[must_use]
pub fn name(&self) -> Option<&str> {
match &self.node_type {
NodeType::Root => None,
- NodeType::Literal { name } => Some(name),
- NodeType::Argument { name, .. } => Some(name),
+ NodeType::Literal { name } | NodeType::Argument { name, .. } => Some(name),
}
}
}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_brigadier_node_stub_root() {
+ let data = BrigadierNodeStub {
+ is_executable: false,
+ children: vec![1, 2],
+ redirect_node: None,
+ node_type: NodeType::Root,
+ };
+ let mut buf = Vec::new();
+ data.write_into(&mut buf).unwrap();
+ let mut data_cursor: Cursor<&[u8]> = Cursor::new(&buf);
+ let read_data = BrigadierNodeStub::read_from(&mut data_cursor).unwrap();
+ assert_eq!(data, read_data);
+ }
+
+ #[test]
+ fn test_brigadier_node_stub_literal() {
+ let data = BrigadierNodeStub {
+ is_executable: true,
+ children: vec![],
+ redirect_node: None,
+ node_type: NodeType::Literal {
+ name: "String".to_string(),
+ },
+ };
+ let mut buf = Vec::new();
+ data.write_into(&mut buf).unwrap();
+ let mut data_cursor: Cursor<&[u8]> = Cursor::new(&buf);
+ let read_data = BrigadierNodeStub::read_from(&mut data_cursor).unwrap();
+ assert_eq!(data, read_data);
+ }
+
+ #[test]
+ fn test_brigadier_node_stub_argument() {
+ let data = BrigadierNodeStub {
+ is_executable: false,
+ children: vec![6, 9],
+ redirect_node: Some(5),
+ node_type: NodeType::Argument {
+ name: "position".to_string(),
+ parser: BrigadierParser::Vec3,
+ suggestions_type: Some(ResourceLocation::new("minecraft:test_suggestion").unwrap()),
+ },
+ };
+ let mut buf = Vec::new();
+ data.write_into(&mut buf).unwrap();
+ let mut data_cursor: Cursor<&[u8]> = Cursor::new(&buf);
+ let read_data = BrigadierNodeStub::read_from(&mut data_cursor).unwrap();
+ assert_eq!(data, read_data);
+ }
+}
diff --git a/azalea-protocol/src/packets/game/clientbound_explode_packet.rs b/azalea-protocol/src/packets/game/clientbound_explode_packet.rs
index 58070769..2146a254 100755
--- a/azalea-protocol/src/packets/game/clientbound_explode_packet.rs
+++ b/azalea-protocol/src/packets/game/clientbound_explode_packet.rs
@@ -31,9 +31,9 @@ impl McBufReadable for ClientboundExplodePacket {
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;
+ let x = x_floor + i32::from(i8::read_from(buf)?);
+ let y = y_floor + i32::from(i8::read_from(buf)?);
+ let z = z_floor + i32::from(i8::read_from(buf)?);
to_blow.push(BlockPos { x, y, z });
}
diff --git a/azalea-protocol/src/packets/game/clientbound_map_item_data_packet.rs b/azalea-protocol/src/packets/game/clientbound_map_item_data_packet.rs
index 94593e3e..38d92135 100755
--- a/azalea-protocol/src/packets/game/clientbound_map_item_data_packet.rs
+++ b/azalea-protocol/src/packets/game/clientbound_map_item_data_packet.rs
@@ -1,71 +1,15 @@
-use azalea_buf::{BufReadError, McBuf};
-use azalea_buf::{McBufReadable, McBufVarReadable, McBufVarWritable, McBufWritable};
+use azalea_buf::{McBuf, McBufReadable, McBufWritable};
use azalea_chat::Component;
use azalea_protocol_macros::ClientboundGamePacket;
-use std::io::{Cursor, Write};
-#[derive(Clone, Debug, ClientboundGamePacket)]
+#[derive(Clone, Debug, ClientboundGamePacket, McBuf)]
pub struct ClientboundMapItemDataPacket {
- // #[var]
+ #[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 Cursor<&[u8]>) -> 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 = Option::<Vec<MapDecoration>>::read_from(buf)?.unwrap_or_default();
-
- 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.is_empty()).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(())
- }
+ pub decorations: Option<Vec<MapDecoration>>,
+ pub color_patch: OptionalMapPatch,
}
#[derive(Clone, Debug, McBuf)]
@@ -80,11 +24,35 @@ pub struct MapDecoration {
}
#[derive(Debug, Clone)]
+pub struct OptionalMapPatch(pub Option<MapPatch>);
+
+impl McBufReadable for OptionalMapPatch {
+ fn read_from(buf: &mut std::io::Cursor<&[u8]>) -> Result<Self, azalea_buf::BufReadError> {
+ let pos = buf.position();
+ Ok(Self(if u8::read_from(buf)? == 0 {
+ None
+ } else {
+ buf.set_position(pos);
+ Some(MapPatch::read_from(buf)?)
+ }))
+ }
+}
+
+impl McBufWritable for OptionalMapPatch {
+ fn write_into(&self, buf: &mut impl std::io::Write) -> Result<(), std::io::Error> {
+ match &self.0 {
+ None => 0u8.write_into(buf),
+ Some(m) => m.write_into(buf),
+ }
+ }
+}
+
+#[derive(Debug, Clone, McBuf)]
pub struct MapPatch {
- pub start_x: u8,
- pub start_y: u8,
pub width: u8,
pub height: u8,
+ pub start_x: u8,
+ pub start_y: u8,
pub map_colors: Vec<u8>,
}
diff --git a/azalea-protocol/src/packets/game/clientbound_player_abilities_packet.rs b/azalea-protocol/src/packets/game/clientbound_player_abilities_packet.rs
index 192a7bf4..12fd45e8 100755
--- a/azalea-protocol/src/packets/game/clientbound_player_abilities_packet.rs
+++ b/azalea-protocol/src/packets/game/clientbound_player_abilities_packet.rs
@@ -1,5 +1,6 @@
use azalea_buf::{BufReadError, McBuf};
use azalea_buf::{McBufReadable, McBufWritable};
+use azalea_core::FixedBitSet;
use azalea_protocol_macros::ClientboundGamePacket;
use std::io::{Cursor, Write};
@@ -21,31 +22,31 @@ pub struct PlayerAbilitiesFlags {
impl McBufReadable for PlayerAbilitiesFlags {
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
- let byte = u8::read_from(buf)?;
+ let set = FixedBitSet::<4>::read_from(buf)?;
Ok(PlayerAbilitiesFlags {
- invulnerable: byte & 1 != 0,
- flying: byte & 2 != 0,
- can_fly: byte & 4 != 0,
- instant_break: byte & 8 != 0,
+ invulnerable: set.index(0),
+ flying: set.index(1),
+ can_fly: set.index(2),
+ instant_break: set.index(3),
})
}
}
impl McBufWritable for PlayerAbilitiesFlags {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
- let mut byte = 0;
+ let mut set = FixedBitSet::<4>::new();
if self.invulnerable {
- byte |= 0b1;
+ set.set(0);
}
if self.flying {
- byte |= 0b10;
+ set.set(1);
}
if self.can_fly {
- byte |= 0b100;
+ set.set(2);
}
if self.instant_break {
- byte |= 0b1000;
+ set.set(3);
}
- u8::write_into(&byte, buf)
+ set.write_into(buf)
}
}
diff --git a/azalea-protocol/src/packets/game/clientbound_player_chat_packet.rs b/azalea-protocol/src/packets/game/clientbound_player_chat_packet.rs
index a735c907..098ffa03 100644
--- a/azalea-protocol/src/packets/game/clientbound_player_chat_packet.rs
+++ b/azalea-protocol/src/packets/game/clientbound_player_chat_packet.rs
@@ -90,6 +90,7 @@ impl ClientboundPlayerChatPacket {
/// Returns the content of the message. If you want to get the Component
/// for the whole message including the sender part, use
/// [`ClientboundPlayerChatPacket::message`].
+ #[must_use]
pub fn content(&self) -> Component {
self.unsigned_content
.clone()
@@ -97,6 +98,7 @@ impl ClientboundPlayerChatPacket {
}
/// Get the full message, including the sender part.
+ #[must_use]
pub fn message(&self) -> Component {
let sender = self.chat_type.name.clone();
let content = self.content();
@@ -119,6 +121,7 @@ impl ClientboundPlayerChatPacket {
}
impl ChatType {
+ #[must_use]
pub fn chat_translation_key(&self) -> &'static str {
match self {
ChatType::Chat => "chat.type.text",
@@ -131,15 +134,11 @@ impl ChatType {
}
}
+ #[must_use]
pub fn narrator_translation_key(&self) -> &'static str {
match self {
- ChatType::Chat => "chat.type.text.narrate",
- ChatType::SayCommand => "chat.type.text.narrate",
- ChatType::MsgCommandIncoming => "chat.type.text.narrate",
- ChatType::MsgCommandOutgoing => "chat.type.text.narrate",
- ChatType::TeamMsgCommandIncoming => "chat.type.text.narrate",
- ChatType::TeamMsgCommandOutgoing => "chat.type.text.narrate",
ChatType::EmoteCommand => "chat.type.emote",
+ _ => "chat.type.text.narrate",
}
}
}
diff --git a/azalea-protocol/src/packets/game/clientbound_player_position_packet.rs b/azalea-protocol/src/packets/game/clientbound_player_position_packet.rs
index 03a2658e..3ad422e7 100755
--- a/azalea-protocol/src/packets/game/clientbound_player_position_packet.rs
+++ b/azalea-protocol/src/packets/game/clientbound_player_position_packet.rs
@@ -1,5 +1,6 @@
use azalea_buf::{BufReadError, McBuf};
use azalea_buf::{McBufReadable, McBufWritable};
+use azalea_core::FixedBitSet;
use azalea_protocol_macros::ClientboundGamePacket;
use std::io::{Cursor, Write};
@@ -29,35 +30,35 @@ pub struct RelativeArguments {
impl McBufReadable for RelativeArguments {
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
- let byte = u8::read_from(buf)?;
+ let set = FixedBitSet::<5>::read_from(buf)?;
Ok(RelativeArguments {
- x: byte & 0b1 != 0,
- y: byte & 0b10 != 0,
- z: byte & 0b100 != 0,
- y_rot: byte & 0b1000 != 0,
- x_rot: byte & 0b10000 != 0,
+ x: set.index(0),
+ y: set.index(1),
+ z: set.index(2),
+ y_rot: set.index(3),
+ x_rot: set.index(4),
})
}
}
impl McBufWritable for RelativeArguments {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
- let mut byte = 0;
+ let mut set = FixedBitSet::<5>::new();
if self.x {
- byte |= 0b1;
+ set.set(0);
}
if self.y {
- byte |= 0b10;
+ set.set(1);
}
if self.z {
- byte |= 0b100;
+ set.set(2);
}
if self.y_rot {
- byte |= 0b1000;
+ set.set(3);
}
if self.x_rot {
- byte |= 0b10000;
+ set.set(4);
}
- u8::write_into(&byte, buf)
+ set.write_into(buf)
}
}
diff --git a/azalea-protocol/src/packets/game/clientbound_section_blocks_update_packet.rs b/azalea-protocol/src/packets/game/clientbound_section_blocks_update_packet.rs
index f9b1cd1e..1a8e0d40 100755
--- a/azalea-protocol/src/packets/game/clientbound_section_blocks_update_packet.rs
+++ b/azalea-protocol/src/packets/game/clientbound_section_blocks_update_packet.rs
@@ -38,7 +38,7 @@ impl McBufReadable for BlockStateWithPosition {
impl McBufWritable for BlockStateWithPosition {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
let data = (self.state as u64) << 12
- | ((self.pos.x as u64) << 8 | (self.pos.z as u64) << 4 | (self.pos.y as u64));
+ | (u64::from(self.pos.x) << 8 | u64::from(self.pos.z) << 4 | u64::from(self.pos.y));
u64::var_write_into(&data, buf)?;
Ok(())
}
diff --git a/azalea-protocol/src/packets/game/clientbound_set_equipment_packet.rs b/azalea-protocol/src/packets/game/clientbound_set_equipment_packet.rs
index 315f1590..11472591 100755
--- a/azalea-protocol/src/packets/game/clientbound_set_equipment_packet.rs
+++ b/azalea-protocol/src/packets/game/clientbound_set_equipment_packet.rs
@@ -65,6 +65,7 @@ pub enum EquipmentSlot {
}
impl EquipmentSlot {
+ #[must_use]
pub fn from_byte(byte: u8) -> Option<Self> {
match byte {
0 => Some(EquipmentSlot::MainHand),
diff --git a/azalea-protocol/src/packets/game/clientbound_set_objective_packet.rs b/azalea-protocol/src/packets/game/clientbound_set_objective_packet.rs
index ad75a1c3..9e2da325 100755
--- a/azalea-protocol/src/packets/game/clientbound_set_objective_packet.rs
+++ b/azalea-protocol/src/packets/game/clientbound_set_objective_packet.rs
@@ -22,7 +22,7 @@ impl McBufReadable for Method {
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 }),
+ id => return Err(BufReadError::UnexpectedEnumVariant { id: i32::from(id) }),
})
}
}
diff --git a/azalea-protocol/src/packets/game/clientbound_set_player_team_packet.rs b/azalea-protocol/src/packets/game/clientbound_set_player_team_packet.rs
index 2550a98c..0b3c1e24 100755
--- a/azalea-protocol/src/packets/game/clientbound_set_player_team_packet.rs
+++ b/azalea-protocol/src/packets/game/clientbound_set_player_team_packet.rs
@@ -26,7 +26,7 @@ impl McBufReadable for Method {
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 }),
+ id => return Err(BufReadError::UnexpectedEnumVariant { id: i32::from(id) }),
})
}
}
diff --git a/azalea-protocol/src/packets/game/clientbound_set_score_packet.rs b/azalea-protocol/src/packets/game/clientbound_set_score_packet.rs
index 7d055a14..56d14b94 100755
--- a/azalea-protocol/src/packets/game/clientbound_set_score_packet.rs
+++ b/azalea-protocol/src/packets/game/clientbound_set_score_packet.rs
@@ -45,7 +45,7 @@ impl McBufWritable for ClientboundSetScorePacket {
// convert None to an empty string
self.objective_name
.as_ref()
- .unwrap_or(&"".to_string())
+ .unwrap_or(&String::new())
.write_into(buf)?;
if let Method::Change { score } = self.method {
score.var_write_into(buf)?;
diff --git a/azalea-protocol/src/packets/game/clientbound_stop_sound_packet.rs b/azalea-protocol/src/packets/game/clientbound_stop_sound_packet.rs
index e0e5db05..5ea80e67 100755
--- a/azalea-protocol/src/packets/game/clientbound_stop_sound_packet.rs
+++ b/azalea-protocol/src/packets/game/clientbound_stop_sound_packet.rs
@@ -1,5 +1,5 @@
use azalea_buf::{BufReadError, McBufReadable, McBufWritable};
-use azalea_core::ResourceLocation;
+use azalea_core::{FixedBitSet, ResourceLocation};
use azalea_protocol_macros::ClientboundGamePacket;
use std::io::{Cursor, Write};
@@ -13,13 +13,13 @@ pub struct ClientboundStopSoundPacket {
impl McBufReadable for ClientboundStopSoundPacket {
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
- let byte = u8::read_from(buf)?;
- let source = if byte & 1 != 0 {
+ let set = FixedBitSet::<2>::read_from(buf)?;
+ let source = if set.index(0) {
Some(SoundSource::read_from(buf)?)
} else {
None
};
- let name = if byte & 2 != 0 {
+ let name = if set.index(1) {
Some(ResourceLocation::read_from(buf)?)
} else {
None
@@ -31,14 +31,14 @@ impl McBufReadable for ClientboundStopSoundPacket {
impl McBufWritable for ClientboundStopSoundPacket {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
- let mut byte = 0u8;
+ let mut set = FixedBitSet::<2>::new();
if self.source.is_some() {
- byte |= 1;
+ set.set(0);
}
if self.name.is_some() {
- byte |= 2;
+ set.set(1);
}
- byte.write_into(buf)?;
+ set.write_into(buf)?;
if let Some(source) = &self.source {
source.write_into(buf)?;
}
diff --git a/azalea-protocol/src/packets/game/clientbound_update_advancements_packet.rs b/azalea-protocol/src/packets/game/clientbound_update_advancements_packet.rs
index b18193d0..e2a46d38 100755
--- a/azalea-protocol/src/packets/game/clientbound_update_advancements_packet.rs
+++ b/azalea-protocol/src/packets/game/clientbound_update_advancements_packet.rs
@@ -17,10 +17,8 @@ pub struct ClientboundUpdateAdvancementsPacket {
pub struct Advancement {
parent_id: Option<ResourceLocation>,
display: Option<DisplayInfo>,
- // rewards: AdvancementRewards.EMPTY,
criteria: HashMap<ResourceLocation, Criterion>,
requirements: Vec<Vec<String>>,
- // requirements_strategy: RequirementsStrategy.AND
}
#[derive(Clone, Debug)]
@@ -87,11 +85,11 @@ impl azalea_buf::McBufReadable for DisplayInfo {
description,
icon,
frame,
+ show_toast,
+ hidden,
background,
x,
y,
- hidden,
- show_toast,
})
}
}
@@ -114,57 +112,77 @@ pub struct CriterionProgress {
date: Option<u64>,
}
-// #[cfg(test)]
-// mod tests {
-// use super::*;
-// use azalea_buf::{McBufReadable, McBufWritable};
-// use azalea_core::ResourceLocation;
-// use azalea_protocol_macros::ClientboundGamePacket;
-// use std::io::Cursor;
-
-// #[test]
-// fn test() {
-// let mut buf = Cursor::new(Vec::new());
-// let packet = ClientboundUpdateAdvancementsPacket {
-// reset: true,
-// added: [(
-// ResourceLocation::new("minecraft:test").unwrap(),
-// Advancement {
-// parent_id: None,
-// display: Some(DisplayInfo {
-// title: Component::from("title".to_string()),
-// description:
-// Component::from("description".to_string()), icon:
-// Slot::Empty, frame: FrameType::Task,
-// show_toast: true,
-// hidden: false,
-// background: None,
-// x: 0.0,
-// y: 0.0,
-// }),
-// criteria: HashMap::new(),
-// requirements: Vec::new(),
-// },
-// )]
-// .into_iter()
-// .collect(),
-// removed: vec![ResourceLocation::new("minecraft:test2").unwrap()],
-// progress: [(
-// ResourceLocation::new("minecraft:test3").unwrap(),
-// [(
-// ResourceLocation::new("minecraft:test4").unwrap(),
-// CriterionProgress {
-// date: Some(123456789),
-// },
-// )]
-// .into_iter()
-// .collect(),
-// )]
-// .into_iter()
-// .collect(),
-// };
-// packet.write_into(&mut buf).unwrap();
-// let packet = ClientboundUpdateAdvancementsPacket::read_from(&mut
-// buf).unwrap(); assert_eq!(packet.reset, true);
-// }
-// }
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use azalea_buf::{McBufReadable, McBufWritable};
+ use azalea_core::ResourceLocation;
+ use std::io::Cursor;
+
+ #[test]
+ fn test() {
+ let packet = ClientboundUpdateAdvancementsPacket {
+ reset: true,
+ added: [(
+ ResourceLocation::new("minecraft:test").unwrap(),
+ Advancement {
+ parent_id: None,
+ display: Some(DisplayInfo {
+ title: Component::from("title".to_string()),
+ description: Component::from("description".to_string()),
+ icon: Slot::Empty,
+ frame: FrameType::Task,
+ show_toast: true,
+ hidden: false,
+ background: None,
+ x: 0.0,
+ y: 0.0,
+ }),
+ criteria: HashMap::new(),
+ requirements: Vec::new(),
+ },
+ )]
+ .into_iter()
+ .collect(),
+ removed: vec![ResourceLocation::new("minecraft:test2").unwrap()],
+ progress: [(
+ ResourceLocation::new("minecraft:test3").unwrap(),
+ [(
+ ResourceLocation::new("minecraft:test4").unwrap(),
+ CriterionProgress {
+ date: Some(123456789),
+ },
+ )]
+ .into_iter()
+ .collect(),
+ )]
+ .into_iter()
+ .collect(),
+ };
+
+ let mut data = Vec::new();
+ packet.write_into(&mut data).unwrap();
+ let mut buf: Cursor<&[u8]> = Cursor::new(&data);
+
+ let read_packet = ClientboundUpdateAdvancementsPacket::read_from(&mut buf).unwrap();
+ assert_eq!(packet.reset, read_packet.reset);
+ assert_eq!(packet.removed, read_packet.removed);
+
+ let advancement = packet
+ .added
+ .get(&ResourceLocation::new("minecraft:test").unwrap())
+ .unwrap()
+ .clone();
+ let read_advancement = read_packet
+ .added
+ .get(&ResourceLocation::new("minecraft:test").unwrap())
+ .unwrap()
+ .clone();
+ assert_eq!(advancement.parent_id, read_advancement.parent_id);
+
+ let display = advancement.display.unwrap();
+ let read_display = read_advancement.display.unwrap();
+ assert_eq!(display.title, read_display.title);
+ assert_eq!(display.description, read_display.description);
+ }
+}
diff --git a/azalea-protocol/src/packets/game/serverbound_client_information_packet.rs b/azalea-protocol/src/packets/game/serverbound_client_information_packet.rs
index 61fcbfbe..95f49a23 100755
--- a/azalea-protocol/src/packets/game/serverbound_client_information_packet.rs
+++ b/azalea-protocol/src/packets/game/serverbound_client_information_packet.rs
@@ -1,7 +1,8 @@
-use azalea_buf::McBuf;
+use azalea_buf::{McBuf, McBufReadable, McBufWritable};
+use azalea_core::FixedBitSet;
use azalea_protocol_macros::ServerboundGamePacket;
-#[derive(Clone, Debug, McBuf, ServerboundGamePacket)]
+#[derive(Clone, Debug, McBuf, ServerboundGamePacket, PartialEq, Eq)]
pub struct ServerboundClientInformationPacket {
/// The locale of the client.
pub language: String,
@@ -14,7 +15,7 @@ pub struct ServerboundClientInformationPacket {
/// Whether the messages sent from the server should have colors. Note that
/// many servers ignore this and always send colored messages.
pub chat_colors: bool,
- pub model_customisation: u8,
+ pub model_customisation: ModelCustomization,
pub main_hand: HumanoidArm,
pub text_filtering_enabled: bool,
/// Whether the client should show up as "Anonymous Player" in the server
@@ -27,9 +28,9 @@ impl Default for ServerboundClientInformationPacket {
Self {
language: "en_us".to_string(),
view_distance: 8,
- chat_visibility: ChatVisibility::Full,
+ chat_visibility: ChatVisibility::default(),
chat_colors: true,
- model_customisation: 0,
+ model_customisation: ModelCustomization::default(),
main_hand: HumanoidArm::Right,
text_filtering_enabled: false,
allows_listing: false,
@@ -37,9 +38,10 @@ impl Default for ServerboundClientInformationPacket {
}
}
-#[derive(McBuf, Clone, Copy, Debug)]
+#[derive(McBuf, Clone, Copy, Debug, PartialEq, Eq, Default)]
pub enum ChatVisibility {
/// All chat messages should be sent to the client.
+ #[default]
Full = 0,
/// Chat messages from other players should be not sent to the client, only
/// messages from the server like "Player joined the game" should be sent.
@@ -48,8 +50,125 @@ pub enum ChatVisibility {
Hidden = 2,
}
-#[derive(McBuf, Clone, Copy, Debug)]
+#[derive(McBuf, Clone, Copy, Debug, PartialEq, Eq, Default)]
pub enum HumanoidArm {
Left = 0,
+ #[default]
Right = 1,
}
+
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub struct ModelCustomization {
+ pub cape: bool,
+ pub jacket: bool,
+ pub left_sleeve: bool,
+ pub right_sleeve: bool,
+ pub left_pants: bool,
+ pub right_pants: bool,
+ pub hat: bool,
+}
+
+impl Default for ModelCustomization {
+ fn default() -> Self {
+ Self {
+ cape: true,
+ jacket: true,
+ left_sleeve: true,
+ right_sleeve: true,
+ left_pants: true,
+ right_pants: true,
+ hat: true,
+ }
+ }
+}
+
+impl McBufReadable for ModelCustomization {
+ fn read_from(buf: &mut std::io::Cursor<&[u8]>) -> Result<Self, azalea_buf::BufReadError> {
+ let set = FixedBitSet::<7>::read_from(buf)?;
+ Ok(Self {
+ cape: set.index(0),
+ jacket: set.index(1),
+ left_sleeve: set.index(2),
+ right_sleeve: set.index(3),
+ left_pants: set.index(4),
+ right_pants: set.index(5),
+ hat: set.index(6),
+ })
+ }
+}
+
+impl McBufWritable for ModelCustomization {
+ fn write_into(&self, buf: &mut impl std::io::Write) -> Result<(), std::io::Error> {
+ let mut set = FixedBitSet::<7>::new();
+ if self.cape {
+ set.set(0);
+ }
+ if self.jacket {
+ set.set(1);
+ }
+ if self.left_sleeve {
+ set.set(2);
+ }
+ if self.right_sleeve {
+ set.set(3);
+ }
+ if self.left_pants {
+ set.set(4);
+ }
+ if self.right_pants {
+ set.set(5);
+ }
+ if self.hat {
+ set.set(6);
+ }
+ set.write_into(buf)
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use std::io::Cursor;
+
+ #[test]
+ fn test_client_information_packet() {
+ {
+ let data = ServerboundClientInformationPacket::default();
+ let mut buf = Vec::new();
+ data.write_into(&mut buf).unwrap();
+ let mut data_cursor: Cursor<&[u8]> = Cursor::new(&buf);
+
+ let read_data =
+ ServerboundClientInformationPacket::read_from(&mut data_cursor).unwrap();
+ assert_eq!(read_data, data);
+ }
+
+ {
+ let data = ServerboundClientInformationPacket {
+ language: "en_gb".to_string(),
+ view_distance: 24,
+ chat_visibility: ChatVisibility::Hidden,
+ chat_colors: false,
+ model_customisation: ModelCustomization {
+ cape: false,
+ jacket: false,
+ left_sleeve: true,
+ right_sleeve: false,
+ left_pants: true,
+ right_pants: false,
+ hat: true,
+ },
+ main_hand: HumanoidArm::Left,
+ text_filtering_enabled: true,
+ allows_listing: true,
+ };
+ let mut buf = Vec::new();
+ data.write_into(&mut buf).unwrap();
+ let mut data_cursor: Cursor<&[u8]> = Cursor::new(&buf);
+
+ let read_data =
+ ServerboundClientInformationPacket::read_from(&mut data_cursor).unwrap();
+ assert_eq!(read_data, data);
+ }
+ }
+}
diff --git a/azalea-protocol/src/packets/game/serverbound_interact_packet.rs b/azalea-protocol/src/packets/game/serverbound_interact_packet.rs
index 1904accf..a117ca6f 100755
--- a/azalea-protocol/src/packets/game/serverbound_interact_packet.rs
+++ b/azalea-protocol/src/packets/game/serverbound_interact_packet.rs
@@ -63,9 +63,9 @@ impl McBufReadable for ActionType {
let hand = InteractionHand::read_from(buf)?;
Ok(ActionType::InteractAt {
location: Vec3 {
- x: x as f64,
- y: y as f64,
- z: z as f64,
+ x: f64::from(x),
+ y: f64::from(y),
+ z: f64::from(z),
},
hand,
})
diff --git a/azalea-protocol/src/packets/game/serverbound_player_abilities_packet.rs b/azalea-protocol/src/packets/game/serverbound_player_abilities_packet.rs
index 7f979363..1f8727ac 100755
--- a/azalea-protocol/src/packets/game/serverbound_player_abilities_packet.rs
+++ b/azalea-protocol/src/packets/game/serverbound_player_abilities_packet.rs
@@ -1,29 +1,29 @@
use crate::packets::BufReadError;
use azalea_buf::{McBufReadable, McBufWritable};
+use azalea_core::FixedBitSet;
use azalea_protocol_macros::ServerboundGamePacket;
use std::io::Cursor;
#[derive(Clone, Debug, ServerboundGamePacket)]
pub struct ServerboundPlayerAbilitiesPacket {
- is_flying: bool,
+ pub is_flying: bool,
}
impl McBufReadable for ServerboundPlayerAbilitiesPacket {
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
- let byte = u8::read_from(buf)?;
+ let set = FixedBitSet::<2>::read_from(buf)?;
Ok(Self {
- is_flying: byte & 2 != 0,
+ is_flying: set.index(1),
})
}
}
impl McBufWritable for ServerboundPlayerAbilitiesPacket {
fn write_into(&self, buf: &mut impl std::io::Write) -> Result<(), std::io::Error> {
- let mut byte = 0;
+ let mut set = FixedBitSet::<2>::new();
if self.is_flying {
- byte |= 2;
+ set.set(1);
}
- u8::write_into(&byte, buf)?;
- Ok(())
+ set.write_into(buf)
}
}
diff --git a/azalea-protocol/src/packets/game/serverbound_player_input_packet.rs b/azalea-protocol/src/packets/game/serverbound_player_input_packet.rs
index 2bd7f6eb..f0c7c548 100755
--- a/azalea-protocol/src/packets/game/serverbound_player_input_packet.rs
+++ b/azalea-protocol/src/packets/game/serverbound_player_input_packet.rs
@@ -2,6 +2,7 @@ use std::io::Cursor;
use azalea_buf::BufReadError;
use azalea_buf::{McBufReadable, McBufWritable};
+use azalea_core::FixedBitSet;
use azalea_protocol_macros::ServerboundGamePacket;
#[derive(Clone, Debug, ServerboundGamePacket)]
@@ -16,14 +17,12 @@ impl McBufReadable for ServerboundPlayerInputPacket {
fn read_from(buf: &mut Cursor<&[u8]>) -> 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;
+ let set = FixedBitSet::<2>::read_from(buf)?;
Ok(Self {
xxa,
zza,
- is_jumping,
- is_shift_key_down,
+ is_jumping: set.index(0),
+ is_shift_key_down: set.index(1),
})
}
}
@@ -32,14 +31,13 @@ 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 = 0u8;
+ let mut set = FixedBitSet::<2>::new();
if self.is_jumping {
- byte |= 1;
+ set.set(0);
}
if self.is_shift_key_down {
- byte |= 2;
+ set.set(1);
}
- byte.write_into(buf)?;
- Ok(())
+ set.write_into(buf)
}
}
diff --git a/azalea-protocol/src/packets/game/serverbound_set_command_block_packet.rs b/azalea-protocol/src/packets/game/serverbound_set_command_block_packet.rs
index 7edb9719..d73654c2 100755
--- a/azalea-protocol/src/packets/game/serverbound_set_command_block_packet.rs
+++ b/azalea-protocol/src/packets/game/serverbound_set_command_block_packet.rs
@@ -1,6 +1,6 @@
use crate::packets::McBufWritable;
use azalea_buf::{BufReadError, McBuf, McBufReadable};
-use azalea_core::BlockPos;
+use azalea_core::{BlockPos, FixedBitSet};
use azalea_protocol_macros::ServerboundGamePacket;
use std::io::Cursor;
@@ -28,17 +28,14 @@ impl McBufReadable for ServerboundSetCommandBlockPacket {
let command = String::read_from(buf)?;
let mode = Mode::read_from(buf)?;
- let byte = u8::read_from(buf)?;
- let track_output = byte & 1 != 0;
- let conditional = byte & 2 != 0;
- let automatic = byte & 4 != 0;
+ let set = FixedBitSet::<3>::read_from(buf)?;
Ok(Self {
pos,
command,
mode,
- track_output,
- conditional,
- automatic,
+ track_output: set.index(0),
+ conditional: set.index(1),
+ automatic: set.index(2),
})
}
}
@@ -49,17 +46,16 @@ impl McBufWritable for ServerboundSetCommandBlockPacket {
self.command.write_into(buf)?;
self.mode.write_into(buf)?;
- let mut byte: u8 = 0;
+ let mut set = FixedBitSet::<3>::new();
if self.track_output {
- byte |= 1;
+ set.set(0);
}
if self.conditional {
- byte |= 2;
+ set.set(1);
}
if self.automatic {
- byte |= 4;
+ set.set(2);
}
- byte.write_into(buf)?;
- Ok(())
+ set.write_into(buf)
}
}
diff --git a/azalea-protocol/src/packets/game/serverbound_set_structure_block_packet.rs b/azalea-protocol/src/packets/game/serverbound_set_structure_block_packet.rs
index 901d3f89..28cc0035 100755
--- a/azalea-protocol/src/packets/game/serverbound_set_structure_block_packet.rs
+++ b/azalea-protocol/src/packets/game/serverbound_set_structure_block_packet.rs
@@ -1,7 +1,7 @@
use crate::packets::BufReadError;
use azalea_buf::McBuf;
use azalea_buf::{McBufReadable, McBufWritable};
-use azalea_core::BlockPos;
+use azalea_core::{BlockPos, FixedBitSet};
use azalea_protocol_macros::ServerboundGamePacket;
use std::io::{Cursor, Write};
@@ -69,28 +69,28 @@ pub struct Flags {
impl McBufReadable for Flags {
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
- let byte = u8::read_from(buf)?;
+ let set = FixedBitSet::<3>::read_from(buf)?;
Ok(Self {
- ignore_entities: byte & 1 != 0,
- show_air: byte & 2 != 0,
- show_bounding_box: byte & 4 != 0,
+ ignore_entities: set.index(0),
+ show_air: set.index(1),
+ show_bounding_box: set.index(2),
})
}
}
impl McBufWritable for Flags {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
- let mut byte = 0;
+ let mut set = FixedBitSet::<3>::new();
if self.ignore_entities {
- byte |= 1;
+ set.set(0);
}
if self.show_air {
- byte |= 2;
+ set.set(1);
}
if self.show_bounding_box {
- byte |= 4;
+ set.set(2);
}
- u8::write_into(&byte, buf)?;
+ set.write_into(buf)?;
Ok(())
}
}
diff --git a/azalea-protocol/src/packets/game/serverbound_use_item_on_packet.rs b/azalea-protocol/src/packets/game/serverbound_use_item_on_packet.rs
index ded977aa..17b537b6 100755
--- a/azalea-protocol/src/packets/game/serverbound_use_item_on_packet.rs
+++ b/azalea-protocol/src/packets/game/serverbound_use_item_on_packet.rs
@@ -24,9 +24,9 @@ impl McBufWritable for BlockHitResult {
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
self.block_pos.write_into(buf)?;
self.direction.write_into(buf)?;
- f32::write_into(&((self.location.x - (self.block_pos.x as f64)) as f32), buf)?;
- f32::write_into(&((self.location.y - (self.block_pos.y as f64)) as f32), buf)?;
- f32::write_into(&((self.location.z - (self.block_pos.z as f64)) as f32), buf)?;
+ f32::write_into(&((self.location.x - f64::from(self.block_pos.x)) as f32), buf)?;
+ f32::write_into(&((self.location.y - f64::from(self.block_pos.y)) as f32), buf)?;
+ f32::write_into(&((self.location.z - f64::from(self.block_pos.z)) as f32), buf)?;
self.inside.write_into(buf)?;
Ok(())
}
@@ -44,9 +44,9 @@ impl McBufReadable for BlockHitResult {
block_pos,
direction,
location: Vec3 {
- x: block_pos.x as f64 + cursor_x as f64,
- y: block_pos.y as f64 + cursor_y as f64,
- z: block_pos.z as f64 + cursor_z as f64,
+ x: f64::from(block_pos.x) + f64::from(cursor_x),
+ y: f64::from(block_pos.y) + f64::from(cursor_y),
+ z: f64::from(block_pos.z) + f64::from(cursor_z),
},
inside,
})
diff --git a/azalea-protocol/src/packets/mod.rs b/azalea-protocol/src/packets/mod.rs
index 508d06a6..e803e85f 100755
--- a/azalea-protocol/src/packets/mod.rs
+++ b/azalea-protocol/src/packets/mod.rs
@@ -21,6 +21,7 @@ pub enum ConnectionProtocol {
}
impl ConnectionProtocol {
+ #[must_use]
pub fn from_i32(i: i32) -> Option<Self> {
match i {
-1 => Some(ConnectionProtocol::Handshake),
@@ -39,7 +40,7 @@ where
{
fn id(&self) -> u32;
- /// Read a packet by its id, ConnectionProtocol, and flow
+ /// Read a packet by its id, `ConnectionProtocol`, and flow
fn read(id: u32, buf: &mut Cursor<&[u8]>) -> Result<Self, Box<ReadPacketError>>;
fn write(&self, buf: &mut impl Write) -> Result<(), std::io::Error>;
diff --git a/azalea-protocol/src/read.rs b/azalea-protocol/src/read.rs
index 7f81cfef..753717b9 100755
--- a/azalea-protocol/src/read.rs
+++ b/azalea-protocol/src/read.rs
@@ -76,8 +76,8 @@ pub enum FrameSplitterError {
ConnectionClosed,
}
-/// Read a length, then read that amount of bytes from BytesMut. If there's not
-/// enough data, return None
+/// Read a length, then read that amount of bytes from `BytesMut`. If there's
+/// not enough data, return None
fn parse_frame(buffer: &mut BytesMut) -> Result<BytesMut, FrameSplitterError> {
// copy the buffer first and read from the copy, then once we make sure
// the packet is all good we read it fully
@@ -258,41 +258,28 @@ where
Ok(packet)
}
-// #[cfg(test)]
-// mod tests {
-// use super::*;
-// use crate::packets::game::{clientbound_player_chat_packet::ChatType,
-// ClientboundGamePacket}; use std::io::Cursor;
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::packets::game::ClientboundGamePacket;
+ use std::io::Cursor;
-// #[tokio::test]
-// async fn test_read_packet() {
-// let mut buf: Cursor<&[u8]> = Cursor::new(&[
-// 51, 0, 12, 177, 250, 155, 132, 106, 60, 218, 161, 217, 90, 157,
-// 105, 57, 206, 20, 0, 5, 104, 101, 108, 108, 111, 0, 0, 0, 0, 0,
-// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 116, 123, 34, 101, 120,
-// 116, 114, 97, 34, 58, 91, 123, 34, 99, 111, 108, 111, 114, 34, 58,
-// 34, 103, 114, 97, 121, 34, 44, 34, 116, 101, 120, 116, 34, 58,
-// 34, 91, 77, 69, 77, 66, 69, 82, 93, 32, 112, 108, 97, 121, 101,
-// 114, 49, 34, 125, 44, 123, 34, 116, 101, 120, 116, 34, 58, 34,
-// 32, 34, 125, 44, 123, 34, 99, 111, 108, 111, 114, 34, 58, 34, 103,
-// 114, 97, 121, 34, 44, 34, 116, 101, 120, 116, 34, 58, 34, 92,
-// 117, 48, 48, 51, 101, 32, 104, 101, 108, 108, 111, 34, 125, 93,
-// 44, 34, 116, 101, 120, 116, 34, 58, 34, 34, 125, 0, 7, 64, 123,
-// 34, 101, 120, 116, 114, 97, 34, 58, 91, 123, 34, 99, 111, 108, 111, 114,
-// 34, 58, 34, 103, 114, 97, 121, 34, 44, 34, 116, 101, 120, 116,
-// 34, 58, 34, 91, 77, 69, 77, 66, 69, 82, 93, 32, 112, 108, 97,
-// 121, 101, 114, 49, 34, 125, 93, 44, 34, 116, 101, 120, 116, 34,
-// 58, 34, 34, 125, 0, ]);
-// let packet = packet_decoder::<ClientboundGamePacket>(&mut
-// buf).unwrap(); match &packet {
-// ClientboundGamePacket::PlayerChat(m) => {
-// assert_eq!(
-// m.chat_type.chat_type,
-// ChatType::Chat,
-// "Enums should default if they're invalid"
-// );
-// }
-// _ => panic!("Wrong packet type"),
-// }
-// }
-// }
+ #[tokio::test]
+ async fn test_read_packet() {
+ let mut buf: Cursor<&[u8]> = Cursor::new(&[
+ 56, 64, 85, 58, 141, 138, 71, 146, 193, 64, 88, 0, 0, 0, 0, 0, 0, 64, 60, 224, 105, 34,
+ 119, 8, 228, 67, 50, 51, 68, 194, 177, 230, 101, 0, 17, 0,
+ ]);
+ let packet = packet_decoder::<ClientboundGamePacket>(&mut buf).unwrap();
+ match &packet {
+ ClientboundGamePacket::PlayerPosition(p) => {
+ assert_eq!(p.id, 17);
+ assert_eq!(p.x, 84.91488892545296);
+ assert_eq!(p.y, 96.0);
+ assert_eq!(p.z, 28.876604227124417);
+ assert_eq!(p.dismount_vehicle, false);
+ }
+ _ => panic!("Wrong packet type"),
+ }
+ }
+}
diff --git a/azalea-protocol/src/resolver.rs b/azalea-protocol/src/resolver.rs
index dde5af3a..d12654f2 100755
--- a/azalea-protocol/src/resolver.rs
+++ b/azalea-protocol/src/resolver.rs
@@ -19,6 +19,7 @@ pub enum ResolverError {
/// Resolve a Minecraft server address into an IP address and port.
/// If it's already an IP address, it's returned as-is.
+#[must_use]
#[async_recursion]
pub async fn resolve_address(address: &ServerAddress) -> Result<SocketAddr, ResolverError> {
// If the address.host is already in the format of an ip address, return it.