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

clientbound_add_entity_packet & clientbound_set_entity_data_packet

This commit is contained in:
mat 2022-05-01 13:51:59 -05:00
parent 4b1cfd1cf8
commit 9dacd90abc
14 changed files with 660 additions and 121 deletions

View file

@ -1,3 +1,3 @@
# Azalea Client # Azalea Client
A library that can mimic everything a normal Minecraft client can do. If you want to make a bot with higher-level functions, you should use `azalea` instead. A library that can mimic everything a normal Minecraft client can do. If you want to make a bot with higher-level functions, you should use the `azalea` crate instead.

View file

@ -200,7 +200,7 @@ impl Client {
println!("Got update tags packet"); println!("Got update tags packet");
} }
GamePacket::ClientboundDisconnectPacket(p) => { GamePacket::ClientboundDisconnectPacket(p) => {
println!("Got login disconnect packet {:?}", p); println!("Got disconnect packet {:?}", p);
} }
GamePacket::ClientboundUpdateRecipesPacket(p) => { GamePacket::ClientboundUpdateRecipesPacket(p) => {
println!("Got update recipes packet"); println!("Got update recipes packet");
@ -230,6 +230,9 @@ impl Client {
GamePacket::ClientboundAddMobPacket(p) => { GamePacket::ClientboundAddMobPacket(p) => {
println!("Got add mob packet {:?}", p); println!("Got add mob packet {:?}", p);
} }
GamePacket::ClientboundAddEntityPacket(p) => {
println!("Got add entity packet {:?}", p);
}
_ => panic!("Unexpected packet {:?}", packet), _ => panic!("Unexpected packet {:?}", packet),
} }
println!(); println!();

View file

@ -0,0 +1,6 @@
#[derive(Clone, Copy, Debug)]
pub struct BlockPos {
pub x: i32,
pub y: i32,
pub z: i32,
}

View file

@ -0,0 +1,9 @@
#[derive(Clone, Copy, Debug)]
pub enum Direction {
Down = 0,
Up = 1,
North = 2,
South = 3,
West = 4,
East = 5,
}

View file

@ -7,3 +7,9 @@ pub mod serializable_uuid;
mod slot; mod slot;
pub use slot::{Slot, SlotData}; pub use slot::{Slot, SlotData};
mod block_pos;
pub use block_pos::BlockPos;
mod direction;
pub use direction::Direction;

View file

@ -7,105 +7,146 @@ use syn::{
}; };
fn create_impl_mcbufreadable(ident: &Ident, data: &Data) -> proc_macro2::TokenStream { fn create_impl_mcbufreadable(ident: &Ident, data: &Data) -> proc_macro2::TokenStream {
let fields = match data { match data {
syn::Data::Struct(syn::DataStruct { fields, .. }) => fields, syn::Data::Struct(syn::DataStruct { fields, .. }) => {
_ => panic!("#[derive(*Packet)] can only be used on structs"), let FieldsNamed { named, .. } = match fields {
}; syn::Fields::Named(f) => f,
let FieldsNamed { named, .. } = match fields { _ => panic!("#[derive(*Packet)] can only be used on structs with named fields"),
syn::Fields::Named(f) => f, };
_ => panic!("#[derive(*Packet)] can only be used on structs with named fields"),
};
let read_fields = named let read_fields = named
.iter() .iter()
.map(|f| { .map(|f| {
let field_name = &f.ident; let field_name = &f.ident;
let field_type = &f.ty; let field_type = &f.ty;
// do a different buf.write_* for each field depending on the type // do a different buf.write_* for each field depending on the type
// if it's a string, use buf.write_string // if it's a string, use buf.write_string
match field_type { match field_type {
syn::Type::Path(_) => { syn::Type::Path(_) => {
if f.attrs.iter().any(|a| a.path.is_ident("varint")) { if f.attrs.iter().any(|a| a.path.is_ident("varint")) {
quote! { quote! {
let #field_name = crate::mc_buf::McBufVarintReadable::varint_read_into(buf).await?; let #field_name = crate::mc_buf::McBufVarintReadable::varint_read_into(buf).await?;
} }
} else { } else {
quote! { quote! {
let #field_name = crate::mc_buf::McBufReadable::read_into(buf).await?; let #field_name = crate::mc_buf::McBufReadable::read_into(buf).await?;
}
} }
}
_ => panic!(
"Error reading field {}: {}",
field_name.clone().unwrap(),
field_type.to_token_stream()
),
}
})
.collect::<Vec<_>>();
let read_field_names = named.iter().map(|f| &f.ident).collect::<Vec<_>>();
quote! {
#[async_trait::async_trait]
impl crate::mc_buf::McBufReadable for #ident {
async fn read_into<R>(buf: &mut R) -> Result<Self, String>
where
R: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send,
{
#(#read_fields)*
Ok(#ident {
#(#read_field_names: #read_field_names),*
})
}
}
}
}
syn::Data::Enum(syn::DataEnum { variants, .. }) => {
let mut match_contents = quote!();
for variant in variants {
let variant_name = &variant.ident;
let variant_discrim = &variant
.discriminant
.as_ref()
.expect("enum variant must have a discriminant")
.1;
match_contents.extend(quote! {
#variant_discrim => Ok(Self::#variant_name),
});
}
quote! {
#[async_trait::async_trait]
impl crate::mc_buf::McBufReadable for #ident {
async fn read_into<R>(buf: &mut R) -> Result<Self, String>
where
R: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send,
{
let id = buf.read_varint().await?;
match id {
#match_contents
_ => Err(format!("Unknown enum variant {}", id)),
} }
} }
_ => panic!(
"Error reading field {}: {}",
field_name.clone().unwrap(),
field_type.to_token_stream()
),
} }
}) }
.collect::<Vec<_>>();
let read_field_names = named.iter().map(|f| &f.ident).collect::<Vec<_>>();
quote! {
#[async_trait::async_trait]
impl crate::mc_buf::McBufReadable for #ident {
async fn read_into<R>(buf: &mut R) -> Result<Self, String>
where
R: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send,
{
#(#read_fields)*
Ok(#ident {
#(#read_field_names: #read_field_names),*
})
} }
} _ => panic!("#[derive(*Packet)] can only be used on structs"),
} }
} }
fn create_impl_mcbufwritable(ident: &Ident, data: &Data) -> proc_macro2::TokenStream { fn create_impl_mcbufwritable(ident: &Ident, data: &Data) -> proc_macro2::TokenStream {
let fields = match data { match data {
syn::Data::Struct(syn::DataStruct { fields, .. }) => fields, syn::Data::Struct(syn::DataStruct { fields, .. }) => {
_ => panic!("#[derive(*Packet)] can only be used on structs"), let FieldsNamed { named, .. } = match fields {
}; syn::Fields::Named(f) => f,
let FieldsNamed { named, .. } = match fields { _ => panic!("#[derive(*Packet)] can only be used on structs with named fields"),
syn::Fields::Named(f) => f, };
_ => panic!("#[derive(*Packet)] can only be used on structs with named fields"),
};
let write_fields = named let write_fields = named
.iter() .iter()
.map(|f| { .map(|f| {
let field_name = &f.ident; let field_name = &f.ident;
let field_type = &f.ty; let field_type = &f.ty;
// do a different buf.write_* for each field depending on the type // do a different buf.write_* for each field depending on the type
// if it's a string, use buf.write_string // if it's a string, use buf.write_string
match field_type { match field_type {
syn::Type::Path(_) => { syn::Type::Path(_) => {
if f.attrs.iter().any(|attr| attr.path.is_ident("varint")) { if f.attrs.iter().any(|attr| attr.path.is_ident("varint")) {
quote! { quote! {
crate::mc_buf::McBufVarintWritable::varint_write_into(&self.#field_name, buf)?; crate::mc_buf::McBufVarintWritable::varint_write_into(&self.#field_name, buf)?;
} }
} else { } else {
quote! { quote! {
crate::mc_buf::McBufWritable::write_into(&self.#field_name, buf)?; crate::mc_buf::McBufWritable::write_into(&self.#field_name, buf)?;
}
} }
} }
_ => panic!(
"Error writing field {}: {}",
field_name.clone().unwrap(),
field_type.to_token_stream()
),
} }
_ => panic!( })
"Error writing field {}: {}", .collect::<Vec<_>>();
field_name.clone().unwrap(),
field_type.to_token_stream()
),
}
})
.collect::<Vec<_>>();
quote! { quote! {
impl crate::mc_buf::McBufWritable for #ident { impl crate::mc_buf::McBufWritable for #ident {
fn write_into(&self, buf: &mut Vec<u8>) -> Result<(), std::io::Error> { fn write_into(&self, buf: &mut Vec<u8>) -> Result<(), std::io::Error> {
#(#write_fields)* #(#write_fields)*
Ok(()) Ok(())
}
}
} }
} }
syn::Data::Enum(syn::DataEnum { .. }) => {
quote! {
impl crate::mc_buf::McBufWritable for #ident {
fn write_into(&self, buf: &mut Vec<u8>) -> Result<(), std::io::Error> {
crate::mc_buf::Writable::write_varint(buf, *self as i32)
}
}
}
}
_ => panic!("#[derive(*Packet)] can only be used on structs"),
} }
} }

View file

@ -2,7 +2,7 @@ use async_trait::async_trait;
use azalea_chat::component::Component; use azalea_chat::component::Component;
use azalea_core::{ use azalea_core::{
difficulty::Difficulty, game_type::GameType, resource_location::ResourceLocation, difficulty::Difficulty, game_type::GameType, resource_location::ResourceLocation,
serializable_uuid::SerializableUuid, Slot, SlotData, serializable_uuid::SerializableUuid, BlockPos, Direction, Slot, SlotData,
}; };
use serde::Deserialize; use serde::Deserialize;
use tokio::io::{AsyncRead, AsyncReadExt}; use tokio::io::{AsyncRead, AsyncReadExt};
@ -473,29 +473,14 @@ impl McBufReadable for Option<GameType> {
// Option<String> // Option<String>
#[async_trait] #[async_trait]
impl McBufReadable for Option<String> { impl<T: McBufReadable> McBufReadable for Option<T> {
async fn read_into<R>(buf: &mut R) -> Result<Self, String> default async fn read_into<R>(buf: &mut R) -> Result<Self, String>
where where
R: AsyncRead + std::marker::Unpin + std::marker::Send, R: AsyncRead + std::marker::Unpin + std::marker::Send,
{ {
let present = buf.read_boolean().await?; let present = buf.read_boolean().await?;
Ok(if present { Ok(if present {
Some(buf.read_utf().await?) Some(T::read_into(buf).await?)
} else {
None
})
}
}
// Option<Component>
#[async_trait]
impl McBufReadable for Option<Component> {
async fn read_into<R>(buf: &mut R) -> Result<Self, String>
where
R: AsyncRead + std::marker::Unpin + std::marker::Send,
{
let present = buf.read_boolean().await?;
Ok(if present {
Some(Component::read_into(buf).await?)
} else { } else {
None None
}) })
@ -567,3 +552,37 @@ impl McBufReadable for Uuid {
buf.read_uuid().await buf.read_uuid().await
} }
} }
// BlockPos
#[async_trait]
impl McBufReadable for BlockPos {
async fn read_into<R>(buf: &mut R) -> Result<Self, String>
where
R: AsyncRead + std::marker::Unpin + std::marker::Send,
{
let val = u64::read_into(buf).await?;
let x = (val >> 38) as i32;
let y = (val & 0xFFF) as i32;
let z = ((val >> 12) & 0x3FFFFFF) as i32;
Ok(BlockPos { x, y, z })
}
}
// Direction
#[async_trait]
impl McBufReadable for Direction {
async fn read_into<R>(buf: &mut R) -> Result<Self, String>
where
R: AsyncRead + std::marker::Unpin + std::marker::Send,
{
match buf.read_varint().await? {
0 => Ok(Self::Down),
1 => Ok(Self::Up),
2 => Ok(Self::North),
3 => Ok(Self::South),
4 => Ok(Self::West),
5 => Ok(Self::East),
_ => Err("Invalid direction".to_string()),
}
}
}

View file

@ -3,7 +3,7 @@ use async_trait::async_trait;
use azalea_chat::component::Component; use azalea_chat::component::Component;
use azalea_core::{ use azalea_core::{
difficulty::Difficulty, game_type::GameType, resource_location::ResourceLocation, difficulty::Difficulty, game_type::GameType, resource_location::ResourceLocation,
serializable_uuid::SerializableUuid, Slot, serializable_uuid::SerializableUuid, BlockPos, Direction, Slot,
}; };
use byteorder::{BigEndian, WriteBytesExt}; use byteorder::{BigEndian, WriteBytesExt};
use std::io::Write; use std::io::Write;
@ -336,21 +336,8 @@ impl McBufWritable for Option<GameType> {
} }
// Option<String> // Option<String>
impl McBufWritable for Option<String> { impl<T: McBufWritable> McBufWritable for Option<T> {
fn write_into(&self, buf: &mut Vec<u8>) -> Result<(), std::io::Error> { default fn write_into(&self, buf: &mut Vec<u8>) -> Result<(), std::io::Error> {
if let Some(s) = self {
buf.write_boolean(true)?;
buf.write_utf(s)?;
} else {
buf.write_boolean(false)?;
};
Ok(())
}
}
// Option<Component>
impl McBufWritable for Option<Component> {
fn write_into(&self, buf: &mut Vec<u8>) -> Result<(), std::io::Error> {
if let Some(s) = self { if let Some(s) = self {
buf.write_boolean(true)?; buf.write_boolean(true)?;
s.write_into(buf)?; s.write_into(buf)?;
@ -418,3 +405,21 @@ impl McBufWritable for Uuid {
Ok(()) Ok(())
} }
} }
// BlockPos
impl McBufWritable for BlockPos {
fn write_into(&self, buf: &mut Vec<u8>) -> Result<(), std::io::Error> {
buf.write_long(
(((self.x & 0x3FFFFFF) as i64) << 38)
| (((self.z & 0x3FFFFFF) as i64) << 12)
| ((self.y & 0xFFF) as i64),
)
}
}
// Direction
impl McBufWritable for Direction {
fn write_into(&self, buf: &mut Vec<u8>) -> Result<(), std::io::Error> {
buf.write_varint(*self as i32)
}
}

View file

@ -0,0 +1,22 @@
use packet_macros::GamePacket;
use uuid::Uuid;
#[derive(Clone, Debug, GamePacket)]
pub struct ClientboundAddEntityPacket {
#[varint]
pub id: i32,
pub uuid: Uuid,
// TODO: have an entity type struct
#[varint]
pub entity_type: i32,
pub x: f64,
pub y: f64,
pub z: f64,
pub x_rot: i8,
pub y_rot: i8,
// pub y_head_rot: i8,
pub data: i32,
pub x_vel: u16,
pub y_vel: u16,
pub z_vel: u16,
}

View file

@ -26,3 +26,9 @@ pub struct BlockEntity {
type_: i32, type_: i32,
data: azalea_nbt::Tag, data: azalea_nbt::Tag,
} }
pub struct ChunkSection {}
impl ClientboundLevelChunkPacketData {
pub fn read(world_height: u32) {}
}

View file

@ -0,0 +1,419 @@
use crate::{
mc_buf::{Readable, Writable},
packets::{McBufReadable, McBufWritable},
};
use async_trait::async_trait;
use azalea_chat::component::Component;
use azalea_core::{BlockPos, Direction, Slot};
use packet_macros::{GamePacket, McBufReadable, McBufWritable};
use tokio::io::AsyncRead;
use uuid::Uuid;
#[derive(Clone, Debug, GamePacket)]
pub struct ClientboundSetEntityDataPacket {
#[varint]
pub id: i32,
pub metadata: Vec<EntityDataItem>,
}
#[derive(Clone, Debug)]
pub struct EntityDataItem {
// we can't identify what the index is for here because we don't know the
// entity type
pub index: u8,
pub value: EntityDataValue,
}
#[async_trait]
impl McBufReadable for Vec<EntityDataItem> {
async fn read_into<R>(buf: &mut R) -> Result<Self, String>
where
R: AsyncRead + std::marker::Unpin + std::marker::Send,
{
let mut metadata = Vec::new();
loop {
let index = buf.read_byte().await?;
if index == 0xff {
break;
}
let value = EntityDataValue::read_into(buf).await?;
metadata.push(EntityDataItem { index, value });
}
Ok(metadata)
}
}
impl McBufWritable for Vec<EntityDataItem> {
fn write_into(&self, buf: &mut Vec<u8>) -> Result<(), std::io::Error> {
for item in self {
buf.write_byte(item.index)?;
item.value.write_into(buf)?;
}
buf.write_byte(0xff)?;
Ok(())
}
}
#[derive(Clone, Debug)]
pub enum EntityDataValue {
Byte(u8),
// varint
Int(i32),
Float(f32),
String(String),
Component(Component),
OptionalComponent(Option<Component>),
ItemStack(Slot),
Boolean(bool),
Rotations { x: f32, y: f32, z: f32 },
BlockPos(BlockPos),
OptionalBlockPos(Option<BlockPos>),
Direction(Direction),
OptionalUuid(Option<Uuid>),
// 0 for absent (implies air); otherwise, a block state ID as per the global palette
// this is a varint
OptionalBlockState(Option<i32>),
CompoundTag(azalea_nbt::Tag),
Particle(Particle),
VillagerData(VillagerData),
// 0 for absent; 1 + actual value otherwise. Used for entity IDs.
OptionalUnsignedInt(Option<u32>),
Pose(Pose),
}
#[async_trait]
impl McBufReadable for EntityDataValue {
async fn read_into<R>(buf: &mut R) -> Result<Self, String>
where
R: AsyncRead + std::marker::Unpin + std::marker::Send,
{
let type_ = buf.read_varint().await?;
Ok(match type_ {
0 => EntityDataValue::Byte(buf.read_byte().await?),
1 => EntityDataValue::Int(buf.read_varint().await?),
2 => EntityDataValue::Float(buf.read_float().await?),
3 => EntityDataValue::String(buf.read_utf().await?),
4 => EntityDataValue::Component(Component::read_into(buf).await?),
5 => EntityDataValue::OptionalComponent(Option::<Component>::read_into(buf).await?),
6 => EntityDataValue::ItemStack(Slot::read_into(buf).await?),
7 => EntityDataValue::Boolean(buf.read_boolean().await?),
8 => EntityDataValue::Rotations {
x: buf.read_float().await?,
y: buf.read_float().await?,
z: buf.read_float().await?,
},
9 => EntityDataValue::BlockPos(BlockPos::read_into(buf).await?),
10 => EntityDataValue::OptionalBlockPos(Option::<BlockPos>::read_into(buf).await?),
11 => EntityDataValue::Direction(Direction::read_into(buf).await?),
12 => EntityDataValue::OptionalUuid(Option::<Uuid>::read_into(buf).await?),
13 => EntityDataValue::OptionalBlockState({
let val = i32::read_into(buf).await?;
if val == 0 {
None
} else {
Some(val)
}
}),
14 => EntityDataValue::CompoundTag(azalea_nbt::Tag::read_into(buf).await?),
15 => EntityDataValue::Particle(Particle::read_into(buf).await?),
16 => EntityDataValue::VillagerData(VillagerData::read_into(buf).await?),
17 => EntityDataValue::OptionalUnsignedInt({
let val = buf.read_varint().await?;
if val == 0 {
None
} else {
Some((val - 1) as u32)
}
}),
18 => EntityDataValue::Pose(Pose::read_into(buf).await?),
_ => return Err(format!("Unknown entity data type: {}", type_)),
})
}
}
impl McBufWritable for EntityDataValue {
fn write_into(&self, buf: &mut Vec<u8>) -> Result<(), std::io::Error> {
todo!();
}
}
#[derive(Clone, Debug, Copy, McBufReadable, McBufWritable)]
pub enum Pose {
Standing = 0,
FallFlying = 1,
Sleeping = 2,
Swimming = 3,
SpinAttack = 4,
Sneaking = 5,
LongJumping = 6,
Dying = 7,
}
#[derive(Debug, Clone, McBufReadable, McBufWritable)]
pub struct VillagerData {
#[varint]
type_: u32,
#[varint]
profession: u32,
#[varint]
level: u32,
}
#[derive(Debug, Clone, McBufReadable, McBufWritable)]
pub struct Particle {
#[varint]
pub id: i32,
pub data: ParticleData,
}
#[derive(Clone, Debug)]
pub enum ParticleData {
AmbientEntityEffect,
AngryVillager,
Block(BlockParticle),
BlockMarker(BlockParticle),
Bubble,
Cloud,
Crit,
DamageIndicator,
DragonBreath,
DrippingLava,
FallingLava,
LandingLava,
DrippingWater,
FallingWater,
Dust(DustParticle),
DustColorTransition(DustColorTransitionParticle),
Effect,
ElderGuardian,
EnchantedHit,
Enchant,
EndRod,
EntityEffect,
ExplosionEmitter,
Explosion,
FallingDust(BlockParticle),
Firework,
Fishing,
Flame,
SoulFireFlame,
Soul,
Flash,
HappyVillager,
Composter,
Heart,
InstantEffect,
Item(ItemParticle),
Vibration(VibrationParticle),
ItemSlime,
ItemSnowball,
LargeSmoke,
Lava,
Mycelium,
Note,
Poof,
Portal,
Rain,
Smoke,
Sneeze,
Spit,
SquidInk,
SweepAttack,
TotemOfUndying,
Underwater,
Splash,
Witch,
BubblePop,
CurrentDown,
BubbleColumnUp,
Nautilus,
Dolphin,
CampfireCozySmoke,
CampfireSignalSmoke,
DrippingHoney,
FallingHoney,
LandingHoney,
FallingNectar,
FallingSporeBlossom,
Ash,
CrimsonSpore,
WarpedSpore,
SporeBlossomAir,
DrippingObsidianTear,
FallingObsidianTear,
LandingObsidianTear,
ReversePortal,
WhiteAsh,
SmallFlame,
Snowflake,
DrippingDripstoneLava,
FallingDripstoneLava,
DrippingDripstoneWater,
FallingDripstoneWater,
GlowSquidInk,
Glow,
WaxOn,
WaxOff,
ElectricSpark,
Scrape,
}
#[derive(Debug, Clone, McBufReadable, McBufWritable)]
pub struct BlockParticle {
#[varint]
pub block_state: i32,
}
#[derive(Debug, Clone, McBufReadable, McBufWritable)]
pub struct DustParticle {
/// Red value, 0-1
pub red: f32,
/// Green value, 0-1
pub green: f32,
/// Blue value, 0-1
pub blue: f32,
/// The scale, will be clamped between 0.01 and 4.
pub scale: f32,
}
#[derive(Debug, Clone, McBufReadable, McBufWritable)]
pub struct DustColorTransitionParticle {
/// Red value, 0-1
pub from_red: f32,
/// Green value, 0-1
pub from_green: f32,
/// Blue value, 0-1
pub from_blue: f32,
/// The scale, will be clamped between 0.01 and 4.
pub scale: f32,
/// Red value, 0-1
pub to_red: f32,
/// Green value, 0-1
pub to_green: f32,
/// Blue value, 0-1
pub to_blue: f32,
}
#[derive(Debug, Clone, McBufReadable, McBufWritable)]
pub struct ItemParticle {
pub item: Slot,
}
#[derive(Debug, Clone, McBufReadable, McBufWritable)]
pub struct VibrationParticle {
pub origin: BlockPos,
pub position_type: String,
pub block_position: BlockPos,
#[varint]
pub entity_id: u32,
#[varint]
pub ticks: u32,
}
#[async_trait]
impl McBufReadable for ParticleData {
async fn read_into<R>(buf: &mut R) -> Result<Self, String>
where
R: AsyncRead + std::marker::Unpin + std::marker::Send,
{
let id = buf.read_varint().await?;
Ok(match id {
0 => ParticleData::AmbientEntityEffect,
1 => ParticleData::AngryVillager,
2 => ParticleData::Block(BlockParticle::read_into(buf).await?),
3 => ParticleData::BlockMarker(BlockParticle::read_into(buf).await?),
4 => ParticleData::Bubble,
5 => ParticleData::Cloud,
6 => ParticleData::Crit,
7 => ParticleData::DamageIndicator,
8 => ParticleData::DragonBreath,
9 => ParticleData::DrippingLava,
10 => ParticleData::FallingLava,
11 => ParticleData::LandingLava,
12 => ParticleData::DrippingWater,
13 => ParticleData::FallingWater,
14 => ParticleData::Dust(DustParticle::read_into(buf).await?),
15 => ParticleData::DustColorTransition(
DustColorTransitionParticle::read_into(buf).await?,
),
16 => ParticleData::Effect,
17 => ParticleData::ElderGuardian,
18 => ParticleData::EnchantedHit,
19 => ParticleData::Enchant,
20 => ParticleData::EndRod,
21 => ParticleData::EntityEffect,
22 => ParticleData::ExplosionEmitter,
23 => ParticleData::Explosion,
24 => ParticleData::FallingDust(BlockParticle::read_into(buf).await?),
25 => ParticleData::Firework,
26 => ParticleData::Fishing,
27 => ParticleData::Flame,
28 => ParticleData::SoulFireFlame,
29 => ParticleData::Soul,
30 => ParticleData::Flash,
31 => ParticleData::HappyVillager,
32 => ParticleData::Composter,
33 => ParticleData::Heart,
34 => ParticleData::InstantEffect,
35 => ParticleData::Item(ItemParticle::read_into(buf).await?),
36 => ParticleData::Vibration(VibrationParticle::read_into(buf).await?),
37 => ParticleData::ItemSlime,
38 => ParticleData::ItemSnowball,
39 => ParticleData::LargeSmoke,
40 => ParticleData::Lava,
41 => ParticleData::Mycelium,
42 => ParticleData::Note,
43 => ParticleData::Poof,
44 => ParticleData::Portal,
45 => ParticleData::Rain,
46 => ParticleData::Smoke,
47 => ParticleData::Sneeze,
48 => ParticleData::Spit,
49 => ParticleData::SquidInk,
50 => ParticleData::SweepAttack,
51 => ParticleData::TotemOfUndying,
52 => ParticleData::Underwater,
53 => ParticleData::Splash,
54 => ParticleData::Witch,
55 => ParticleData::BubblePop,
56 => ParticleData::CurrentDown,
57 => ParticleData::BubbleColumnUp,
58 => ParticleData::Nautilus,
59 => ParticleData::Dolphin,
60 => ParticleData::CampfireCozySmoke,
61 => ParticleData::CampfireSignalSmoke,
62 => ParticleData::DrippingHoney,
63 => ParticleData::FallingHoney,
64 => ParticleData::LandingHoney,
65 => ParticleData::FallingNectar,
66 => ParticleData::FallingSporeBlossom,
67 => ParticleData::Ash,
68 => ParticleData::CrimsonSpore,
69 => ParticleData::WarpedSpore,
70 => ParticleData::SporeBlossomAir,
71 => ParticleData::DrippingObsidianTear,
72 => ParticleData::FallingObsidianTear,
73 => ParticleData::LandingObsidianTear,
74 => ParticleData::ReversePortal,
75 => ParticleData::WhiteAsh,
76 => ParticleData::SmallFlame,
77 => ParticleData::Snowflake,
78 => ParticleData::DrippingDripstoneLava,
79 => ParticleData::FallingDripstoneLava,
80 => ParticleData::DrippingDripstoneWater,
81 => ParticleData::FallingDripstoneWater,
82 => ParticleData::GlowSquidInk,
83 => ParticleData::Glow,
84 => ParticleData::WaxOn,
85 => ParticleData::WaxOff,
86 => ParticleData::ElectricSpark,
87 => ParticleData::Scrape,
_ => return Err(format!("Unknown particle id: {}", id)),
})
}
}
impl McBufWritable for ParticleData {
fn write_into(&self, buf: &mut Vec<u8>) -> Result<(), std::io::Error> {
todo!()
}
}

View file

@ -1,3 +1,4 @@
pub mod clientbound_add_entity_packet;
pub mod clientbound_add_mob_packet; pub mod clientbound_add_mob_packet;
pub mod clientbound_change_difficulty_packet; pub mod clientbound_change_difficulty_packet;
pub mod clientbound_custom_payload_packet; pub mod clientbound_custom_payload_packet;
@ -13,6 +14,7 @@ pub mod clientbound_player_position_packet;
pub mod clientbound_recipe_packet; pub mod clientbound_recipe_packet;
pub mod clientbound_set_carried_item_packet; pub mod clientbound_set_carried_item_packet;
pub mod clientbound_set_chunk_cache_center; pub mod clientbound_set_chunk_cache_center;
pub mod clientbound_set_entity_data_packet;
pub mod clientbound_update_recipes_packet; pub mod clientbound_update_recipes_packet;
pub mod clientbound_update_tags_packet; pub mod clientbound_update_tags_packet;
pub mod clientbound_update_view_distance_packet; pub mod clientbound_update_view_distance_packet;
@ -26,6 +28,7 @@ declare_state_packets!(
0x0a: serverbound_custom_payload_packet::ServerboundCustomPayloadPacket, 0x0a: serverbound_custom_payload_packet::ServerboundCustomPayloadPacket,
}, },
Clientbound => { Clientbound => {
0x00: clientbound_add_entity_packet::ClientboundAddEntityPacket,
0x02: clientbound_add_mob_packet::ClientboundAddMobPacket, 0x02: clientbound_add_mob_packet::ClientboundAddMobPacket,
0x0e: clientbound_change_difficulty_packet::ClientboundChangeDifficultyPacket, 0x0e: clientbound_change_difficulty_packet::ClientboundChangeDifficultyPacket,
0x12: clientbound_declare_commands_packet::ClientboundDeclareCommandsPacket, 0x12: clientbound_declare_commands_packet::ClientboundDeclareCommandsPacket,
@ -42,6 +45,7 @@ declare_state_packets!(
0x48: clientbound_set_carried_item_packet::ClientboundSetCarriedItemPacket, 0x48: clientbound_set_carried_item_packet::ClientboundSetCarriedItemPacket,
0x49: clientbound_set_chunk_cache_center::ClientboundSetChunkCacheCenterPacket, 0x49: clientbound_set_chunk_cache_center::ClientboundSetChunkCacheCenterPacket,
0x4a: clientbound_update_view_distance_packet::ClientboundUpdateViewDistancePacket, 0x4a: clientbound_update_view_distance_packet::ClientboundUpdateViewDistancePacket,
0x4d: clientbound_set_entity_data_packet::ClientboundSetEntityDataPacket,
0x66: clientbound_update_recipes_packet::ClientboundUpdateRecipesPacket, 0x66: clientbound_update_recipes_packet::ClientboundUpdateRecipesPacket,
0x67: clientbound_update_tags_packet::ClientboundUpdateTagsPacket 0x67: clientbound_update_tags_packet::ClientboundUpdateTagsPacket
} }

View file

@ -1,5 +1,4 @@
use packet_macros::StatusPacket; use packet_macros::StatusPacket;
use std::hash::Hash;
#[derive(Clone, Debug, StatusPacket)] #[derive(Clone, Debug, StatusPacket)]
pub struct ServerboundStatusRequestPacket {} pub struct ServerboundStatusRequestPacket {}

View file

@ -5,7 +5,7 @@ async fn main() {
println!("Hello, world!"); println!("Hello, world!");
// let address = "95.111.249.143:10000"; // let address = "95.111.249.143:10000";
let address = "172.23.192.1:51015"; let address = "172.23.192.1:58024";
// let response = azalea_client::ping::ping_server(&address.try_into().unwrap()) // let response = azalea_client::ping::ping_server(&address.try_into().unwrap())
// .await // .await
// .unwrap(); // .unwrap();