mirror of
https://github.com/mat-1/azalea.git
synced 2025-08-02 23:44:38 +00:00
player info packet
This commit is contained in:
parent
60d1fa50c3
commit
9b50886c30
9 changed files with 217 additions and 6 deletions
|
@ -127,6 +127,9 @@ pub async fn join_server(address: &ServerAddress) -> Result<(), String> {
|
||||||
// TODO: reply with teleport confirm
|
// TODO: reply with teleport confirm
|
||||||
println!("Got player position packet {:?}", p);
|
println!("Got player position packet {:?}", p);
|
||||||
}
|
}
|
||||||
|
GamePacket::ClientboundPlayerInfoPacket(p) => {
|
||||||
|
println!("Got player info packet {:?}", p);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
panic!("Error: {:?}", e);
|
panic!("Error: {:?}", e);
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
# Azalea Protocol
|
# Azalea Protocol
|
||||||
|
|
||||||
Sent and receive Minecraft packets. You should probably use `azalea` or `azalea-client` instead.
|
Sent and receive Minecraft packets. You should probably use `azalea` or `azalea-client` instead.
|
||||||
|
|
||||||
|
The goal is to **only** support the latest Minecraft version in order to ease development.
|
||||||
|
|
||||||
|
This is not yet complete, search for `TODO` in the code for things that need to be done.
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
use async_trait::async_trait;
|
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, Slot,
|
difficulty::Difficulty, game_type::GameType, resource_location::ResourceLocation,
|
||||||
SlotData,
|
serializable_uuid::SerializableUuid, Slot, SlotData,
|
||||||
};
|
};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use tokio::io::{AsyncRead, AsyncReadExt};
|
use tokio::io::{AsyncRead, AsyncReadExt};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
use super::{UnsizedByteArray, MAX_STRING_LENGTH};
|
use super::{UnsizedByteArray, MAX_STRING_LENGTH};
|
||||||
|
|
||||||
|
@ -29,6 +30,7 @@ pub trait Readable {
|
||||||
async fn read_short(&mut self) -> Result<i16, String>;
|
async fn read_short(&mut self) -> Result<i16, String>;
|
||||||
async fn read_float(&mut self) -> Result<f32, String>;
|
async fn read_float(&mut self) -> Result<f32, String>;
|
||||||
async fn read_double(&mut self) -> Result<f64, String>;
|
async fn read_double(&mut self) -> Result<f64, String>;
|
||||||
|
async fn read_uuid(&mut self) -> Result<Uuid, String>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
|
@ -207,6 +209,15 @@ where
|
||||||
Err(_) => Err("Error reading double".to_string()),
|
Err(_) => Err("Error reading double".to_string()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn read_uuid(&mut self) -> Result<Uuid, String> {
|
||||||
|
Ok(Uuid::from_int_array([
|
||||||
|
self.read_int().await? as u32,
|
||||||
|
self.read_int().await? as u32,
|
||||||
|
self.read_int().await? as u32,
|
||||||
|
self.read_int().await? as u32,
|
||||||
|
]))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
|
@ -439,6 +450,37 @@ impl McBufReadable for Option<GameType> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Option<String>
|
||||||
|
#[async_trait]
|
||||||
|
impl McBufReadable for Option<String> {
|
||||||
|
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(buf.read_utf().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 {
|
||||||
|
None
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// azalea_nbt::Tag
|
// azalea_nbt::Tag
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl McBufReadable for azalea_nbt::Tag {
|
impl McBufReadable for azalea_nbt::Tag {
|
||||||
|
@ -493,3 +535,14 @@ impl McBufReadable for Slot {
|
||||||
Ok(Slot::Present(SlotData { id, count, nbt }))
|
Ok(Slot::Present(SlotData { id, count, nbt }))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Uuid
|
||||||
|
#[async_trait]
|
||||||
|
impl McBufReadable for Uuid {
|
||||||
|
async fn read_into<R>(buf: &mut R) -> Result<Self, String>
|
||||||
|
where
|
||||||
|
R: AsyncRead + std::marker::Unpin + std::marker::Send,
|
||||||
|
{
|
||||||
|
buf.read_uuid().await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2,10 +2,12 @@ use super::{UnsizedByteArray, MAX_STRING_LENGTH};
|
||||||
use async_trait::async_trait;
|
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, Slot,
|
difficulty::Difficulty, game_type::GameType, resource_location::ResourceLocation,
|
||||||
|
serializable_uuid::SerializableUuid, Slot,
|
||||||
};
|
};
|
||||||
use byteorder::{BigEndian, WriteBytesExt};
|
use byteorder::{BigEndian, WriteBytesExt};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
pub trait Writable {
|
pub trait Writable {
|
||||||
|
@ -43,6 +45,7 @@ pub trait Writable {
|
||||||
) -> Result<(), std::io::Error>;
|
) -> Result<(), std::io::Error>;
|
||||||
fn write_float(&mut self, n: f32) -> Result<(), std::io::Error>;
|
fn write_float(&mut self, n: f32) -> Result<(), std::io::Error>;
|
||||||
fn write_double(&mut self, n: f64) -> Result<(), std::io::Error>;
|
fn write_double(&mut self, n: f64) -> Result<(), std::io::Error>;
|
||||||
|
fn write_uuid(&mut self, uuid: &Uuid) -> Result<(), std::io::Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
|
@ -163,6 +166,15 @@ impl Writable for Vec<u8> {
|
||||||
) -> Result<(), std::io::Error> {
|
) -> Result<(), std::io::Error> {
|
||||||
self.write_utf(&location.to_string())
|
self.write_utf(&location.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn write_uuid(&mut self, uuid: &Uuid) -> Result<(), std::io::Error> {
|
||||||
|
let [a, b, c, d] = uuid.to_int_array();
|
||||||
|
a.write_into(self)?;
|
||||||
|
b.write_into(self)?;
|
||||||
|
c.write_into(self)?;
|
||||||
|
d.write_into(self)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait McBufWritable
|
pub trait McBufWritable
|
||||||
|
@ -317,6 +329,32 @@ impl McBufWritable for Option<GameType> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Option<String>
|
||||||
|
impl McBufWritable for Option<String> {
|
||||||
|
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 {
|
||||||
|
buf.write_boolean(true)?;
|
||||||
|
s.write_into(buf)?;
|
||||||
|
} else {
|
||||||
|
buf.write_boolean(false)?;
|
||||||
|
};
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// azalea_nbt::Tag
|
// azalea_nbt::Tag
|
||||||
impl McBufWritable for azalea_nbt::Tag {
|
impl McBufWritable for azalea_nbt::Tag {
|
||||||
fn write_into(&self, buf: &mut Vec<u8>) -> Result<(), std::io::Error> {
|
fn write_into(&self, buf: &mut Vec<u8>) -> Result<(), std::io::Error> {
|
||||||
|
@ -365,3 +403,12 @@ impl McBufWritable for Slot {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Slot
|
||||||
|
impl McBufWritable for Uuid {
|
||||||
|
fn write_into(&self, buf: &mut Vec<u8>) -> Result<(), std::io::Error> {
|
||||||
|
buf.write_uuid(self)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use super::GamePacket;
|
use super::GamePacket;
|
||||||
use crate::mc_buf::{McBufReadable, McBufWritable, Readable};
|
use crate::mc_buf::{McBufReadable, McBufWritable, Readable, Writable};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use azalea_core::resource_location::ResourceLocation;
|
use azalea_core::resource_location::ResourceLocation;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
@ -115,7 +115,7 @@ impl McBufReadable for BrigadierString {
|
||||||
}
|
}
|
||||||
impl McBufWritable for BrigadierString {
|
impl McBufWritable for BrigadierString {
|
||||||
fn write_into(&self, buf: &mut Vec<u8>) -> Result<(), std::io::Error> {
|
fn write_into(&self, buf: &mut Vec<u8>) -> Result<(), std::io::Error> {
|
||||||
buf.write_i8(*self as i8);
|
buf.write_byte(*self as u8)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
use azalea_core::{game_type::GameType, resource_location::ResourceLocation};
|
|
||||||
use packet_macros::GamePacket;
|
use packet_macros::GamePacket;
|
||||||
|
|
||||||
// we can't identify the status in azalea-protocol since they vary depending on the entity
|
// we can't identify the status in azalea-protocol since they vary depending on the entity
|
||||||
|
|
|
@ -0,0 +1,101 @@
|
||||||
|
// i don't know the actual name of this packet, i couldn't find it in the source code
|
||||||
|
|
||||||
|
use crate::mc_buf::{McBufReadable, McBufWritable, Readable, Writable};
|
||||||
|
use async_trait::async_trait;
|
||||||
|
use azalea_chat::component::Component;
|
||||||
|
use packet_macros::{GamePacket, McBufReadable, McBufWritable};
|
||||||
|
use tokio::io::AsyncRead;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, GamePacket)]
|
||||||
|
pub struct ClientboundPlayerInfoPacket {
|
||||||
|
pub action: Action,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum Action {
|
||||||
|
AddPlayer(Vec<AddPlayer>),
|
||||||
|
UpdateGameMode(Vec<UpdateGameMode>),
|
||||||
|
UpdateLatency(Vec<UpdateLatency>),
|
||||||
|
UpdateDisplayName(Vec<UpdateDisplayName>),
|
||||||
|
RemovePlayer(Vec<RemovePlayer>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, McBufReadable, McBufWritable)]
|
||||||
|
pub struct PlayerProperty {
|
||||||
|
name: String,
|
||||||
|
value: String,
|
||||||
|
signature: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, McBufReadable, McBufWritable)]
|
||||||
|
pub struct AddPlayer {
|
||||||
|
uuid: Uuid,
|
||||||
|
properties: Vec<PlayerProperty>,
|
||||||
|
#[varint]
|
||||||
|
gamemode: u32,
|
||||||
|
#[varint]
|
||||||
|
ping: i32,
|
||||||
|
display_name: Option<Component>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, McBufReadable, McBufWritable)]
|
||||||
|
pub struct UpdateGameMode {
|
||||||
|
uuid: Uuid,
|
||||||
|
#[varint]
|
||||||
|
gamemode: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, McBufReadable, McBufWritable)]
|
||||||
|
pub struct UpdateLatency {
|
||||||
|
uuid: Uuid,
|
||||||
|
#[varint]
|
||||||
|
ping: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, McBufReadable, McBufWritable)]
|
||||||
|
pub struct UpdateDisplayName {
|
||||||
|
uuid: Uuid,
|
||||||
|
display_name: Option<Component>,
|
||||||
|
}
|
||||||
|
#[derive(Clone, Debug, McBufReadable, McBufWritable)]
|
||||||
|
pub struct RemovePlayer {
|
||||||
|
uuid: Uuid,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl McBufReadable for Action {
|
||||||
|
async fn read_into<R>(buf: &mut R) -> Result<Self, String>
|
||||||
|
where
|
||||||
|
R: AsyncRead + std::marker::Unpin + std::marker::Send,
|
||||||
|
{
|
||||||
|
let id = buf.read_byte().await?;
|
||||||
|
Ok(match id {
|
||||||
|
0 => Action::AddPlayer(Vec::<AddPlayer>::read_into(buf).await?),
|
||||||
|
1 => Action::UpdateGameMode(Vec::<UpdateGameMode>::read_into(buf).await?),
|
||||||
|
2 => Action::UpdateLatency(Vec::<UpdateLatency>::read_into(buf).await?),
|
||||||
|
3 => Action::UpdateDisplayName(Vec::<UpdateDisplayName>::read_into(buf).await?),
|
||||||
|
4 => Action::RemovePlayer(Vec::<RemovePlayer>::read_into(buf).await?),
|
||||||
|
_ => panic!("Unknown player info action id: {}", id),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl McBufWritable for Action {
|
||||||
|
fn write_into(&self, buf: &mut Vec<u8>) -> Result<(), std::io::Error> {
|
||||||
|
buf.write_byte(match self {
|
||||||
|
Action::AddPlayer(_) => 0,
|
||||||
|
Action::UpdateGameMode(_) => 1,
|
||||||
|
Action::UpdateLatency(_) => 2,
|
||||||
|
Action::UpdateDisplayName(_) => 3,
|
||||||
|
Action::RemovePlayer(_) => 4,
|
||||||
|
})?;
|
||||||
|
match self {
|
||||||
|
Action::AddPlayer(players) => players.write_into(buf)?,
|
||||||
|
Action::UpdateGameMode(players) => players.write_into(buf)?,
|
||||||
|
Action::UpdateLatency(players) => players.write_into(buf)?,
|
||||||
|
Action::UpdateDisplayName(players) => players.write_into(buf)?,
|
||||||
|
Action::RemovePlayer(players) => players.write_into(buf)?,
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,6 +5,7 @@ pub mod clientbound_disconnect_packet;
|
||||||
pub mod clientbound_entity_event_packet;
|
pub mod clientbound_entity_event_packet;
|
||||||
pub mod clientbound_login_packet;
|
pub mod clientbound_login_packet;
|
||||||
pub mod clientbound_player_abilities_packet;
|
pub mod clientbound_player_abilities_packet;
|
||||||
|
pub mod clientbound_player_info_packet;
|
||||||
pub mod clientbound_player_position_packet;
|
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;
|
||||||
|
@ -25,6 +26,7 @@ declare_state_packets!(
|
||||||
0x18: clientbound_custom_payload_packet::ClientboundCustomPayloadPacket,
|
0x18: clientbound_custom_payload_packet::ClientboundCustomPayloadPacket,
|
||||||
0x26: clientbound_login_packet::ClientboundLoginPacket,
|
0x26: clientbound_login_packet::ClientboundLoginPacket,
|
||||||
0x32: clientbound_player_abilities_packet::ClientboundPlayerAbilitiesPacket,
|
0x32: clientbound_player_abilities_packet::ClientboundPlayerAbilitiesPacket,
|
||||||
|
0x36: clientbound_player_info_packet::ClientboundPlayerInfoPacket,
|
||||||
0x38: clientbound_player_position_packet::ClientboundPlayerPositionPacket,
|
0x38: clientbound_player_position_packet::ClientboundPlayerPositionPacket,
|
||||||
0x39: clientbound_recipe_packet::ClientboundRecipePacket,
|
0x39: clientbound_recipe_packet::ClientboundRecipePacket,
|
||||||
0x48: clientbound_set_carried_item_packet::ClientboundSetCarriedItemPacket,
|
0x48: clientbound_set_carried_item_packet::ClientboundSetCarriedItemPacket,
|
||||||
|
|
|
@ -9,6 +9,7 @@ pub struct ClientboundGameProfilePacket {
|
||||||
pub game_profile: GameProfile,
|
pub game_profile: GameProfile,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: add derives to GameProfile and have an impl McBufReadable/Writable for GameProfile
|
||||||
impl ClientboundGameProfilePacket {
|
impl ClientboundGameProfilePacket {
|
||||||
pub fn get(self) -> LoginPacket {
|
pub fn get(self) -> LoginPacket {
|
||||||
LoginPacket::ClientboundGameProfilePacket(self)
|
LoginPacket::ClientboundGameProfilePacket(self)
|
||||||
|
@ -25,6 +26,7 @@ impl ClientboundGameProfilePacket {
|
||||||
pub async fn read<T: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send>(
|
pub async fn read<T: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send>(
|
||||||
buf: &mut T,
|
buf: &mut T,
|
||||||
) -> Result<LoginPacket, String> {
|
) -> Result<LoginPacket, String> {
|
||||||
|
// TODO: we have a thing to read from the uuid now
|
||||||
let uuid = Uuid::from_int_array([
|
let uuid = Uuid::from_int_array([
|
||||||
buf.read_int().await? as u32,
|
buf.read_int().await? as u32,
|
||||||
buf.read_int().await? as u32,
|
buf.read_int().await? as u32,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue