mirror of
https://github.com/italicsjenga/valence.git
synced 2024-10-17 07:21:30 +11:00
Valence protocol redesign (#177)
- Fix performance issues related to writing individual bytes instead of using `Write::write_all`. - Make manual implementations of `Encode` and `Decode` easier: - Remove `encoded_len` method from `Encode` - Split `Packet` trait into `EncodePacket` and `DecodePacket`. - Simplify derive macros.
This commit is contained in:
parent
1f5ec6f94f
commit
c26bbe7ec2
|
@ -6,8 +6,7 @@ description = "A simple Minecraft proxy for inspecting packets."
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
valence_protocol = { path = "../valence_protocol", version = "0.1.0", features = ["compression"] }
|
valence_protocol = { path = "../valence_protocol", version = "0.1.0", features = ["compression"] }
|
||||||
clap = { version = "3.2.8", features = ["derive"] }
|
clap = { version = "4.0.30", features = ["derive"] }
|
||||||
tokio = { version = "1", features = ["full"] }
|
tokio = { version = "1", features = ["full"] }
|
||||||
anyhow = "1"
|
anyhow = "1"
|
||||||
chrono = "0.4.19"
|
|
||||||
regex = "1.6.0"
|
regex = "1.6.0"
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
use std::fmt::Write;
|
||||||
use std::io::ErrorKind;
|
use std::io::ErrorKind;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::{fmt, io};
|
use std::{fmt, io};
|
||||||
|
|
||||||
use anyhow::bail;
|
use anyhow::bail;
|
||||||
use chrono::{DateTime, Utc};
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||||
|
@ -21,7 +21,7 @@ use valence_protocol::packets::s2c::login::{LoginSuccess, S2cLoginPacket};
|
||||||
use valence_protocol::packets::s2c::play::S2cPlayPacket;
|
use valence_protocol::packets::s2c::play::S2cPlayPacket;
|
||||||
use valence_protocol::packets::s2c::status::{PingResponse, StatusResponse};
|
use valence_protocol::packets::s2c::status::{PingResponse, StatusResponse};
|
||||||
use valence_protocol::types::HandshakeNextState;
|
use valence_protocol::types::HandshakeNextState;
|
||||||
use valence_protocol::{Decode, Encode, Packet, PacketDecoder, PacketEncoder};
|
use valence_protocol::{DecodePacket, EncodePacket, PacketDecoder, PacketEncoder};
|
||||||
|
|
||||||
#[derive(Parser, Clone, Debug)]
|
#[derive(Parser, Clone, Debug)]
|
||||||
#[clap(author, version, about)]
|
#[clap(author, version, about)]
|
||||||
|
@ -48,9 +48,6 @@ struct Cli {
|
||||||
/// there is no limit.
|
/// there is no limit.
|
||||||
#[clap(short, long)]
|
#[clap(short, long)]
|
||||||
max_connections: Option<usize>,
|
max_connections: Option<usize>,
|
||||||
/// Print a timestamp before each packet.
|
|
||||||
#[clap(short, long)]
|
|
||||||
timestamp: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct State {
|
struct State {
|
||||||
|
@ -59,12 +56,13 @@ struct State {
|
||||||
dec: PacketDecoder,
|
dec: PacketDecoder,
|
||||||
read: OwnedReadHalf,
|
read: OwnedReadHalf,
|
||||||
write: OwnedWriteHalf,
|
write: OwnedWriteHalf,
|
||||||
|
buf: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl State {
|
impl State {
|
||||||
pub async fn rw_packet<'a, P>(&'a mut self) -> anyhow::Result<P>
|
pub async fn rw_packet<'a, P>(&'a mut self) -> anyhow::Result<P>
|
||||||
where
|
where
|
||||||
P: Decode<'a> + Encode + Packet + fmt::Debug,
|
P: DecodePacket<'a> + EncodePacket + fmt::Debug,
|
||||||
{
|
{
|
||||||
while !self.dec.has_next_packet()? {
|
while !self.dec.has_next_packet()? {
|
||||||
self.dec.reserve(4096);
|
self.dec.reserve(4096);
|
||||||
|
@ -84,24 +82,24 @@ impl State {
|
||||||
let bytes = self.enc.take();
|
let bytes = self.enc.take();
|
||||||
self.write.write_all(&bytes).await?;
|
self.write.write_all(&bytes).await?;
|
||||||
|
|
||||||
|
self.buf.clear();
|
||||||
|
write!(&mut self.buf, "{pkt:?}")?;
|
||||||
|
|
||||||
|
let packet_name = self.buf.split_ascii_whitespace().next().unwrap();
|
||||||
|
|
||||||
if let Some(r) = &self.cli.include_regex {
|
if let Some(r) = &self.cli.include_regex {
|
||||||
if !r.is_match(pkt.packet_name()) {
|
if !r.is_match(packet_name) {
|
||||||
return Ok(pkt);
|
return Ok(pkt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(r) = &self.cli.exclude_regex {
|
if let Some(r) = &self.cli.exclude_regex {
|
||||||
if r.is_match(pkt.packet_name()) {
|
if r.is_match(packet_name) {
|
||||||
return Ok(pkt);
|
return Ok(pkt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.cli.timestamp {
|
println!("{}", self.buf);
|
||||||
let now: DateTime<Utc> = Utc::now();
|
|
||||||
println!("{now} {pkt:#?}");
|
|
||||||
} else {
|
|
||||||
println!("{pkt:#?}");
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(pkt)
|
Ok(pkt)
|
||||||
}
|
}
|
||||||
|
@ -156,6 +154,7 @@ async fn handle_connection(client: TcpStream, cli: Arc<Cli>) -> anyhow::Result<(
|
||||||
dec: PacketDecoder::new(),
|
dec: PacketDecoder::new(),
|
||||||
read: server_read,
|
read: server_read,
|
||||||
write: client_write,
|
write: client_write,
|
||||||
|
buf: String::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut c2s = State {
|
let mut c2s = State {
|
||||||
|
@ -164,6 +163,7 @@ async fn handle_connection(client: TcpStream, cli: Arc<Cli>) -> anyhow::Result<(
|
||||||
dec: PacketDecoder::new(),
|
dec: PacketDecoder::new(),
|
||||||
read: client_read,
|
read: client_read,
|
||||||
write: server_write,
|
write: server_write,
|
||||||
|
buf: String::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let handshake: Handshake = c2s.rw_packet().await?;
|
let handshake: Handshake = c2s.rw_packet().await?;
|
||||||
|
|
|
@ -835,7 +835,7 @@ impl<C: Config> LoadedChunk<C> {
|
||||||
let mut compression_scratch = vec![];
|
let mut compression_scratch = vec![];
|
||||||
|
|
||||||
let mut writer =
|
let mut writer =
|
||||||
PacketWriter::new(&mut *lck, compression_threshold, &mut compression_scratch);
|
PacketWriter::new(&mut lck, compression_threshold, &mut compression_scratch);
|
||||||
|
|
||||||
writer
|
writer
|
||||||
.write_packet(&ChunkDataAndUpdateLightEncode {
|
.write_packet(&ChunkDataAndUpdateLightEncode {
|
||||||
|
|
|
@ -27,7 +27,7 @@ use valence_protocol::types::{
|
||||||
SyncPlayerPosLookFlags,
|
SyncPlayerPosLookFlags,
|
||||||
};
|
};
|
||||||
use valence_protocol::{
|
use valence_protocol::{
|
||||||
BlockPos, Encode, Ident, ItemStack, Packet, RawBytes, Text, Username, VarInt,
|
BlockPos, EncodePacket, Ident, ItemStack, RawBytes, Text, Username, VarInt,
|
||||||
};
|
};
|
||||||
use vek::Vec3;
|
use vek::Vec3;
|
||||||
|
|
||||||
|
@ -344,7 +344,7 @@ impl<C: Config> Client<C> {
|
||||||
/// effect if the client is already disconnected.
|
/// effect if the client is already disconnected.
|
||||||
pub fn queue_packet<P>(&mut self, pkt: &P)
|
pub fn queue_packet<P>(&mut self, pkt: &P)
|
||||||
where
|
where
|
||||||
P: Encode + Packet + fmt::Debug + ?Sized,
|
P: EncodePacket + fmt::Debug + ?Sized,
|
||||||
{
|
{
|
||||||
if let Some(send) = &mut self.send {
|
if let Some(send) = &mut self.send {
|
||||||
if let Err(e) = send.append_packet(pkt) {
|
if let Err(e) = send.append_packet(pkt) {
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
|
||||||
use valence_protocol::{write_packet, write_packet_compressed, Encode, Packet};
|
use valence_protocol::{encode_packet, encode_packet_compressed, EncodePacket};
|
||||||
|
|
||||||
pub trait WritePacket {
|
pub trait WritePacket {
|
||||||
fn write_packet<P>(&mut self, packet: &P) -> anyhow::Result<()>
|
fn write_packet<P>(&mut self, packet: &P) -> anyhow::Result<()>
|
||||||
where
|
where
|
||||||
P: Encode + Packet + ?Sized;
|
P: EncodePacket + ?Sized;
|
||||||
|
|
||||||
fn write_bytes(&mut self, bytes: &[u8]) -> anyhow::Result<()>;
|
fn write_bytes(&mut self, bytes: &[u8]) -> anyhow::Result<()>;
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ pub trait WritePacket {
|
||||||
impl<W: WritePacket> WritePacket for &mut W {
|
impl<W: WritePacket> WritePacket for &mut W {
|
||||||
fn write_packet<P>(&mut self, packet: &P) -> anyhow::Result<()>
|
fn write_packet<P>(&mut self, packet: &P) -> anyhow::Result<()>
|
||||||
where
|
where
|
||||||
P: Encode + Packet + ?Sized,
|
P: EncodePacket + ?Sized,
|
||||||
{
|
{
|
||||||
(*self).write_packet(packet)
|
(*self).write_packet(packet)
|
||||||
}
|
}
|
||||||
|
@ -23,35 +23,35 @@ impl<W: WritePacket> WritePacket for &mut W {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PacketWriter<'a, W> {
|
pub struct PacketWriter<'a> {
|
||||||
writer: W,
|
buf: &'a mut Vec<u8>,
|
||||||
threshold: Option<u32>,
|
threshold: Option<u32>,
|
||||||
scratch: &'a mut Vec<u8>,
|
scratch: &'a mut Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, W: Write> PacketWriter<'a, W> {
|
impl<'a> PacketWriter<'a> {
|
||||||
pub fn new(writer: W, threshold: Option<u32>, scratch: &'a mut Vec<u8>) -> PacketWriter<W> {
|
pub fn new(buf: &'a mut Vec<u8>, threshold: Option<u32>, scratch: &'a mut Vec<u8>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
writer,
|
buf,
|
||||||
threshold,
|
threshold,
|
||||||
scratch,
|
scratch,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<W: Write> WritePacket for PacketWriter<'_, W> {
|
impl WritePacket for PacketWriter<'_> {
|
||||||
fn write_packet<P>(&mut self, packet: &P) -> anyhow::Result<()>
|
fn write_packet<P>(&mut self, pkt: &P) -> anyhow::Result<()>
|
||||||
where
|
where
|
||||||
P: Encode + Packet + ?Sized,
|
P: EncodePacket + ?Sized,
|
||||||
{
|
{
|
||||||
if let Some(threshold) = self.threshold {
|
if let Some(threshold) = self.threshold {
|
||||||
write_packet_compressed(&mut self.writer, threshold, self.scratch, packet)
|
encode_packet_compressed(self.buf, pkt, threshold, self.scratch)
|
||||||
} else {
|
} else {
|
||||||
write_packet(&mut self.writer, packet)
|
encode_packet(self.buf, pkt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_bytes(&mut self, bytes: &[u8]) -> anyhow::Result<()> {
|
fn write_bytes(&mut self, bytes: &[u8]) -> anyhow::Result<()> {
|
||||||
Ok(self.writer.write_all(bytes)?)
|
Ok(self.buf.write_all(bytes)?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ use tokio::sync::OwnedSemaphorePermit;
|
||||||
use tokio::task::JoinHandle;
|
use tokio::task::JoinHandle;
|
||||||
use tokio::time::timeout;
|
use tokio::time::timeout;
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
use valence_protocol::{Decode, Encode, Packet, PacketDecoder, PacketEncoder};
|
use valence_protocol::{DecodePacket, EncodePacket, PacketDecoder, PacketEncoder};
|
||||||
|
|
||||||
use crate::packet::WritePacket;
|
use crate::packet::WritePacket;
|
||||||
use crate::server::byte_channel::{byte_channel, ByteReceiver, ByteSender, TryRecvError};
|
use crate::server::byte_channel::{byte_channel, ByteReceiver, ByteSender, TryRecvError};
|
||||||
|
@ -50,7 +50,7 @@ where
|
||||||
|
|
||||||
pub async fn send_packet<P>(&mut self, pkt: &P) -> Result<()>
|
pub async fn send_packet<P>(&mut self, pkt: &P) -> Result<()>
|
||||||
where
|
where
|
||||||
P: Encode + Packet + ?Sized,
|
P: EncodePacket + ?Sized,
|
||||||
{
|
{
|
||||||
self.enc.append_packet(pkt)?;
|
self.enc.append_packet(pkt)?;
|
||||||
let bytes = self.enc.take();
|
let bytes = self.enc.take();
|
||||||
|
@ -60,7 +60,7 @@ where
|
||||||
|
|
||||||
pub async fn recv_packet<'a, P>(&'a mut self) -> Result<P>
|
pub async fn recv_packet<'a, P>(&'a mut self) -> Result<P>
|
||||||
where
|
where
|
||||||
P: Decode<'a> + Packet,
|
P: DecodePacket<'a>,
|
||||||
{
|
{
|
||||||
timeout(self.timeout, async {
|
timeout(self.timeout, async {
|
||||||
while !self.dec.has_next_packet()? {
|
while !self.dec.has_next_packet()? {
|
||||||
|
@ -196,7 +196,7 @@ pub struct PlayPacketSender {
|
||||||
impl PlayPacketSender {
|
impl PlayPacketSender {
|
||||||
pub fn append_packet<P>(&mut self, pkt: &P) -> Result<()>
|
pub fn append_packet<P>(&mut self, pkt: &P) -> Result<()>
|
||||||
where
|
where
|
||||||
P: Encode + Packet + ?Sized,
|
P: EncodePacket + ?Sized,
|
||||||
{
|
{
|
||||||
self.enc.append_packet(pkt)
|
self.enc.append_packet(pkt)
|
||||||
}
|
}
|
||||||
|
@ -207,7 +207,7 @@ impl PlayPacketSender {
|
||||||
|
|
||||||
pub fn prepend_packet<P>(&mut self, pkt: &P) -> Result<()>
|
pub fn prepend_packet<P>(&mut self, pkt: &P) -> Result<()>
|
||||||
where
|
where
|
||||||
P: Encode + Packet + ?Sized,
|
P: EncodePacket + ?Sized,
|
||||||
{
|
{
|
||||||
self.enc.prepend_packet(pkt)
|
self.enc.prepend_packet(pkt)
|
||||||
}
|
}
|
||||||
|
@ -222,7 +222,7 @@ impl PlayPacketSender {
|
||||||
impl WritePacket for PlayPacketSender {
|
impl WritePacket for PlayPacketSender {
|
||||||
fn write_packet<P>(&mut self, packet: &P) -> Result<()>
|
fn write_packet<P>(&mut self, packet: &P) -> Result<()>
|
||||||
where
|
where
|
||||||
P: Encode + Packet + ?Sized,
|
P: EncodePacket + ?Sized,
|
||||||
{
|
{
|
||||||
self.append_packet(packet)
|
self.append_packet(packet)
|
||||||
}
|
}
|
||||||
|
@ -259,7 +259,7 @@ pub struct PlayPacketReceiver {
|
||||||
impl PlayPacketReceiver {
|
impl PlayPacketReceiver {
|
||||||
pub fn try_next_packet<'a, P>(&'a mut self) -> Result<Option<P>>
|
pub fn try_next_packet<'a, P>(&'a mut self) -> Result<Option<P>>
|
||||||
where
|
where
|
||||||
P: Decode<'a> + Packet,
|
P: DecodePacket<'a>,
|
||||||
{
|
{
|
||||||
self.dec.try_next_packet()
|
self.dec.try_next_packet()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::{quote, ToTokens};
|
use quote::quote;
|
||||||
use syn::spanned::Spanned;
|
use syn::spanned::Spanned;
|
||||||
use syn::{parse2, parse_quote, Data, DeriveInput, Error, Fields, Result};
|
use syn::{parse2, parse_quote, Data, DeriveInput, Error, Fields, Result};
|
||||||
|
|
||||||
|
@ -11,12 +11,6 @@ pub fn derive_decode(item: TokenStream) -> Result<TokenStream> {
|
||||||
let mut input = parse2::<DeriveInput>(item)?;
|
let mut input = parse2::<DeriveInput>(item)?;
|
||||||
|
|
||||||
let name = input.ident;
|
let name = input.ident;
|
||||||
let string_name = name.to_string();
|
|
||||||
|
|
||||||
let packet_id = find_packet_id_attr(&input.attrs)?
|
|
||||||
.into_iter()
|
|
||||||
.map(|l| l.to_token_stream())
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
if input.generics.lifetimes().count() > 1 {
|
if input.generics.lifetimes().count() > 1 {
|
||||||
return Err(Error::new(
|
return Err(Error::new(
|
||||||
|
@ -79,36 +73,15 @@ pub fn derive_decode(item: TokenStream) -> Result<TokenStream> {
|
||||||
|
|
||||||
Ok(quote! {
|
Ok(quote! {
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
impl #impl_generics ::valence_protocol::Decode<#lifetime> for #name #ty_generics
|
impl #impl_generics ::valence_protocol::__private::Decode<#lifetime> for #name #ty_generics
|
||||||
#where_clause
|
#where_clause
|
||||||
{
|
{
|
||||||
fn decode(_r: &mut &#lifetime [u8]) -> ::valence_protocol::__private::Result<Self> {
|
fn decode(_r: &mut &#lifetime [u8]) -> ::valence_protocol::__private::Result<Self> {
|
||||||
use ::valence_protocol::__private::{Decode, Context, VarInt, ensure};
|
use ::valence_protocol::__private::{Decode, Context, ensure};
|
||||||
|
|
||||||
#(
|
|
||||||
let id = VarInt::decode(_r).context("failed to decode packet ID")?.0;
|
|
||||||
ensure!(id == #packet_id, "unexpected packet ID {} (expected {})", id, #packet_id);
|
|
||||||
)*
|
|
||||||
|
|
||||||
Ok(#decode_fields)
|
Ok(#decode_fields)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#(
|
|
||||||
#[allow(unused_imports)]
|
|
||||||
impl #impl_generics ::valence_protocol::DerivedPacketDecode<#lifetime> for #name #ty_generics
|
|
||||||
#where_clause
|
|
||||||
{
|
|
||||||
const ID: i32 = #packet_id;
|
|
||||||
const NAME: &'static str = #string_name;
|
|
||||||
|
|
||||||
fn decode_without_id(_r: &mut &#lifetime [u8]) -> ::valence_protocol::__private::Result<Self> {
|
|
||||||
use ::valence_protocol::__private::{Decode, Context, VarInt, ensure};
|
|
||||||
|
|
||||||
Ok(#decode_fields)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)*
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Data::Enum(enum_) => {
|
Data::Enum(enum_) => {
|
||||||
|
@ -170,16 +143,11 @@ pub fn derive_decode(item: TokenStream) -> Result<TokenStream> {
|
||||||
|
|
||||||
Ok(quote! {
|
Ok(quote! {
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
impl #impl_generics ::valence_protocol::Decode<#lifetime> for #name #ty_generics
|
impl #impl_generics ::valence_protocol::__private::Decode<#lifetime> for #name #ty_generics
|
||||||
#where_clause
|
#where_clause
|
||||||
{
|
{
|
||||||
fn decode(_r: &mut &#lifetime [u8]) -> ::valence_protocol::__private::Result<Self> {
|
fn decode(_r: &mut &#lifetime [u8]) -> ::valence_protocol::__private::Result<Self> {
|
||||||
use ::valence_protocol::__private::{Decode, Context, VarInt, bail, ensure};
|
use ::valence_protocol::__private::{Decode, Context, VarInt, bail};
|
||||||
|
|
||||||
#(
|
|
||||||
let id = VarInt::decode(_r).context("failed to decode packet ID")?.0;
|
|
||||||
ensure!(id == #packet_id, "unexpected packet ID {} (expected {})", id, #packet_id);
|
|
||||||
)*
|
|
||||||
|
|
||||||
let disc = VarInt::decode(_r).context("failed to decode enum discriminant")?.0;
|
let disc = VarInt::decode(_r).context("failed to decode enum discriminant")?.0;
|
||||||
match disc {
|
match disc {
|
||||||
|
@ -188,26 +156,6 @@ pub fn derive_decode(item: TokenStream) -> Result<TokenStream> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#(
|
|
||||||
#[allow(unused_imports)]
|
|
||||||
impl #impl_generics ::valence_protocol::DerivedPacketDecode<#lifetime> for #name #ty_generics
|
|
||||||
#where_clause
|
|
||||||
{
|
|
||||||
const ID: i32 = #packet_id;
|
|
||||||
const NAME: &'static str = #string_name;
|
|
||||||
|
|
||||||
fn decode_without_id(_r: &mut &#lifetime [u8]) -> ::valence_protocol::__private::Result<Self> {
|
|
||||||
use ::valence_protocol::__private::{Decode, Context, VarInt, bail};
|
|
||||||
|
|
||||||
let disc = VarInt::decode(_r).context("failed to decode enum discriminant")?.0;
|
|
||||||
match disc {
|
|
||||||
#decode_arms
|
|
||||||
n => bail!("unexpected enum discriminant {}", disc),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)*
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Data::Union(u) => Err(Error::new(
|
Data::Union(u) => Err(Error::new(
|
||||||
|
@ -216,3 +164,48 @@ pub fn derive_decode(item: TokenStream) -> Result<TokenStream> {
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn derive_decode_packet(item: TokenStream) -> Result<TokenStream> {
|
||||||
|
let mut input = parse2::<DeriveInput>(item)?;
|
||||||
|
|
||||||
|
let Some(packet_id) = find_packet_id_attr(&input.attrs)? else {
|
||||||
|
return Err(Error::new(
|
||||||
|
input.ident.span(),
|
||||||
|
"cannot derive `DecodePacket` without `#[packet_id = ...]` helper attribute",
|
||||||
|
))
|
||||||
|
};
|
||||||
|
|
||||||
|
let lifetime = input
|
||||||
|
.generics
|
||||||
|
.lifetimes()
|
||||||
|
.next()
|
||||||
|
.map(|l| l.lifetime.clone())
|
||||||
|
.unwrap_or_else(|| parse_quote!('a));
|
||||||
|
|
||||||
|
add_trait_bounds(
|
||||||
|
&mut input.generics,
|
||||||
|
quote!(::valence_protocol::__private::Decode<#lifetime>),
|
||||||
|
);
|
||||||
|
|
||||||
|
let (impl_generics, ty_generics, where_clause) =
|
||||||
|
decode_split_for_impl(input.generics, lifetime.clone());
|
||||||
|
|
||||||
|
let name = input.ident;
|
||||||
|
|
||||||
|
Ok(quote! {
|
||||||
|
impl #impl_generics ::valence_protocol::__private::DecodePacket<#lifetime> for #name #ty_generics
|
||||||
|
#where_clause
|
||||||
|
{
|
||||||
|
const PACKET_ID: i32 = #packet_id;
|
||||||
|
|
||||||
|
fn decode_packet(r: &mut &#lifetime [u8]) -> ::valence_protocol::__private::Result<Self> {
|
||||||
|
use ::valence_protocol::__private::{Decode, Context, VarInt, ensure};
|
||||||
|
|
||||||
|
let id = VarInt::decode(r).context("failed to decode packet ID")?.0;
|
||||||
|
ensure!(id == #packet_id, "unexpected packet ID {} (expected {})", id, #packet_id);
|
||||||
|
|
||||||
|
Self::decode(r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use proc_macro2::{Ident, Span, TokenStream};
|
use proc_macro2::{Ident, Span, TokenStream};
|
||||||
use quote::{quote, ToTokens};
|
use quote::quote;
|
||||||
use syn::spanned::Spanned;
|
use syn::spanned::Spanned;
|
||||||
use syn::{parse2, Data, DeriveInput, Error, Fields, LitInt, Result};
|
use syn::{parse2, Data, DeriveInput, Error, Fields, LitInt, Result};
|
||||||
|
|
||||||
|
@ -9,22 +9,16 @@ pub fn derive_encode(item: TokenStream) -> Result<TokenStream> {
|
||||||
let mut input = parse2::<DeriveInput>(item)?;
|
let mut input = parse2::<DeriveInput>(item)?;
|
||||||
|
|
||||||
let name = input.ident;
|
let name = input.ident;
|
||||||
let string_name = name.to_string();
|
|
||||||
|
|
||||||
let packet_id = find_packet_id_attr(&input.attrs)?
|
add_trait_bounds(
|
||||||
.into_iter()
|
&mut input.generics,
|
||||||
.map(|l| l.to_token_stream())
|
quote!(::valence_protocol::__private::Encode),
|
||||||
.collect::<Vec<_>>();
|
);
|
||||||
|
|
||||||
|
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
|
||||||
|
|
||||||
match input.data {
|
match input.data {
|
||||||
Data::Struct(struct_) => {
|
Data::Struct(struct_) => {
|
||||||
add_trait_bounds(
|
|
||||||
&mut input.generics,
|
|
||||||
quote!(::valence_protocol::__private::Encode),
|
|
||||||
);
|
|
||||||
|
|
||||||
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
|
|
||||||
|
|
||||||
let encode_fields = match &struct_.fields {
|
let encode_fields = match &struct_.fields {
|
||||||
Fields::Named(fields) => fields
|
Fields::Named(fields) => fields
|
||||||
.named
|
.named
|
||||||
|
@ -49,87 +43,22 @@ pub fn derive_encode(item: TokenStream) -> Result<TokenStream> {
|
||||||
Fields::Unit => TokenStream::new(),
|
Fields::Unit => TokenStream::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let encoded_len_fields = match &struct_.fields {
|
|
||||||
Fields::Named(fields) => fields
|
|
||||||
.named
|
|
||||||
.iter()
|
|
||||||
.map(|f| {
|
|
||||||
let name = &f.ident;
|
|
||||||
quote! {
|
|
||||||
+ self.#name.encoded_len()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect(),
|
|
||||||
Fields::Unnamed(fields) => (0..fields.unnamed.len())
|
|
||||||
.map(|i| {
|
|
||||||
let lit = LitInt::new(&i.to_string(), Span::call_site());
|
|
||||||
quote! {
|
|
||||||
+ self.#lit.encoded_len()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect(),
|
|
||||||
Fields::Unit => TokenStream::new(),
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(quote! {
|
Ok(quote! {
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
impl #impl_generics ::valence_protocol::__private::Encode for #name #ty_generics
|
impl #impl_generics ::valence_protocol::__private::Encode for #name #ty_generics
|
||||||
#where_clause
|
#where_clause
|
||||||
{
|
{
|
||||||
fn encode(&self, mut _w: impl ::std::io::Write) -> ::valence_protocol::__private::Result<()> {
|
fn encode(&self, mut _w: impl ::std::io::Write) -> ::valence_protocol::__private::Result<()> {
|
||||||
use ::valence_protocol::__private::{Encode, Context, VarInt};
|
use ::valence_protocol::__private::{Encode, Context};
|
||||||
|
|
||||||
#(
|
|
||||||
VarInt(#packet_id)
|
|
||||||
.encode(&mut _w)
|
|
||||||
.context("failed to encode packet ID")?;
|
|
||||||
)*
|
|
||||||
|
|
||||||
#encode_fields
|
#encode_fields
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encoded_len(&self) -> usize {
|
|
||||||
use ::valence_protocol::__private::{Encode, Context, VarInt};
|
|
||||||
|
|
||||||
0 #(+ VarInt(#packet_id).encoded_len())* #encoded_len_fields
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#(
|
|
||||||
#[allow(unused_imports)]
|
|
||||||
impl #impl_generics ::valence_protocol::__private::DerivedPacketEncode for #name #ty_generics
|
|
||||||
#where_clause
|
|
||||||
{
|
|
||||||
const ID: i32 = #packet_id;
|
|
||||||
const NAME: &'static str = #string_name;
|
|
||||||
|
|
||||||
fn encode_without_id(&self, mut _w: impl ::std::io::Write) -> ::valence_protocol::__private::Result<()> {
|
|
||||||
use ::valence_protocol::__private::{Encode, Context, VarInt};
|
|
||||||
|
|
||||||
#encode_fields
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn encoded_len_without_id(&self) -> usize {
|
|
||||||
use ::valence_protocol::__private::{Encode, Context, VarInt};
|
|
||||||
|
|
||||||
0 #encoded_len_fields
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)*
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Data::Enum(enum_) => {
|
Data::Enum(enum_) => {
|
||||||
add_trait_bounds(
|
|
||||||
&mut input.generics,
|
|
||||||
quote!(::valence_protocol::__private::Encode),
|
|
||||||
);
|
|
||||||
|
|
||||||
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
|
|
||||||
|
|
||||||
let variants = pair_variants_with_discriminants(enum_.variants.into_iter())?;
|
let variants = pair_variants_with_discriminants(enum_.variants.into_iter())?;
|
||||||
|
|
||||||
let encode_arms = variants
|
let encode_arms = variants
|
||||||
|
@ -211,45 +140,6 @@ pub fn derive_encode(item: TokenStream) -> Result<TokenStream> {
|
||||||
})
|
})
|
||||||
.collect::<TokenStream>();
|
.collect::<TokenStream>();
|
||||||
|
|
||||||
let encoded_len_arms = variants
|
|
||||||
.iter()
|
|
||||||
.map(|(disc, variant)| {
|
|
||||||
let name = &variant.ident;
|
|
||||||
|
|
||||||
match &variant.fields {
|
|
||||||
Fields::Named(fields) => {
|
|
||||||
let fields = fields.named.iter().map(|f| &f.ident).collect::<Vec<_>>();
|
|
||||||
|
|
||||||
quote! {
|
|
||||||
Self::#name { #(#fields,)* } => {
|
|
||||||
VarInt(#disc).encoded_len()
|
|
||||||
|
|
||||||
#(+ #fields.encoded_len())*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Fields::Unnamed(fields) => {
|
|
||||||
let fields = (0..fields.unnamed.len())
|
|
||||||
.map(|i| Ident::new(&format!("_{i}"), Span::call_site()))
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
quote! {
|
|
||||||
Self::#name(#(#fields,)*) => {
|
|
||||||
VarInt(#disc).encoded_len()
|
|
||||||
|
|
||||||
#(+ #fields.encoded_len())*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Fields::Unit => {
|
|
||||||
quote! {
|
|
||||||
Self::#name => VarInt(#disc).encoded_len(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect::<TokenStream>();
|
|
||||||
|
|
||||||
Ok(quote! {
|
Ok(quote! {
|
||||||
#[allow(unused_imports, unreachable_code)]
|
#[allow(unused_imports, unreachable_code)]
|
||||||
impl #impl_generics ::valence_protocol::Encode for #name #ty_generics
|
impl #impl_generics ::valence_protocol::Encode for #name #ty_generics
|
||||||
|
@ -258,53 +148,12 @@ pub fn derive_encode(item: TokenStream) -> Result<TokenStream> {
|
||||||
fn encode(&self, mut _w: impl ::std::io::Write) -> ::valence_protocol::__private::Result<()> {
|
fn encode(&self, mut _w: impl ::std::io::Write) -> ::valence_protocol::__private::Result<()> {
|
||||||
use ::valence_protocol::__private::{Encode, VarInt, Context};
|
use ::valence_protocol::__private::{Encode, VarInt, Context};
|
||||||
|
|
||||||
#(
|
|
||||||
VarInt(#packet_id)
|
|
||||||
.encode(&mut _w)
|
|
||||||
.context("failed to encode packet ID")?;
|
|
||||||
)*
|
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
#encode_arms
|
#encode_arms
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn encoded_len(&self) -> usize {
|
|
||||||
use ::valence_protocol::__private::{Encode, Context, VarInt};
|
|
||||||
|
|
||||||
#(VarInt(#packet_id).encoded_len() +)* match self {
|
|
||||||
#encoded_len_arms
|
|
||||||
_ => unreachable!() as usize,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#(
|
|
||||||
#[allow(unused_imports)]
|
|
||||||
impl #impl_generics ::valence_protocol::DerivedPacketEncode for #name #ty_generics
|
|
||||||
#where_clause
|
|
||||||
{
|
|
||||||
const ID: i32 = #packet_id;
|
|
||||||
const NAME: &'static str = #string_name;
|
|
||||||
|
|
||||||
fn encode_without_id(&self, mut _w: impl ::std::io::Write) -> ::valence_protocol::__private::Result<()> {
|
|
||||||
use ::valence_protocol::__private::{Encode, VarInt, Context};
|
|
||||||
|
|
||||||
match self {
|
|
||||||
#encode_arms
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn encoded_len_without_id(&self) -> usize {
|
|
||||||
use ::valence_protocol::__private::{Encode, Context, VarInt};
|
|
||||||
|
|
||||||
match self {
|
|
||||||
#encoded_len_arms
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)*
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Data::Union(u) => Err(Error::new(
|
Data::Union(u) => Err(Error::new(
|
||||||
|
@ -313,3 +162,41 @@ pub fn derive_encode(item: TokenStream) -> Result<TokenStream> {
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn derive_encode_packet(item: TokenStream) -> Result<TokenStream> {
|
||||||
|
let mut input = parse2::<DeriveInput>(item)?;
|
||||||
|
|
||||||
|
let Some(packet_id) = find_packet_id_attr(&input.attrs)? else {
|
||||||
|
return Err(Error::new(
|
||||||
|
input.ident.span(),
|
||||||
|
"cannot derive `EncodePacket` without `#[packet_id = ...]` helper attribute",
|
||||||
|
))
|
||||||
|
};
|
||||||
|
|
||||||
|
add_trait_bounds(
|
||||||
|
&mut input.generics,
|
||||||
|
quote!(::valence_protocol::__private::Encode),
|
||||||
|
);
|
||||||
|
|
||||||
|
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
|
||||||
|
|
||||||
|
let name = input.ident;
|
||||||
|
|
||||||
|
Ok(quote! {
|
||||||
|
impl #impl_generics ::valence_protocol::__private::EncodePacket for #name #ty_generics
|
||||||
|
#where_clause
|
||||||
|
{
|
||||||
|
const PACKET_ID: i32 = #packet_id;
|
||||||
|
|
||||||
|
fn encode_packet(&self, mut w: impl ::std::io::Write) -> ::valence_protocol::__private::Result<()> {
|
||||||
|
use ::valence_protocol::__private::{Encode, Context, VarInt};
|
||||||
|
|
||||||
|
VarInt(#packet_id)
|
||||||
|
.encode(&mut w)
|
||||||
|
.context("failed to encode packet ID")?;
|
||||||
|
|
||||||
|
self.encode(w)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -4,17 +4,17 @@
|
||||||
//! See `valence_protocol`'s documentation for more information.
|
//! See `valence_protocol`'s documentation for more information.
|
||||||
|
|
||||||
use proc_macro::TokenStream as StdTokenStream;
|
use proc_macro::TokenStream as StdTokenStream;
|
||||||
use proc_macro2::{Span, TokenStream};
|
use proc_macro2::TokenStream;
|
||||||
use quote::{quote, ToTokens};
|
use quote::ToTokens;
|
||||||
use syn::{
|
use syn::{
|
||||||
parse2, parse_quote, Attribute, DeriveInput, Error, GenericParam, Generics, Lifetime,
|
parse_quote, Attribute, Error, GenericParam, Generics, Lifetime, LifetimeDef, Lit, LitInt,
|
||||||
LifetimeDef, Lit, LitInt, Meta, Result, Variant,
|
Meta, Result, Variant,
|
||||||
};
|
};
|
||||||
|
|
||||||
mod decode;
|
mod decode;
|
||||||
mod encode;
|
mod encode;
|
||||||
|
|
||||||
#[proc_macro_derive(Encode, attributes(packet_id, tag))]
|
#[proc_macro_derive(Encode, attributes(tag))]
|
||||||
pub fn derive_encode(item: StdTokenStream) -> StdTokenStream {
|
pub fn derive_encode(item: StdTokenStream) -> StdTokenStream {
|
||||||
match encode::derive_encode(item.into()) {
|
match encode::derive_encode(item.into()) {
|
||||||
Ok(tokens) => tokens.into(),
|
Ok(tokens) => tokens.into(),
|
||||||
|
@ -22,7 +22,15 @@ pub fn derive_encode(item: StdTokenStream) -> StdTokenStream {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proc_macro_derive(Decode, attributes(packet_id, tag))]
|
#[proc_macro_derive(EncodePacket, attributes(packet_id))]
|
||||||
|
pub fn derive_encode_packet(item: StdTokenStream) -> StdTokenStream {
|
||||||
|
match encode::derive_encode_packet(item.into()) {
|
||||||
|
Ok(tokens) => tokens.into(),
|
||||||
|
Err(e) => e.into_compile_error().into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[proc_macro_derive(Decode, attributes(tag))]
|
||||||
pub fn derive_decode(item: StdTokenStream) -> StdTokenStream {
|
pub fn derive_decode(item: StdTokenStream) -> StdTokenStream {
|
||||||
match decode::derive_decode(item.into()) {
|
match decode::derive_decode(item.into()) {
|
||||||
Ok(tokens) => tokens.into(),
|
Ok(tokens) => tokens.into(),
|
||||||
|
@ -30,41 +38,14 @@ pub fn derive_decode(item: StdTokenStream) -> StdTokenStream {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proc_macro_derive(Packet)]
|
#[proc_macro_derive(DecodePacket, attributes(packet_id))]
|
||||||
pub fn derive_packet(item: StdTokenStream) -> StdTokenStream {
|
pub fn derive_decode_packet(item: StdTokenStream) -> StdTokenStream {
|
||||||
match derive_packet_inner(item.into()) {
|
match decode::derive_decode_packet(item.into()) {
|
||||||
Ok(tokens) => tokens.into(),
|
Ok(tokens) => tokens.into(),
|
||||||
Err(e) => e.into_compile_error().into(),
|
Err(e) => e.into_compile_error().into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn derive_packet_inner(item: TokenStream) -> Result<TokenStream> {
|
|
||||||
let input = parse2::<DeriveInput>(item)?;
|
|
||||||
|
|
||||||
if find_packet_id_attr(&input.attrs)?.is_none() {
|
|
||||||
return Err(Error::new(
|
|
||||||
Span::call_site(),
|
|
||||||
"cannot derive `Packet` without `#[packet_id = ...]` attribute. Consider implementing \
|
|
||||||
the trait manually",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
let name = input.ident;
|
|
||||||
let string_name = name.to_string();
|
|
||||||
|
|
||||||
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
|
|
||||||
|
|
||||||
Ok(quote! {
|
|
||||||
impl #impl_generics ::valence_protocol::Packet for #name #ty_generics
|
|
||||||
#where_clause
|
|
||||||
{
|
|
||||||
fn packet_name(&self) -> &'static str {
|
|
||||||
#string_name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn find_packet_id_attr(attrs: &[Attribute]) -> Result<Option<LitInt>> {
|
fn find_packet_id_attr(attrs: &[Attribute]) -> Result<Option<LitInt>> {
|
||||||
for attr in attrs {
|
for attr in attrs {
|
||||||
if let Meta::NameValue(nv) = attr.parse_meta()? {
|
if let Meta::NameValue(nv) = attr.parse_meta()? {
|
||||||
|
|
|
@ -4,7 +4,7 @@ use std::hash::Hash;
|
||||||
use std::iter::FusedIterator;
|
use std::iter::FusedIterator;
|
||||||
use std::ops::{Index, IndexMut};
|
use std::ops::{Index, IndexMut};
|
||||||
|
|
||||||
use crate::to_binary_writer::encoded_len;
|
use crate::to_binary_writer::written_size;
|
||||||
use crate::Value;
|
use crate::Value;
|
||||||
|
|
||||||
/// A map type with [`String`] keys and [`Value`] values.
|
/// A map type with [`String`] keys and [`Value`] values.
|
||||||
|
@ -20,18 +20,17 @@ type Map = std::collections::BTreeMap<String, Value>;
|
||||||
type Map = indexmap::IndexMap<String, Value>;
|
type Map = indexmap::IndexMap<String, Value>;
|
||||||
|
|
||||||
impl Compound {
|
impl Compound {
|
||||||
/// Returns the number of bytes that will be written with
|
/// Returns the number of bytes that will be written when
|
||||||
/// [`to_binary_writer`] when called with this compound and root name.
|
/// [`to_binary_writer`] is called with this compound and root name.
|
||||||
///
|
///
|
||||||
/// If [`to_binary_writer`] results in `Ok`, the exact number of bytes
|
/// If [`to_binary_writer`] results in `Ok`, the exact number of bytes
|
||||||
/// reported by this function will have been written.
|
/// reported by this function will have been written. If the result is
|
||||||
///
|
/// `Err`, then the reported count will be greater than or equal to the
|
||||||
/// If the result is `Err`, then the reported count will be greater than or
|
/// number of bytes that have actually been written.
|
||||||
/// equal to the number of bytes that have actually been written.
|
|
||||||
///
|
///
|
||||||
/// [`to_binary_writer`]: crate::to_binary_writer()
|
/// [`to_binary_writer`]: crate::to_binary_writer()
|
||||||
pub fn binary_encoded_len(&self, root_name: &str) -> usize {
|
pub fn written_size(&self, root_name: &str) -> usize {
|
||||||
encoded_len(self, root_name)
|
written_size(self, root_name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -94,7 +94,7 @@ fn correct_length() {
|
||||||
let mut buf = vec![];
|
let mut buf = vec![];
|
||||||
to_binary_writer(&mut buf, &c, "abc").unwrap();
|
to_binary_writer(&mut buf, &c, "abc").unwrap();
|
||||||
|
|
||||||
assert_eq!(c.binary_encoded_len("abc"), buf.len());
|
assert_eq!(c.written_size("abc"), buf.len());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "preserve_order")]
|
#[cfg(feature = "preserve_order")]
|
||||||
|
|
|
@ -22,7 +22,7 @@ pub fn to_binary_writer<W: Write>(writer: W, compound: &Compound, root_name: &st
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn encoded_len(compound: &Compound, root_name: &str) -> usize {
|
pub(crate) fn written_size(compound: &Compound, root_name: &str) -> usize {
|
||||||
fn value_len(val: &Value) -> usize {
|
fn value_len(val: &Value) -> usize {
|
||||||
match val {
|
match val {
|
||||||
Value::Byte(_) => 1,
|
Value::Byte(_) => 1,
|
||||||
|
|
|
@ -7,7 +7,6 @@ build = "build/main.rs"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
aes = { version = "0.7.5", optional = true }
|
aes = { version = "0.7.5", optional = true }
|
||||||
anyhow = "1.0.66"
|
anyhow = "1.0.66"
|
||||||
arrayvec = "0.7.2"
|
|
||||||
bitfield-struct = "0.1.7"
|
bitfield-struct = "0.1.7"
|
||||||
byteorder = "1.4.3"
|
byteorder = "1.4.3"
|
||||||
bytes = "1.2.1"
|
bytes = "1.2.1"
|
||||||
|
|
|
@ -5,12 +5,11 @@ use rand::Rng;
|
||||||
use valence_nbt::{compound, List};
|
use valence_nbt::{compound, List};
|
||||||
use valence_protocol::block::{BlockKind, BlockState, PropName, PropValue};
|
use valence_protocol::block::{BlockKind, BlockState, PropName, PropValue};
|
||||||
use valence_protocol::packets::s2c::play::{
|
use valence_protocol::packets::s2c::play::{
|
||||||
ChunkDataAndUpdateLight, ChunkDataAndUpdateLightEncode, SetTabListHeaderAndFooter,
|
ChunkDataAndUpdateLight, ChunkDataAndUpdateLightEncode, SetTabListHeaderAndFooter, SpawnEntity,
|
||||||
TeleportEntity,
|
|
||||||
};
|
};
|
||||||
use valence_protocol::text::Color;
|
use valence_protocol::text::Color;
|
||||||
use valence_protocol::{
|
use valence_protocol::{
|
||||||
write_packet, write_packet_compressed, ByteAngle, Decode, Encode, ItemKind,
|
encode_packet, encode_packet_compressed, ByteAngle, Decode, Encode, ItemKind,
|
||||||
LengthPrefixedArray, PacketDecoder, PacketEncoder, TextFormat, VarInt,
|
LengthPrefixedArray, PacketDecoder, PacketEncoder, TextFormat, VarInt,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -18,7 +17,7 @@ criterion_group! {
|
||||||
name = benches;
|
name = benches;
|
||||||
config = Criterion::default()
|
config = Criterion::default()
|
||||||
.measurement_time(Duration::from_secs(5)).confidence_level(0.99);
|
.measurement_time(Duration::from_secs(5)).confidence_level(0.99);
|
||||||
targets = blocks, packets, var_int
|
targets = blocks, packets, var_int, decode_array
|
||||||
}
|
}
|
||||||
criterion_main!(benches);
|
criterion_main!(benches);
|
||||||
|
|
||||||
|
@ -139,12 +138,16 @@ fn packets(c: &mut Criterion) {
|
||||||
threshold.",
|
threshold.",
|
||||||
};
|
};
|
||||||
|
|
||||||
let teleport_entity_packet = TeleportEntity {
|
let spawn_entity_packet = SpawnEntity {
|
||||||
entity_id: VarInt(123456),
|
entity_id: VarInt(1234),
|
||||||
|
object_uuid: Default::default(),
|
||||||
|
kind: VarInt(5),
|
||||||
position: [123.0, 456.0, 789.0],
|
position: [123.0, 456.0, 789.0],
|
||||||
yaw: ByteAngle(42),
|
pitch: ByteAngle(200),
|
||||||
pitch: ByteAngle(69),
|
yaw: ByteAngle(100),
|
||||||
on_ground: true,
|
head_yaw: ByteAngle(50),
|
||||||
|
data: VarInt(i32::MIN),
|
||||||
|
velocity: [12, 34, 56],
|
||||||
};
|
};
|
||||||
|
|
||||||
c.bench_function("encode_chunk_data", |b| {
|
c.bench_function("encode_chunk_data", |b| {
|
||||||
|
@ -171,12 +174,12 @@ fn packets(c: &mut Criterion) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
c.bench_function("encode_teleport_entity", |b| {
|
c.bench_function("encode_spawn_entity", |b| {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
let encoder = black_box(&mut encoder);
|
let encoder = black_box(&mut encoder);
|
||||||
|
|
||||||
encoder.clear();
|
encoder.clear();
|
||||||
encoder.append_packet(&teleport_entity_packet).unwrap();
|
encoder.append_packet(&spawn_entity_packet).unwrap();
|
||||||
|
|
||||||
black_box(encoder);
|
black_box(encoder);
|
||||||
});
|
});
|
||||||
|
@ -208,12 +211,12 @@ fn packets(c: &mut Criterion) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
c.bench_function("encode_teleport_entity_compressed", |b| {
|
c.bench_function("encode_spawn_entity_compressed", |b| {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
let encoder = black_box(&mut encoder);
|
let encoder = black_box(&mut encoder);
|
||||||
|
|
||||||
encoder.clear();
|
encoder.clear();
|
||||||
encoder.append_packet(&teleport_entity_packet).unwrap();
|
encoder.append_packet(&spawn_entity_packet).unwrap();
|
||||||
|
|
||||||
black_box(encoder);
|
black_box(encoder);
|
||||||
});
|
});
|
||||||
|
@ -222,7 +225,7 @@ fn packets(c: &mut Criterion) {
|
||||||
let mut decoder = PacketDecoder::new();
|
let mut decoder = PacketDecoder::new();
|
||||||
let mut packet_buf = vec![];
|
let mut packet_buf = vec![];
|
||||||
|
|
||||||
write_packet(&mut packet_buf, &chunk_data_packet).unwrap();
|
encode_packet(&mut packet_buf, &chunk_data_packet).unwrap();
|
||||||
|
|
||||||
c.bench_function("decode_chunk_data", |b| {
|
c.bench_function("decode_chunk_data", |b| {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
|
@ -238,7 +241,7 @@ fn packets(c: &mut Criterion) {
|
||||||
});
|
});
|
||||||
|
|
||||||
packet_buf.clear();
|
packet_buf.clear();
|
||||||
write_packet(&mut packet_buf, &tab_list_header_footer_packet).unwrap();
|
encode_packet(&mut packet_buf, &tab_list_header_footer_packet).unwrap();
|
||||||
|
|
||||||
c.bench_function("decode_tab_list_header_footer", |b| {
|
c.bench_function("decode_tab_list_header_footer", |b| {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
|
@ -254,14 +257,14 @@ fn packets(c: &mut Criterion) {
|
||||||
});
|
});
|
||||||
|
|
||||||
packet_buf.clear();
|
packet_buf.clear();
|
||||||
write_packet(&mut packet_buf, &teleport_entity_packet).unwrap();
|
encode_packet(&mut packet_buf, &spawn_entity_packet).unwrap();
|
||||||
|
|
||||||
c.bench_function("decode_teleport_entity", |b| {
|
c.bench_function("decode_spawn_entity", |b| {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
let decoder = black_box(&mut decoder);
|
let decoder = black_box(&mut decoder);
|
||||||
|
|
||||||
decoder.queue_slice(&packet_buf);
|
decoder.queue_slice(&packet_buf);
|
||||||
decoder.try_next_packet::<TeleportEntity>().unwrap();
|
decoder.try_next_packet::<SpawnEntity>().unwrap();
|
||||||
|
|
||||||
black_box(decoder);
|
black_box(decoder);
|
||||||
});
|
});
|
||||||
|
@ -272,7 +275,7 @@ fn packets(c: &mut Criterion) {
|
||||||
let mut scratch = vec![];
|
let mut scratch = vec![];
|
||||||
|
|
||||||
packet_buf.clear();
|
packet_buf.clear();
|
||||||
write_packet_compressed(&mut packet_buf, 256, &mut scratch, &chunk_data_packet).unwrap();
|
encode_packet_compressed(&mut packet_buf, &chunk_data_packet, 256, &mut scratch).unwrap();
|
||||||
|
|
||||||
c.bench_function("decode_chunk_data_compressed", |b| {
|
c.bench_function("decode_chunk_data_compressed", |b| {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
|
@ -288,11 +291,11 @@ fn packets(c: &mut Criterion) {
|
||||||
});
|
});
|
||||||
|
|
||||||
packet_buf.clear();
|
packet_buf.clear();
|
||||||
write_packet_compressed(
|
encode_packet_compressed(
|
||||||
&mut packet_buf,
|
&mut packet_buf,
|
||||||
|
&tab_list_header_footer_packet,
|
||||||
256,
|
256,
|
||||||
&mut scratch,
|
&mut scratch,
|
||||||
&tab_list_header_footer_packet,
|
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -310,14 +313,14 @@ fn packets(c: &mut Criterion) {
|
||||||
});
|
});
|
||||||
|
|
||||||
packet_buf.clear();
|
packet_buf.clear();
|
||||||
write_packet_compressed(&mut packet_buf, 256, &mut scratch, &teleport_entity_packet).unwrap();
|
encode_packet_compressed(&mut packet_buf, &spawn_entity_packet, 256, &mut scratch).unwrap();
|
||||||
|
|
||||||
c.bench_function("decode_teleport_entity_compressed", |b| {
|
c.bench_function("decode_spawn_entity_compressed", |b| {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
let decoder = black_box(&mut decoder);
|
let decoder = black_box(&mut decoder);
|
||||||
|
|
||||||
decoder.queue_slice(&packet_buf);
|
decoder.queue_slice(&packet_buf);
|
||||||
decoder.try_next_packet::<TeleportEntity>().unwrap();
|
decoder.try_next_packet::<SpawnEntity>().unwrap();
|
||||||
|
|
||||||
black_box(decoder);
|
black_box(decoder);
|
||||||
});
|
});
|
||||||
|
@ -353,3 +356,26 @@ fn var_int(c: &mut Criterion) {
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn decode_array(c: &mut Criterion) {
|
||||||
|
let floats = [123.0, 456.0, 789.0];
|
||||||
|
let mut buf = [0u8; 24];
|
||||||
|
|
||||||
|
floats.encode(buf.as_mut_slice()).unwrap();
|
||||||
|
|
||||||
|
c.bench_function("<[f64; 3]>::decode", |b| {
|
||||||
|
b.iter(|| {
|
||||||
|
let mut r = black_box(buf.as_slice());
|
||||||
|
let _ = black_box(<[f64; 3]>::decode(&mut r));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
let bytes = [42; 4096];
|
||||||
|
|
||||||
|
c.bench_function("<[u8; 4096]>::decode", |b| {
|
||||||
|
b.iter(|| {
|
||||||
|
let mut r = black_box(bytes.as_slice());
|
||||||
|
let _ = black_box(<[u8; 4096]>::decode(&mut r));
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -17,10 +17,6 @@ impl<T: Encode, const N: usize> Encode for LengthPrefixedArray<T, N> {
|
||||||
VarInt(N as i32).encode(&mut w)?;
|
VarInt(N as i32).encode(&mut w)?;
|
||||||
self.0.encode(w)
|
self.0.encode(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encoded_len(&self) -> usize {
|
|
||||||
VarInt(N as i32).encoded_len() + self.0.encoded_len()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: Decode<'a>, const N: usize> Decode<'a> for LengthPrefixedArray<T, N> {
|
impl<'a, T: Decode<'a>, const N: usize> Decode<'a> for LengthPrefixedArray<T, N> {
|
||||||
|
|
|
@ -53,10 +53,6 @@ impl Encode for BlockState {
|
||||||
fn encode(&self, w: impl Write) -> Result<()> {
|
fn encode(&self, w: impl Write) -> Result<()> {
|
||||||
VarInt(self.0 as i32).encode(w)
|
VarInt(self.0 as i32).encode(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encoded_len(&self) -> usize {
|
|
||||||
VarInt(self.0 as i32).encoded_len()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decode<'_> for BlockState {
|
impl Decode<'_> for BlockState {
|
||||||
|
|
|
@ -55,10 +55,6 @@ impl Encode for BlockPos {
|
||||||
_ => bail!("out of range: {self:?}"),
|
_ => bail!("out of range: {self:?}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encoded_len(&self) -> usize {
|
|
||||||
8
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decode<'_> for BlockPos {
|
impl Decode<'_> for BlockPos {
|
||||||
|
|
|
@ -29,10 +29,6 @@ where
|
||||||
|
|
||||||
self.0.encode(w)
|
self.0.encode(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encoded_len(&self) -> usize {
|
|
||||||
self.0.encoded_len()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T, const MIN: i128, const MAX: i128> Decode<'a> for BoundedInt<T, MIN, MAX>
|
impl<'a, T, const MIN: i128, const MAX: i128> Decode<'a> for BoundedInt<T, MIN, MAX>
|
||||||
|
@ -82,10 +78,6 @@ where
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encoded_len(&self) -> usize {
|
|
||||||
self.0.as_ref().encoded_len()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, S, const MIN: usize, const MAX: usize> Decode<'a> for BoundedString<S, MIN, MAX>
|
impl<'a, S, const MIN: usize, const MAX: usize> Decode<'a> for BoundedString<S, MIN, MAX>
|
||||||
|
|
|
@ -29,10 +29,6 @@ impl Encode for ByteAngle {
|
||||||
fn encode(&self, w: impl Write) -> Result<()> {
|
fn encode(&self, w: impl Write) -> Result<()> {
|
||||||
self.0.encode(w)
|
self.0.encode(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encoded_len(&self) -> usize {
|
|
||||||
self.0.encoded_len()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decode<'_> for ByteAngle {
|
impl Decode<'_> for ByteAngle {
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
use std::io;
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug)]
|
|
||||||
pub struct ByteCounter(pub usize);
|
|
||||||
|
|
||||||
impl ByteCounter {
|
|
||||||
pub const fn new() -> Self {
|
|
||||||
Self(0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl io::Write for ByteCounter {
|
|
||||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
|
||||||
self.0 += buf.len();
|
|
||||||
Ok(buf.len())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn flush(&mut self) -> io::Result<()> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
|
|
||||||
self.0 += buf.len();
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +1,10 @@
|
||||||
use std::io::Write;
|
|
||||||
|
|
||||||
#[cfg(feature = "encryption")]
|
#[cfg(feature = "encryption")]
|
||||||
use aes::cipher::{AsyncStreamCipher, NewCipher};
|
use aes::cipher::{AsyncStreamCipher, NewCipher};
|
||||||
use anyhow::{bail, ensure};
|
use anyhow::{bail, ensure};
|
||||||
use bytes::{Buf, BufMut, BytesMut};
|
use bytes::{Buf, BufMut, BytesMut};
|
||||||
|
|
||||||
use crate::var_int::{VarInt, VarIntDecodeError};
|
use crate::var_int::{VarInt, VarIntDecodeError};
|
||||||
use crate::{Decode, Encode, Packet, Result, MAX_PACKET_SIZE};
|
use crate::{DecodePacket, Encode, EncodePacket, Result, MAX_PACKET_SIZE};
|
||||||
|
|
||||||
/// The AES block cipher with a 128 bit key, using the CFB-8 mode of
|
/// The AES block cipher with a 128 bit key, using the CFB-8 mode of
|
||||||
/// operation.
|
/// operation.
|
||||||
|
@ -29,108 +27,93 @@ impl PacketEncoder {
|
||||||
Self::default()
|
Self::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn append_packet<P>(&mut self, pkt: &P) -> Result<()>
|
|
||||||
where
|
|
||||||
P: Encode + Packet + ?Sized,
|
|
||||||
{
|
|
||||||
self.append_or_prepend_packet::<true>(pkt)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn append_bytes(&mut self, bytes: &[u8]) {
|
pub fn append_bytes(&mut self, bytes: &[u8]) {
|
||||||
self.buf.extend_from_slice(bytes)
|
self.buf.extend_from_slice(bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn prepend_packet<P>(&mut self, pkt: &P) -> Result<()>
|
pub fn prepend_packet<P>(&mut self, pkt: &P) -> Result<()>
|
||||||
where
|
where
|
||||||
P: Encode + Packet + ?Sized,
|
P: EncodePacket + ?Sized,
|
||||||
{
|
{
|
||||||
self.append_or_prepend_packet::<false>(pkt)
|
let start_len = self.buf.len();
|
||||||
|
self.append_packet(pkt)?;
|
||||||
|
|
||||||
|
let end_len = self.buf.len();
|
||||||
|
let total_packet_len = end_len - start_len;
|
||||||
|
|
||||||
|
// 1) Move everything back by the length of the packet.
|
||||||
|
// 2) Move the packet to the new space at the front.
|
||||||
|
// 3) Truncate the old packet away.
|
||||||
|
self.buf.put_bytes(0, total_packet_len);
|
||||||
|
self.buf.copy_within(..end_len, total_packet_len);
|
||||||
|
self.buf.copy_within(total_packet_len + start_len.., 0);
|
||||||
|
self.buf.truncate(end_len);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn append_or_prepend_packet<const APPEND: bool>(
|
pub fn append_packet<P>(&mut self, pkt: &P) -> Result<()>
|
||||||
&mut self,
|
where
|
||||||
pkt: &(impl Encode + Packet + ?Sized),
|
P: EncodePacket + ?Sized,
|
||||||
) -> Result<()> {
|
{
|
||||||
let data_len = pkt.encoded_len();
|
let start_len = self.buf.len();
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
pkt.encode_packet((&mut self.buf).writer())?;
|
||||||
{
|
|
||||||
use crate::byte_counter::ByteCounter;
|
|
||||||
|
|
||||||
let mut counter = ByteCounter::new();
|
let data_len = self.buf.len() - start_len;
|
||||||
pkt.encode(&mut counter)?;
|
|
||||||
|
|
||||||
let actual = counter.0;
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
actual,
|
|
||||||
data_len,
|
|
||||||
"actual encoded size of {} packet differs from reported size (actual = {actual}, \
|
|
||||||
reported = {data_len})",
|
|
||||||
pkt.packet_name()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "compression")]
|
#[cfg(feature = "compression")]
|
||||||
if let Some(threshold) = self.compression_threshold {
|
if let Some(threshold) = self.compression_threshold {
|
||||||
use flate2::write::ZlibEncoder;
|
use std::io::Read;
|
||||||
|
|
||||||
|
use flate2::bufread::ZlibEncoder;
|
||||||
use flate2::Compression;
|
use flate2::Compression;
|
||||||
|
|
||||||
if data_len >= threshold as usize {
|
if data_len > threshold as usize {
|
||||||
let mut z = ZlibEncoder::new(&mut self.compress_buf, Compression::new(4));
|
let mut z = ZlibEncoder::new(&self.buf[start_len..], Compression::new(4));
|
||||||
pkt.encode(&mut z)?;
|
|
||||||
drop(z);
|
|
||||||
|
|
||||||
let packet_len = VarInt(data_len as i32).encoded_len() + self.compress_buf.len();
|
|
||||||
|
|
||||||
ensure!(
|
|
||||||
packet_len <= MAX_PACKET_SIZE as usize,
|
|
||||||
"packet exceeds maximum length"
|
|
||||||
);
|
|
||||||
|
|
||||||
// BytesMut doesn't implement io::Write for some reason.
|
|
||||||
let mut writer = (&mut self.buf).writer();
|
|
||||||
|
|
||||||
if APPEND {
|
|
||||||
VarInt(packet_len as i32).encode(&mut writer)?;
|
|
||||||
VarInt(data_len as i32).encode(&mut writer)?;
|
|
||||||
self.buf.extend_from_slice(&self.compress_buf);
|
|
||||||
} else {
|
|
||||||
let mut slice = move_forward_by(
|
|
||||||
&mut self.buf,
|
|
||||||
VarInt(packet_len as i32).encoded_len() + packet_len,
|
|
||||||
);
|
|
||||||
|
|
||||||
VarInt(packet_len as i32).encode(&mut slice)?;
|
|
||||||
VarInt(data_len as i32).encode(&mut slice)?;
|
|
||||||
slice.copy_from_slice(&self.compress_buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.compress_buf.clear();
|
self.compress_buf.clear();
|
||||||
} else {
|
|
||||||
let packet_len = VarInt(0).encoded_len() + data_len;
|
let data_len_size = VarInt(data_len as i32).written_size();
|
||||||
|
|
||||||
|
let packet_len = data_len_size + z.read_to_end(&mut self.compress_buf)?;
|
||||||
|
|
||||||
ensure!(
|
ensure!(
|
||||||
packet_len <= MAX_PACKET_SIZE as usize,
|
packet_len <= MAX_PACKET_SIZE as usize,
|
||||||
"packet exceeds maximum length"
|
"packet exceeds maximum length"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
drop(z);
|
||||||
|
|
||||||
|
self.buf.truncate(start_len);
|
||||||
|
|
||||||
let mut writer = (&mut self.buf).writer();
|
let mut writer = (&mut self.buf).writer();
|
||||||
|
|
||||||
if APPEND {
|
VarInt(packet_len as i32).encode(&mut writer)?;
|
||||||
VarInt(packet_len as i32).encode(&mut writer)?;
|
VarInt(data_len as i32).encode(&mut writer)?;
|
||||||
VarInt(0).encode(&mut writer)?; // 0 for no compression on this packet.
|
self.buf.extend_from_slice(&self.compress_buf);
|
||||||
pkt.encode(&mut writer)?;
|
} else {
|
||||||
} else {
|
let data_len_size = 1;
|
||||||
let mut slice = move_forward_by(
|
let packet_len = data_len_size + data_len;
|
||||||
&mut self.buf,
|
|
||||||
VarInt(packet_len as i32).encoded_len() + packet_len,
|
|
||||||
);
|
|
||||||
|
|
||||||
VarInt(packet_len as i32).encode(&mut slice)?;
|
ensure!(
|
||||||
VarInt(0).encode(&mut slice)?;
|
packet_len <= MAX_PACKET_SIZE as usize,
|
||||||
pkt.encode(&mut slice)?;
|
"packet exceeds maximum length"
|
||||||
}
|
);
|
||||||
|
|
||||||
|
let packet_len_size = VarInt(packet_len as i32).written_size();
|
||||||
|
|
||||||
|
let data_prefix_len = packet_len_size + data_len_size;
|
||||||
|
|
||||||
|
self.buf.put_bytes(0, data_prefix_len);
|
||||||
|
self.buf
|
||||||
|
.copy_within(start_len..start_len + data_len, start_len + data_prefix_len);
|
||||||
|
|
||||||
|
let mut front = &mut self.buf[start_len..];
|
||||||
|
|
||||||
|
VarInt(packet_len as i32).encode(&mut front)?;
|
||||||
|
// Zero for no compression on this packet.
|
||||||
|
VarInt(0).encode(front)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
@ -143,27 +126,14 @@ impl PacketEncoder {
|
||||||
"packet exceeds maximum length"
|
"packet exceeds maximum length"
|
||||||
);
|
);
|
||||||
|
|
||||||
if APPEND {
|
let packet_len_size = VarInt(packet_len as i32).written_size();
|
||||||
let mut writer = (&mut self.buf).writer();
|
|
||||||
VarInt(packet_len as i32).encode(&mut writer)?;
|
|
||||||
pkt.encode(&mut writer)?;
|
|
||||||
} else {
|
|
||||||
let mut slice = move_forward_by(
|
|
||||||
&mut self.buf,
|
|
||||||
VarInt(packet_len as i32).encoded_len() + packet_len,
|
|
||||||
);
|
|
||||||
|
|
||||||
VarInt(packet_len as i32).encode(&mut slice)?;
|
self.buf.put_bytes(0, packet_len_size);
|
||||||
pkt.encode(&mut slice)?;
|
self.buf
|
||||||
|
.copy_within(start_len..start_len + data_len, start_len + packet_len_size);
|
||||||
|
|
||||||
debug_assert!(
|
let front = &mut self.buf[start_len..];
|
||||||
slice.is_empty(),
|
VarInt(packet_len as i32).encode(front)?;
|
||||||
"actual size of {} packet differs from reported size (actual = {}, reported = {})",
|
|
||||||
pkt.packet_name(),
|
|
||||||
data_len - slice.len(),
|
|
||||||
data_len,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -199,75 +169,98 @@ impl PacketEncoder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Move the bytes in `bytes` forward by `count` bytes and return a
|
pub fn encode_packet<P>(buf: &mut Vec<u8>, pkt: &P) -> Result<()>
|
||||||
/// mutable reference to the new space at the front.
|
|
||||||
fn move_forward_by(bytes: &mut BytesMut, count: usize) -> &mut [u8] {
|
|
||||||
let len = bytes.len();
|
|
||||||
bytes.put_bytes(0, count);
|
|
||||||
bytes.copy_within(..len, count);
|
|
||||||
&mut bytes[..count]
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn write_packet<W, P>(mut writer: W, packet: &P) -> Result<()>
|
|
||||||
where
|
where
|
||||||
W: Write,
|
P: EncodePacket + ?Sized,
|
||||||
P: Encode + Packet + ?Sized,
|
|
||||||
{
|
{
|
||||||
let packet_len = packet.encoded_len();
|
let start_len = buf.len();
|
||||||
|
|
||||||
|
pkt.encode_packet(&mut *buf)?;
|
||||||
|
|
||||||
|
let packet_len = buf.len() - start_len;
|
||||||
|
|
||||||
ensure!(
|
ensure!(
|
||||||
packet_len <= MAX_PACKET_SIZE as usize,
|
packet_len <= MAX_PACKET_SIZE as usize,
|
||||||
"packet exceeds maximum length"
|
"packet exceeds maximum length"
|
||||||
);
|
);
|
||||||
|
|
||||||
VarInt(packet_len as i32).encode(&mut writer)?;
|
let packet_len_size = VarInt(packet_len as i32).written_size();
|
||||||
packet.encode(&mut writer)
|
|
||||||
|
buf.put_bytes(0, packet_len_size);
|
||||||
|
buf.copy_within(
|
||||||
|
start_len..start_len + packet_len,
|
||||||
|
start_len + packet_len_size,
|
||||||
|
);
|
||||||
|
|
||||||
|
let front = &mut buf[start_len..];
|
||||||
|
VarInt(packet_len as i32).encode(front)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "compression")]
|
#[cfg(feature = "compression")]
|
||||||
pub fn write_packet_compressed<W, P>(
|
pub fn encode_packet_compressed<P>(
|
||||||
mut writer: W,
|
buf: &mut Vec<u8>,
|
||||||
|
pkt: &P,
|
||||||
threshold: u32,
|
threshold: u32,
|
||||||
scratch: &mut Vec<u8>,
|
scratch: &mut Vec<u8>,
|
||||||
packet: &P,
|
|
||||||
) -> Result<()>
|
) -> Result<()>
|
||||||
where
|
where
|
||||||
W: Write,
|
P: EncodePacket + ?Sized,
|
||||||
P: Encode + Packet + ?Sized,
|
|
||||||
{
|
{
|
||||||
use flate2::write::ZlibEncoder;
|
use std::io::Read;
|
||||||
|
|
||||||
|
use flate2::bufread::ZlibEncoder;
|
||||||
use flate2::Compression;
|
use flate2::Compression;
|
||||||
|
|
||||||
let data_len = packet.encoded_len();
|
let start_len = buf.len();
|
||||||
|
|
||||||
|
pkt.encode_packet(&mut *buf)?;
|
||||||
|
|
||||||
|
let data_len = buf.len() - start_len;
|
||||||
|
|
||||||
if data_len > threshold as usize {
|
if data_len > threshold as usize {
|
||||||
|
let mut z = ZlibEncoder::new(&buf[start_len..], Compression::new(4));
|
||||||
|
|
||||||
scratch.clear();
|
scratch.clear();
|
||||||
|
|
||||||
let mut z = ZlibEncoder::new(&mut *scratch, Compression::new(4));
|
let data_len_size = VarInt(data_len as i32).written_size();
|
||||||
packet.encode(&mut z)?;
|
|
||||||
|
let packet_len = data_len_size + z.read_to_end(scratch)?;
|
||||||
|
|
||||||
|
ensure!(
|
||||||
|
packet_len <= MAX_PACKET_SIZE as usize,
|
||||||
|
"packet exceeds maximum length"
|
||||||
|
);
|
||||||
|
|
||||||
drop(z);
|
drop(z);
|
||||||
|
|
||||||
let packet_len = VarInt(data_len as i32).encoded_len() + scratch.len();
|
buf.truncate(start_len);
|
||||||
|
|
||||||
ensure!(
|
VarInt(packet_len as i32).encode(&mut *buf)?;
|
||||||
packet_len <= MAX_PACKET_SIZE as usize,
|
VarInt(data_len as i32).encode(&mut *buf)?;
|
||||||
"packet exceeds maximum length"
|
buf.extend_from_slice(scratch);
|
||||||
);
|
|
||||||
|
|
||||||
VarInt(packet_len as i32).encode(&mut writer)?;
|
|
||||||
VarInt(data_len as i32).encode(&mut writer)?;
|
|
||||||
writer.write_all(scratch)?;
|
|
||||||
} else {
|
} else {
|
||||||
let packet_len = VarInt(0).encoded_len() + data_len;
|
let data_len_size = 1;
|
||||||
|
let packet_len = data_len_size + data_len;
|
||||||
|
|
||||||
ensure!(
|
ensure!(
|
||||||
packet_len <= MAX_PACKET_SIZE as usize,
|
packet_len <= MAX_PACKET_SIZE as usize,
|
||||||
"packet exceeds maximum length"
|
"packet exceeds maximum length"
|
||||||
);
|
);
|
||||||
|
|
||||||
VarInt(packet_len as i32).encode(&mut writer)?;
|
let packet_len_size = VarInt(packet_len as i32).written_size();
|
||||||
VarInt(0).encode(&mut writer)?; // 0 for no compression on this packet.
|
|
||||||
packet.encode(&mut writer)?;
|
let data_prefix_len = packet_len_size + data_len_size;
|
||||||
|
|
||||||
|
buf.put_bytes(0, data_prefix_len);
|
||||||
|
buf.copy_within(start_len..start_len + data_len, start_len + data_prefix_len);
|
||||||
|
|
||||||
|
let mut front = &mut buf[start_len..];
|
||||||
|
|
||||||
|
VarInt(packet_len as i32).encode(&mut front)?;
|
||||||
|
// Zero for no compression on this packet.
|
||||||
|
VarInt(0).encode(front)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -292,7 +285,7 @@ impl PacketDecoder {
|
||||||
|
|
||||||
pub fn try_next_packet<'a, P>(&'a mut self) -> Result<Option<P>>
|
pub fn try_next_packet<'a, P>(&'a mut self) -> Result<Option<P>>
|
||||||
where
|
where
|
||||||
P: Decode<'a> + Packet,
|
P: DecodePacket<'a>,
|
||||||
{
|
{
|
||||||
self.buf.advance(self.cursor);
|
self.buf.advance(self.cursor);
|
||||||
self.cursor = 0;
|
self.cursor = 0;
|
||||||
|
@ -318,6 +311,13 @@ impl PacketDecoder {
|
||||||
|
|
||||||
#[cfg(feature = "compression")]
|
#[cfg(feature = "compression")]
|
||||||
let packet = if self.compression_enabled {
|
let packet = if self.compression_enabled {
|
||||||
|
use std::io::Read;
|
||||||
|
|
||||||
|
use anyhow::Context;
|
||||||
|
use flate2::bufread::ZlibDecoder;
|
||||||
|
|
||||||
|
use crate::Decode;
|
||||||
|
|
||||||
let data_len = VarInt::decode(&mut r)?.0;
|
let data_len = VarInt::decode(&mut r)?.0;
|
||||||
|
|
||||||
ensure!(
|
ensure!(
|
||||||
|
@ -326,11 +326,6 @@ impl PacketDecoder {
|
||||||
);
|
);
|
||||||
|
|
||||||
if data_len != 0 {
|
if data_len != 0 {
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
use anyhow::Context;
|
|
||||||
use flate2::bufread::ZlibDecoder;
|
|
||||||
|
|
||||||
self.decompress_buf.clear();
|
self.decompress_buf.clear();
|
||||||
self.decompress_buf.reserve_exact(data_len as usize);
|
self.decompress_buf.reserve_exact(data_len as usize);
|
||||||
let mut z = ZlibDecoder::new(r).take(data_len as u64);
|
let mut z = ZlibDecoder::new(r).take(data_len as u64);
|
||||||
|
@ -339,16 +334,16 @@ impl PacketDecoder {
|
||||||
.context("decompressing packet")?;
|
.context("decompressing packet")?;
|
||||||
|
|
||||||
r = &self.decompress_buf;
|
r = &self.decompress_buf;
|
||||||
P::decode(&mut r)?
|
P::decode_packet(&mut r)?
|
||||||
} else {
|
} else {
|
||||||
P::decode(&mut r)?
|
P::decode_packet(&mut r)?
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
P::decode(&mut r)?
|
P::decode_packet(&mut r)?
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(not(feature = "compression"))]
|
#[cfg(not(feature = "compression"))]
|
||||||
let packet = P::decode(&mut r)?;
|
let packet = P::decode_packet(&mut r)?;
|
||||||
|
|
||||||
ensure!(
|
ensure!(
|
||||||
r.is_empty(),
|
r.is_empty(),
|
||||||
|
@ -356,7 +351,7 @@ impl PacketDecoder {
|
||||||
r.len()
|
r.len()
|
||||||
);
|
);
|
||||||
|
|
||||||
let total_packet_len = VarInt(packet_len).encoded_len() + packet_len as usize;
|
let total_packet_len = VarInt(packet_len).written_size() + packet_len as usize;
|
||||||
self.cursor = total_packet_len;
|
self.cursor = total_packet_len;
|
||||||
|
|
||||||
Ok(Some(packet))
|
Ok(Some(packet))
|
||||||
|
@ -440,11 +435,12 @@ mod tests {
|
||||||
use crate::text::{Text, TextFormat};
|
use crate::text::{Text, TextFormat};
|
||||||
use crate::username::Username;
|
use crate::username::Username;
|
||||||
use crate::var_long::VarLong;
|
use crate::var_long::VarLong;
|
||||||
|
use crate::Decode;
|
||||||
|
|
||||||
#[cfg(feature = "encryption")]
|
#[cfg(feature = "encryption")]
|
||||||
const CRYPT_KEY: [u8; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
|
const CRYPT_KEY: [u8; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
|
||||||
|
|
||||||
#[derive(PartialEq, Debug, Encode, Decode, Packet)]
|
#[derive(PartialEq, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 42]
|
#[packet_id = 42]
|
||||||
struct TestPacket<'a> {
|
struct TestPacket<'a> {
|
||||||
a: bool,
|
a: bool,
|
||||||
|
@ -507,6 +503,7 @@ mod tests {
|
||||||
enc.enable_encryption(&CRYPT_KEY);
|
enc.enable_encryption(&CRYPT_KEY);
|
||||||
enc.append_packet(&TestPacket::new("third")).unwrap();
|
enc.append_packet(&TestPacket::new("third")).unwrap();
|
||||||
enc.prepend_packet(&TestPacket::new("fourth")).unwrap();
|
enc.prepend_packet(&TestPacket::new("fourth")).unwrap();
|
||||||
|
|
||||||
buf.unsplit(enc.take());
|
buf.unsplit(enc.take());
|
||||||
|
|
||||||
let mut dec = PacketDecoder::new();
|
let mut dec = PacketDecoder::new();
|
||||||
|
|
|
@ -265,10 +265,6 @@ impl<S: Encode> Encode for Ident<S> {
|
||||||
fn encode(&self, w: impl Write) -> anyhow::Result<()> {
|
fn encode(&self, w: impl Write) -> anyhow::Result<()> {
|
||||||
self.string.encode(w)
|
self.string.encode(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encoded_len(&self) -> usize {
|
|
||||||
self.string.encoded_len()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, S> Decode<'a> for Ident<S>
|
impl<'a, S> Decode<'a> for Ident<S>
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::mem;
|
use std::mem::MaybeUninit;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use std::{io, mem};
|
||||||
|
|
||||||
use anyhow::ensure;
|
use anyhow::ensure;
|
||||||
use arrayvec::ArrayVec;
|
|
||||||
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
|
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
use valence_nbt::Compound;
|
use valence_nbt::Compound;
|
||||||
|
@ -19,9 +19,12 @@ impl Encode for bool {
|
||||||
Ok(w.write_u8(*self as u8)?)
|
Ok(w.write_u8(*self as u8)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encoded_len(&self) -> usize {
|
fn write_slice(slice: &[bool], mut w: impl Write) -> io::Result<()> {
|
||||||
1
|
let bytes: &[u8] = unsafe { mem::transmute(slice) };
|
||||||
|
w.write_all(bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const HAS_WRITE_SLICE: bool = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decode<'_> for bool {
|
impl Decode<'_> for bool {
|
||||||
|
@ -37,9 +40,11 @@ impl Encode for u8 {
|
||||||
Ok(w.write_u8(*self)?)
|
Ok(w.write_u8(*self)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encoded_len(&self) -> usize {
|
fn write_slice(slice: &[u8], mut w: impl Write) -> io::Result<()> {
|
||||||
1
|
w.write_all(slice)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const HAS_WRITE_SLICE: bool = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decode<'_> for u8 {
|
impl Decode<'_> for u8 {
|
||||||
|
@ -53,9 +58,15 @@ impl Encode for i8 {
|
||||||
Ok(w.write_i8(*self)?)
|
Ok(w.write_i8(*self)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encoded_len(&self) -> usize {
|
fn write_slice(slice: &[i8], mut w: impl Write) -> io::Result<()>
|
||||||
1
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
let bytes: &[u8] = unsafe { mem::transmute(slice) };
|
||||||
|
w.write_all(bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const HAS_WRITE_SLICE: bool = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decode<'_> for i8 {
|
impl Decode<'_> for i8 {
|
||||||
|
@ -68,10 +79,6 @@ impl Encode for u16 {
|
||||||
fn encode(&self, mut w: impl Write) -> Result<()> {
|
fn encode(&self, mut w: impl Write) -> Result<()> {
|
||||||
Ok(w.write_u16::<BigEndian>(*self)?)
|
Ok(w.write_u16::<BigEndian>(*self)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encoded_len(&self) -> usize {
|
|
||||||
2
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decode<'_> for u16 {
|
impl Decode<'_> for u16 {
|
||||||
|
@ -84,10 +91,6 @@ impl Encode for i16 {
|
||||||
fn encode(&self, mut w: impl Write) -> Result<()> {
|
fn encode(&self, mut w: impl Write) -> Result<()> {
|
||||||
Ok(w.write_i16::<BigEndian>(*self)?)
|
Ok(w.write_i16::<BigEndian>(*self)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encoded_len(&self) -> usize {
|
|
||||||
2
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decode<'_> for i16 {
|
impl Decode<'_> for i16 {
|
||||||
|
@ -100,10 +103,6 @@ impl Encode for u32 {
|
||||||
fn encode(&self, mut w: impl Write) -> Result<()> {
|
fn encode(&self, mut w: impl Write) -> Result<()> {
|
||||||
Ok(w.write_u32::<BigEndian>(*self)?)
|
Ok(w.write_u32::<BigEndian>(*self)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encoded_len(&self) -> usize {
|
|
||||||
4
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decode<'_> for u32 {
|
impl Decode<'_> for u32 {
|
||||||
|
@ -116,10 +115,6 @@ impl Encode for i32 {
|
||||||
fn encode(&self, mut w: impl Write) -> Result<()> {
|
fn encode(&self, mut w: impl Write) -> Result<()> {
|
||||||
Ok(w.write_i32::<BigEndian>(*self)?)
|
Ok(w.write_i32::<BigEndian>(*self)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encoded_len(&self) -> usize {
|
|
||||||
4
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decode<'_> for i32 {
|
impl Decode<'_> for i32 {
|
||||||
|
@ -132,10 +127,6 @@ impl Encode for u64 {
|
||||||
fn encode(&self, mut w: impl Write) -> Result<()> {
|
fn encode(&self, mut w: impl Write) -> Result<()> {
|
||||||
Ok(w.write_u64::<BigEndian>(*self)?)
|
Ok(w.write_u64::<BigEndian>(*self)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encoded_len(&self) -> usize {
|
|
||||||
8
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decode<'_> for u64 {
|
impl Decode<'_> for u64 {
|
||||||
|
@ -154,10 +145,6 @@ impl Encode for u128 {
|
||||||
fn encode(&self, mut w: impl Write) -> Result<()> {
|
fn encode(&self, mut w: impl Write) -> Result<()> {
|
||||||
Ok(w.write_u128::<BigEndian>(*self)?)
|
Ok(w.write_u128::<BigEndian>(*self)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encoded_len(&self) -> usize {
|
|
||||||
16
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decode<'_> for u128 {
|
impl Decode<'_> for u128 {
|
||||||
|
@ -170,10 +157,6 @@ impl Encode for i128 {
|
||||||
fn encode(&self, mut w: impl Write) -> Result<()> {
|
fn encode(&self, mut w: impl Write) -> Result<()> {
|
||||||
Ok(w.write_i128::<BigEndian>(*self)?)
|
Ok(w.write_i128::<BigEndian>(*self)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encoded_len(&self) -> usize {
|
|
||||||
16
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decode<'_> for i128 {
|
impl Decode<'_> for i128 {
|
||||||
|
@ -186,10 +169,6 @@ impl Encode for i64 {
|
||||||
fn encode(&self, mut w: impl Write) -> Result<()> {
|
fn encode(&self, mut w: impl Write) -> Result<()> {
|
||||||
Ok(w.write_i64::<BigEndian>(*self)?)
|
Ok(w.write_i64::<BigEndian>(*self)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encoded_len(&self) -> usize {
|
|
||||||
8
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Encode for f32 {
|
impl Encode for f32 {
|
||||||
|
@ -201,10 +180,6 @@ impl Encode for f32 {
|
||||||
);
|
);
|
||||||
Ok(w.write_f32::<BigEndian>(*self)?)
|
Ok(w.write_f32::<BigEndian>(*self)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encoded_len(&self) -> usize {
|
|
||||||
4
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decode<'_> for f32 {
|
impl Decode<'_> for f32 {
|
||||||
|
@ -224,10 +199,6 @@ impl Encode for f64 {
|
||||||
);
|
);
|
||||||
Ok(w.write_f64::<BigEndian>(*self)?)
|
Ok(w.write_f64::<BigEndian>(*self)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encoded_len(&self) -> usize {
|
|
||||||
8
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decode<'_> for f64 {
|
impl Decode<'_> for f64 {
|
||||||
|
@ -244,30 +215,18 @@ impl<T: Encode + ?Sized> Encode for &T {
|
||||||
fn encode(&self, w: impl Write) -> Result<()> {
|
fn encode(&self, w: impl Write) -> Result<()> {
|
||||||
(**self).encode(w)
|
(**self).encode(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encoded_len(&self) -> usize {
|
|
||||||
(**self).encoded_len()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Encode + ?Sized> Encode for &mut T {
|
impl<T: Encode + ?Sized> Encode for &mut T {
|
||||||
fn encode(&self, w: impl Write) -> Result<()> {
|
fn encode(&self, w: impl Write) -> Result<()> {
|
||||||
(**self).encode(w)
|
(**self).encode(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encoded_len(&self) -> usize {
|
|
||||||
(**self).encoded_len()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Encode + ?Sized> Encode for Box<T> {
|
impl<T: Encode + ?Sized> Encode for Box<T> {
|
||||||
fn encode(&self, w: impl Write) -> Result<()> {
|
fn encode(&self, w: impl Write) -> Result<()> {
|
||||||
self.as_ref().encode(w)
|
self.as_ref().encode(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encoded_len(&self) -> usize {
|
|
||||||
self.as_ref().encoded_len()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: Decode<'a>> Decode<'a> for Box<T> {
|
impl<'a, T: Decode<'a>> Decode<'a> for Box<T> {
|
||||||
|
@ -280,10 +239,6 @@ impl<T: Encode + ?Sized> Encode for Rc<T> {
|
||||||
fn encode(&self, w: impl Write) -> Result<()> {
|
fn encode(&self, w: impl Write) -> Result<()> {
|
||||||
self.as_ref().encode(w)
|
self.as_ref().encode(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encoded_len(&self) -> usize {
|
|
||||||
self.as_ref().encoded_len()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: Decode<'a>> Decode<'a> for Rc<T> {
|
impl<'a, T: Decode<'a>> Decode<'a> for Rc<T> {
|
||||||
|
@ -296,10 +251,6 @@ impl<T: Encode + ?Sized> Encode for Arc<T> {
|
||||||
fn encode(&self, w: impl Write) -> Result<()> {
|
fn encode(&self, w: impl Write) -> Result<()> {
|
||||||
self.as_ref().encode(w)
|
self.as_ref().encode(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encoded_len(&self) -> usize {
|
|
||||||
self.as_ref().encoded_len()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: Decode<'a>> Decode<'a> for Arc<T> {
|
impl<'a, T: Decode<'a>> Decode<'a> for Arc<T> {
|
||||||
|
@ -321,11 +272,6 @@ macro_rules! impl_tuple {
|
||||||
)*
|
)*
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encoded_len(&self) -> usize {
|
|
||||||
let ($($ty,)*) = self;
|
|
||||||
0 $(+ $ty.encoded_len())*
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, $($ty: Decode<'a>,)*> Decode<'a> for ($($ty,)*) {
|
impl<'a, $($ty: Decode<'a>,)*> Decode<'a> for ($($ty,)*) {
|
||||||
|
@ -355,28 +301,42 @@ impl_tuple!(A B C D E F G H I J K L);
|
||||||
/// Like tuples, arrays are encoded and decoded without a VarInt length prefix.
|
/// Like tuples, arrays are encoded and decoded without a VarInt length prefix.
|
||||||
impl<const N: usize, T: Encode> Encode for [T; N] {
|
impl<const N: usize, T: Encode> Encode for [T; N] {
|
||||||
fn encode(&self, mut w: impl Write) -> Result<()> {
|
fn encode(&self, mut w: impl Write) -> Result<()> {
|
||||||
|
if T::HAS_WRITE_SLICE {
|
||||||
|
return Ok(T::write_slice(self, w)?);
|
||||||
|
}
|
||||||
|
|
||||||
for t in self {
|
for t in self {
|
||||||
t.encode(&mut w)?;
|
t.encode(&mut w)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encoded_len(&self) -> usize {
|
|
||||||
self.iter().map(|t| t.encoded_len()).sum()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, const N: usize, T: Decode<'a>> Decode<'a> for [T; N] {
|
impl<'a, const N: usize, T: Decode<'a>> Decode<'a> for [T; N] {
|
||||||
fn decode(r: &mut &'a [u8]) -> Result<Self> {
|
fn decode(r: &mut &'a [u8]) -> Result<Self> {
|
||||||
// TODO: rewrite using std::array::try_from_fn when stabilized.
|
// TODO: rewrite using std::array::try_from_fn when stabilized?
|
||||||
|
// TODO: specialization for [f64; 3] improved performance.
|
||||||
|
|
||||||
let mut elems = ArrayVec::new();
|
let mut data: [MaybeUninit<T>; N] = unsafe { MaybeUninit::uninit().assume_init() };
|
||||||
for _ in 0..N {
|
|
||||||
elems.push(T::decode(r)?);
|
for (i, elem) in data.iter_mut().enumerate() {
|
||||||
|
match T::decode(r) {
|
||||||
|
Ok(val) => {
|
||||||
|
elem.write(val);
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
// Call destructors for values decoded so far.
|
||||||
|
for elem in &mut data[..i] {
|
||||||
|
unsafe { elem.assume_init_drop() };
|
||||||
|
}
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
elems.into_inner().map_err(|_| unreachable!())
|
// All values in `data` are initialized.
|
||||||
|
unsafe { Ok(mem::transmute_copy(&data)) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -404,17 +364,17 @@ impl<T: Encode> Encode for [T] {
|
||||||
);
|
);
|
||||||
|
|
||||||
VarInt(len as i32).encode(&mut w)?;
|
VarInt(len as i32).encode(&mut w)?;
|
||||||
|
|
||||||
|
if T::HAS_WRITE_SLICE {
|
||||||
|
return Ok(T::write_slice(self, w)?);
|
||||||
|
}
|
||||||
|
|
||||||
for t in self {
|
for t in self {
|
||||||
t.encode(&mut w)?;
|
t.encode(&mut w)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encoded_len(&self) -> usize {
|
|
||||||
let elems_len: usize = self.iter().map(|a| a.encoded_len()).sum();
|
|
||||||
VarInt(self.len().try_into().unwrap_or(i32::MAX)).encoded_len() + elems_len
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Decode<'a> for &'a [u8] {
|
impl<'a> Decode<'a> for &'a [u8] {
|
||||||
|
@ -430,14 +390,18 @@ impl<'a> Decode<'a> for &'a [u8] {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> Decode<'a> for &'a [i8] {
|
||||||
|
fn decode(r: &mut &'a [u8]) -> Result<Self> {
|
||||||
|
let unsigned_bytes = <&[u8]>::decode(r)?;
|
||||||
|
let signed_bytes: &[i8] = unsafe { mem::transmute(unsigned_bytes) };
|
||||||
|
Ok(signed_bytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: Encode> Encode for Vec<T> {
|
impl<T: Encode> Encode for Vec<T> {
|
||||||
fn encode(&self, w: impl Write) -> Result<()> {
|
fn encode(&self, w: impl Write) -> Result<()> {
|
||||||
self.as_slice().encode(w)
|
self.as_slice().encode(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encoded_len(&self) -> usize {
|
|
||||||
self.as_slice().encoded_len()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: Decode<'a>> Decode<'a> for Vec<T> {
|
impl<'a, T: Decode<'a>> Decode<'a> for Vec<T> {
|
||||||
|
@ -478,10 +442,6 @@ impl Encode for str {
|
||||||
VarInt(self.len() as i32).encode(&mut w)?;
|
VarInt(self.len() as i32).encode(&mut w)?;
|
||||||
Ok(w.write_all(self.as_bytes())?)
|
Ok(w.write_all(self.as_bytes())?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encoded_len(&self) -> usize {
|
|
||||||
VarInt(self.len().try_into().unwrap_or(i32::MAX)).encoded_len() + self.len()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Decode<'a> for &'a str {
|
impl<'a> Decode<'a> for &'a str {
|
||||||
|
@ -502,10 +462,6 @@ impl Encode for String {
|
||||||
fn encode(&self, w: impl Write) -> Result<()> {
|
fn encode(&self, w: impl Write) -> Result<()> {
|
||||||
self.as_str().encode(w)
|
self.as_str().encode(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encoded_len(&self) -> usize {
|
|
||||||
self.as_str().encoded_len()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decode<'_> for String {
|
impl Decode<'_> for String {
|
||||||
|
@ -532,10 +488,6 @@ impl<T: Encode> Encode for Option<T> {
|
||||||
None => false.encode(w),
|
None => false.encode(w),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encoded_len(&self) -> usize {
|
|
||||||
1 + self.as_ref().map_or(0, |t| t.encoded_len())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: Decode<'a>> Decode<'a> for Option<T> {
|
impl<'a, T: Decode<'a>> Decode<'a> for Option<T> {
|
||||||
|
@ -554,10 +506,6 @@ where
|
||||||
fn encode(&self, w: impl Write) -> Result<()> {
|
fn encode(&self, w: impl Write) -> Result<()> {
|
||||||
self.as_ref().encode(w)
|
self.as_ref().encode(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encoded_len(&self) -> usize {
|
|
||||||
self.as_ref().encoded_len()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, B> Decode<'a> for Cow<'a, B>
|
impl<'a, B> Decode<'a> for Cow<'a, B>
|
||||||
|
@ -574,10 +522,6 @@ impl Encode for Uuid {
|
||||||
fn encode(&self, w: impl Write) -> Result<()> {
|
fn encode(&self, w: impl Write) -> Result<()> {
|
||||||
self.as_u128().encode(w)
|
self.as_u128().encode(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encoded_len(&self) -> usize {
|
|
||||||
16
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Decode<'a> for Uuid {
|
impl<'a> Decode<'a> for Uuid {
|
||||||
|
@ -590,10 +534,6 @@ impl Encode for Compound {
|
||||||
fn encode(&self, w: impl Write) -> Result<()> {
|
fn encode(&self, w: impl Write) -> Result<()> {
|
||||||
Ok(valence_nbt::to_binary_writer(w, self, "")?)
|
Ok(valence_nbt::to_binary_writer(w, self, "")?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encoded_len(&self) -> usize {
|
|
||||||
self.binary_encoded_len("")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decode<'_> for Compound {
|
impl Decode<'_> for Compound {
|
||||||
|
|
|
@ -42,10 +42,6 @@ impl Encode for Option<ItemStack> {
|
||||||
fn encode(&self, w: impl Write) -> Result<()> {
|
fn encode(&self, w: impl Write) -> Result<()> {
|
||||||
self.as_ref().encode(w)
|
self.as_ref().encode(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encoded_len(&self) -> usize {
|
|
||||||
self.as_ref().encoded_len()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Encode for Option<&'a ItemStack> {
|
impl<'a> Encode for Option<&'a ItemStack> {
|
||||||
|
@ -63,17 +59,6 @@ impl<'a> Encode for Option<&'a ItemStack> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encoded_len(&self) -> usize {
|
|
||||||
match *self {
|
|
||||||
None => 1,
|
|
||||||
Some(s) => {
|
|
||||||
1 + s.item.encoded_len()
|
|
||||||
+ 1
|
|
||||||
+ s.nbt.as_ref().map(|nbt| nbt.encoded_len()).unwrap_or(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decode<'_> for Option<ItemStack> {
|
impl Decode<'_> for Option<ItemStack> {
|
||||||
|
@ -106,10 +91,6 @@ impl Encode for ItemKind {
|
||||||
fn encode(&self, w: impl Write) -> Result<()> {
|
fn encode(&self, w: impl Write) -> Result<()> {
|
||||||
VarInt(self.to_raw() as i32).encode(w)
|
VarInt(self.to_raw() as i32).encode(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encoded_len(&self) -> usize {
|
|
||||||
VarInt(self.to_raw() as i32).encoded_len()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decode<'_> for ItemKind {
|
impl Decode<'_> for ItemKind {
|
||||||
|
|
|
@ -44,7 +44,6 @@
|
||||||
//!
|
//!
|
||||||
//! TODO
|
//! TODO
|
||||||
|
|
||||||
#![forbid(unsafe_code)]
|
|
||||||
#![deny(
|
#![deny(
|
||||||
rustdoc::broken_intra_doc_links,
|
rustdoc::broken_intra_doc_links,
|
||||||
rustdoc::private_intra_doc_links,
|
rustdoc::private_intra_doc_links,
|
||||||
|
@ -69,6 +68,7 @@
|
||||||
// Allows us to use our own proc macros internally.
|
// Allows us to use our own proc macros internally.
|
||||||
extern crate self as valence_protocol;
|
extern crate self as valence_protocol;
|
||||||
|
|
||||||
|
use std::io;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
|
||||||
pub use anyhow::{Error, Result};
|
pub use anyhow::{Error, Result};
|
||||||
|
@ -84,13 +84,11 @@ pub use raw_bytes::RawBytes;
|
||||||
pub use text::{Text, TextFormat};
|
pub use text::{Text, TextFormat};
|
||||||
pub use username::Username;
|
pub use username::Username;
|
||||||
pub use uuid::Uuid;
|
pub use uuid::Uuid;
|
||||||
pub use valence_derive::{Decode, Encode, Packet};
|
pub use valence_derive::{Decode, DecodePacket, Encode, EncodePacket};
|
||||||
pub use var_int::VarInt;
|
pub use var_int::VarInt;
|
||||||
pub use var_long::VarLong;
|
pub use var_long::VarLong;
|
||||||
pub use {uuid, valence_nbt as nbt};
|
pub use {uuid, valence_nbt as nbt};
|
||||||
|
|
||||||
use crate::byte_counter::ByteCounter;
|
|
||||||
|
|
||||||
/// The Minecraft protocol version this library currently targets.
|
/// The Minecraft protocol version this library currently targets.
|
||||||
pub const PROTOCOL_VERSION: i32 = 760;
|
pub const PROTOCOL_VERSION: i32 = 760;
|
||||||
|
|
||||||
|
@ -103,7 +101,6 @@ pub mod block;
|
||||||
mod block_pos;
|
mod block_pos;
|
||||||
mod bounded;
|
mod bounded;
|
||||||
mod byte_angle;
|
mod byte_angle;
|
||||||
mod byte_counter;
|
|
||||||
mod codec;
|
mod codec;
|
||||||
pub mod enchant;
|
pub mod enchant;
|
||||||
pub mod entity_meta;
|
pub mod entity_meta;
|
||||||
|
@ -117,7 +114,7 @@ pub mod text;
|
||||||
pub mod translation_key;
|
pub mod translation_key;
|
||||||
pub mod types;
|
pub mod types;
|
||||||
pub mod username;
|
pub mod username;
|
||||||
mod var_int;
|
pub mod var_int;
|
||||||
mod var_long;
|
mod var_long;
|
||||||
|
|
||||||
/// Used only by proc macros. Not public API.
|
/// Used only by proc macros. Not public API.
|
||||||
|
@ -125,7 +122,7 @@ mod var_long;
|
||||||
pub mod __private {
|
pub mod __private {
|
||||||
pub use anyhow::{anyhow, bail, ensure, Context, Result};
|
pub use anyhow::{anyhow, bail, ensure, Context, Result};
|
||||||
|
|
||||||
pub use crate::{Decode, DerivedPacketDecode, DerivedPacketEncode, Encode, VarInt};
|
pub use crate::{Decode, DecodePacket, Encode, EncodePacket, VarInt};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The maximum number of bytes in a single Minecraft packet.
|
/// The maximum number of bytes in a single Minecraft packet.
|
||||||
|
@ -141,22 +138,15 @@ pub const MAX_PACKET_SIZE: i32 = 2097152;
|
||||||
/// implement `Encode`. Components are encoded in the order they appear in the
|
/// implement `Encode`. Components are encoded in the order they appear in the
|
||||||
/// type definition.
|
/// type definition.
|
||||||
///
|
///
|
||||||
/// If a `#[packet_id = ...]` attribute is present, encoding the type begins by
|
|
||||||
/// writing the specified constant [`VarInt`] value before any of the
|
|
||||||
/// components.
|
|
||||||
///
|
|
||||||
/// For enums, the variant to encode is marked by a leading [`VarInt`]
|
/// For enums, the variant to encode is marked by a leading [`VarInt`]
|
||||||
/// discriminant (tag). The discriminant value can be changed using the `#[tag =
|
/// discriminant (tag). The discriminant value can be changed using the `#[tag =
|
||||||
/// ...]` attribute on the variant in question. Discriminant values are assigned
|
/// ...]` attribute on the variant in question. Discriminant values are assigned
|
||||||
/// to variants using rules similar to regular enum discriminants.
|
/// to variants using rules similar to regular enum discriminants.
|
||||||
///
|
///
|
||||||
/// [`VarInt`]: var_int::VarInt
|
|
||||||
///
|
|
||||||
/// ```
|
/// ```
|
||||||
/// use valence_protocol::Encode;
|
/// use valence_protocol::Encode;
|
||||||
///
|
///
|
||||||
/// #[derive(Encode)]
|
/// #[derive(Encode)]
|
||||||
/// #[packet_id = 42]
|
|
||||||
/// struct MyStruct<'a> {
|
/// struct MyStruct<'a> {
|
||||||
/// first: i32,
|
/// first: i32,
|
||||||
/// second: &'a str,
|
/// second: &'a str,
|
||||||
|
@ -193,32 +183,22 @@ pub trait Encode {
|
||||||
/// the data that was written to the writer. The exact number of bytes
|
/// the data that was written to the writer. The exact number of bytes
|
||||||
/// that were originally written must be consumed during the decoding.
|
/// that were originally written must be consumed during the decoding.
|
||||||
///
|
///
|
||||||
/// Additionally, this function must be pure. If no write error occurs,
|
|
||||||
/// successive calls to `encode` must write the same bytes to the writer
|
|
||||||
/// argument. This property can be broken by using internal mutability,
|
|
||||||
/// global state, or other tricks.
|
|
||||||
///
|
|
||||||
/// [`decode`]: Decode::decode
|
/// [`decode`]: Decode::decode
|
||||||
fn encode(&self, w: impl Write) -> Result<()>;
|
fn encode(&self, w: impl Write) -> Result<()>;
|
||||||
|
|
||||||
/// Returns the number of bytes that will be written when [`Self::encode`]
|
/// Hack to get around the lack of specialization. Not public API.
|
||||||
/// is called.
|
#[doc(hidden)]
|
||||||
///
|
fn write_slice(slice: &[Self], w: impl Write) -> io::Result<()>
|
||||||
/// If [`Self::encode`] returns `Ok`, then the exact number of bytes
|
where
|
||||||
/// reported by this function must be written to the writer argument.
|
Self: Sized,
|
||||||
///
|
{
|
||||||
/// If the result is `Err`, then the number of written bytes must be less
|
let _ = (slice, w);
|
||||||
/// than or equal to the count returned by this function.
|
unimplemented!("for internal use in valence_protocol only")
|
||||||
///
|
|
||||||
/// # Default Implementation
|
|
||||||
///
|
|
||||||
/// Calls [`Self::encode`] to count the number of written bytes. This is
|
|
||||||
/// always correct, but is not always the most efficient approach.
|
|
||||||
fn encoded_len(&self) -> usize {
|
|
||||||
let mut counter = ByteCounter::new();
|
|
||||||
let _ = self.encode(&mut counter);
|
|
||||||
counter.0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Hack to get around the lack of specialization. Not public API.
|
||||||
|
#[doc(hidden)]
|
||||||
|
const HAS_WRITE_SLICE: bool = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The `Decode` trait allows objects to be read from the Minecraft protocol. It
|
/// The `Decode` trait allows objects to be read from the Minecraft protocol. It
|
||||||
|
@ -234,10 +214,6 @@ pub trait Encode {
|
||||||
/// implement `Decode`. Components are decoded in the order they appear in the
|
/// implement `Decode`. Components are decoded in the order they appear in the
|
||||||
/// type definition.
|
/// type definition.
|
||||||
///
|
///
|
||||||
/// If a `#[packet_id = ...]` attribute is present, encoding the type begins by
|
|
||||||
/// reading the specified constant [`VarInt`] value before any of the
|
|
||||||
/// components.
|
|
||||||
///
|
|
||||||
/// For enums, the variant to decode is determined by a leading [`VarInt`]
|
/// For enums, the variant to decode is determined by a leading [`VarInt`]
|
||||||
/// discriminant (tag). The discriminant value can be changed using the `#[tag =
|
/// discriminant (tag). The discriminant value can be changed using the `#[tag =
|
||||||
/// ...]` attribute on the variant in question. Discriminant values are assigned
|
/// ...]` attribute on the variant in question. Discriminant values are assigned
|
||||||
|
@ -247,7 +223,6 @@ pub trait Encode {
|
||||||
/// use valence_protocol::Decode;
|
/// use valence_protocol::Decode;
|
||||||
///
|
///
|
||||||
/// #[derive(PartialEq, Debug, Decode)]
|
/// #[derive(PartialEq, Debug, Decode)]
|
||||||
/// #[packet_id = 5]
|
|
||||||
/// struct MyStruct {
|
/// struct MyStruct {
|
||||||
/// first: i32,
|
/// first: i32,
|
||||||
/// second: MyEnum,
|
/// second: MyEnum,
|
||||||
|
@ -262,7 +237,7 @@ pub trait Encode {
|
||||||
/// Fourth, // tag = 26
|
/// Fourth, // tag = 26
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// let mut r: &[u8] = &[5, 0, 0, 0, 0, 26];
|
/// let mut r: &[u8] = &[0, 0, 0, 0, 26];
|
||||||
///
|
///
|
||||||
/// let value = MyStruct::decode(&mut r).unwrap();
|
/// let value = MyStruct::decode(&mut r).unwrap();
|
||||||
/// let expected = MyStruct {
|
/// let expected = MyStruct {
|
||||||
|
@ -283,60 +258,80 @@ pub trait Decode<'a>: Sized {
|
||||||
fn decode(r: &mut &'a [u8]) -> Result<Self>;
|
fn decode(r: &mut &'a [u8]) -> Result<Self>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Marker for types that are encoded or decoded as complete packets.
|
/// Like [`Encode`], but implementations must write a leading [`VarInt`] packet
|
||||||
|
/// ID before any other data.
|
||||||
///
|
///
|
||||||
/// A complete packet is data starting with a [`VarInt`] packet ID. [`Encode`]
|
/// # Deriving
|
||||||
/// and [`Decode`] implementations on `Self`, if present, are expected to handle
|
///
|
||||||
/// this leading `VarInt`.
|
/// This trait can be implemented automatically by using the
|
||||||
pub trait Packet {
|
/// [`EncodePacket`][macro] derive macro. The trait is implemented by writing
|
||||||
/// The name of this packet.
|
/// the packet ID provided in the `#[packet_id = ...]` helper attribute followed
|
||||||
///
|
/// by a call to [`Encode::encode`].
|
||||||
/// This is usually the name of the type representing the packet without any
|
///
|
||||||
/// generic parameters or other decorations.
|
/// ```
|
||||||
fn packet_name(&self) -> &'static str;
|
/// use valence_protocol::{Encode, EncodePacket};
|
||||||
|
///
|
||||||
|
/// #[derive(Encode, EncodePacket)]
|
||||||
|
/// #[packet_id = 42]
|
||||||
|
/// struct MyStruct {
|
||||||
|
/// first: i32,
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// let value = MyStruct { first: 123 };
|
||||||
|
/// let mut buf = vec![];
|
||||||
|
///
|
||||||
|
/// value.encode_packet(&mut buf).unwrap();
|
||||||
|
/// println!("{buf:?}");
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// [macro]: valence_derive::DecodePacket
|
||||||
|
pub trait EncodePacket {
|
||||||
|
/// The packet ID that is written when [`Self::encode_packet`] is called. A
|
||||||
|
/// negative value indicates that the packet ID is not statically known.
|
||||||
|
const PACKET_ID: i32 = -1;
|
||||||
|
|
||||||
|
/// Like [`Encode::encode`], but a leading [`VarInt`] packet ID must be
|
||||||
|
/// written first.
|
||||||
|
fn encode_packet(&self, w: impl Write) -> Result<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Packets which obtained [`Encode`] implementations via the [`Encode`][macro]
|
/// Like [`Decode`], but implementations must read a leading [`VarInt`] packet
|
||||||
/// derive macro with the `#[packet_id = ...]` attribute.
|
/// ID before any other data.
|
||||||
///
|
///
|
||||||
/// Along with [`DerivedPacketDecode`], this trait can be occasionally useful
|
/// # Deriving
|
||||||
/// for automating tasks such as defining large packet enums. Otherwise, this
|
|
||||||
/// trait should not be used and has thus been hidden from the documentation.
|
|
||||||
///
|
///
|
||||||
/// [macro]: valence_derive::Encode
|
/// This trait can be implemented automatically by using the
|
||||||
#[doc(hidden)]
|
/// [`DecodePacket`][macro] derive macro. The trait is implemented by reading
|
||||||
pub trait DerivedPacketEncode: Encode {
|
/// the packet ID provided in the `#[packet_id = ...]` helper attribute followed
|
||||||
/// The ID of this packet specified with `#[packet_id = ...]`.
|
/// by a call to [`Decode::decode`].
|
||||||
const ID: i32;
|
///
|
||||||
/// The name of the type implementing this trait.
|
/// ```
|
||||||
const NAME: &'static str;
|
/// use valence_protocol::{Decode, DecodePacket};
|
||||||
|
///
|
||||||
|
/// #[derive(Decode, DecodePacket)]
|
||||||
|
/// #[packet_id = 42]
|
||||||
|
/// struct MyStruct {
|
||||||
|
/// first: i32,
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// let buf = [42, 0, 0, 0, 0];
|
||||||
|
/// let mut r = buf.as_slice();
|
||||||
|
///
|
||||||
|
/// let value = MyStruct::decode_packet(&mut r).unwrap();
|
||||||
|
///
|
||||||
|
/// assert_eq!(value.first, 0);
|
||||||
|
/// assert!(r.is_empty());
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// [macro]: valence_protocol::DecodePacket
|
||||||
|
pub trait DecodePacket<'a>: Sized {
|
||||||
|
/// The packet ID that is read when [`Self::decode_packet`] is called. A
|
||||||
|
/// negative value indicates that the packet ID is not statically known.
|
||||||
|
const PACKET_ID: i32 = -1;
|
||||||
|
|
||||||
/// Like [`Encode::encode`], but does not write a leading [`VarInt`] packet
|
/// Like [`Decode::decode`], but a leading [`VarInt`] packet ID must be read
|
||||||
/// ID.
|
/// first.
|
||||||
fn encode_without_id(&self, w: impl Write) -> Result<()>;
|
fn decode_packet(r: &mut &'a [u8]) -> Result<Self>;
|
||||||
/// Like [`Encode::encoded_len`], but does not count a leading [`VarInt`]
|
|
||||||
/// packet ID.
|
|
||||||
fn encoded_len_without_id(&self) -> usize;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Packets which obtained [`Decode`] implementations via the [`Decode`][macro]
|
|
||||||
/// derive macro with the `#[packet_id = ...]` attribute.
|
|
||||||
///
|
|
||||||
/// Along with [`DerivedPacketEncode`], this trait can be occasionally useful
|
|
||||||
/// for automating tasks such as defining large packet enums. Otherwise, this
|
|
||||||
/// trait should not be used and has thus been hidden from the documentation.
|
|
||||||
///
|
|
||||||
/// [macro]: valence_derive::Decode
|
|
||||||
#[doc(hidden)]
|
|
||||||
pub trait DerivedPacketDecode<'a>: Decode<'a> {
|
|
||||||
/// The ID of this packet specified with `#[packet_id = ...]`.
|
|
||||||
const ID: i32;
|
|
||||||
/// The name of the type implementing this trait.
|
|
||||||
const NAME: &'static str;
|
|
||||||
|
|
||||||
/// Like [`Decode::decode`], but does not decode a leading [`VarInt`] packet
|
|
||||||
/// ID.
|
|
||||||
fn decode_without_id(r: &mut &'a [u8]) -> Result<Self>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
@ -344,7 +339,7 @@ pub trait DerivedPacketDecode<'a>: Decode<'a> {
|
||||||
mod derive_tests {
|
mod derive_tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[derive(Encode, Decode, Packet)]
|
#[derive(Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 1]
|
#[packet_id = 1]
|
||||||
struct RegularStruct {
|
struct RegularStruct {
|
||||||
foo: i32,
|
foo: i32,
|
||||||
|
@ -352,30 +347,30 @@ mod derive_tests {
|
||||||
baz: f64,
|
baz: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Encode, Decode, Packet)]
|
#[derive(Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 2]
|
#[packet_id = 2]
|
||||||
struct UnitStruct;
|
struct UnitStruct;
|
||||||
|
|
||||||
#[derive(Encode, Decode, Packet)]
|
#[derive(Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 3]
|
#[packet_id = 3]
|
||||||
struct EmptyStruct {}
|
struct EmptyStruct {}
|
||||||
|
|
||||||
#[derive(Encode, Decode, Packet)]
|
#[derive(Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 4]
|
#[packet_id = 4]
|
||||||
struct TupleStruct(i32, bool, f64);
|
struct TupleStruct(i32, bool, f64);
|
||||||
|
|
||||||
#[derive(Encode, Decode, Packet)]
|
#[derive(Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 5]
|
#[packet_id = 5]
|
||||||
struct StructWithGenerics<'z, T = ()> {
|
struct StructWithGenerics<'z, T = ()> {
|
||||||
foo: &'z str,
|
foo: &'z str,
|
||||||
bar: T,
|
bar: T,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Encode, Decode, Packet)]
|
#[derive(Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 6]
|
#[packet_id = 6]
|
||||||
struct TupleStructWithGenerics<'z, T = ()>(&'z str, i32, T);
|
struct TupleStructWithGenerics<'z, T = ()>(&'z str, i32, T);
|
||||||
|
|
||||||
#[derive(Encode, Decode, Packet)]
|
#[derive(Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 7]
|
#[packet_id = 7]
|
||||||
enum RegularEnum {
|
enum RegularEnum {
|
||||||
Empty,
|
Empty,
|
||||||
|
@ -383,11 +378,11 @@ mod derive_tests {
|
||||||
Fields { foo: i32, bar: bool, baz: f64 },
|
Fields { foo: i32, bar: bool, baz: f64 },
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Encode, Decode, Packet)]
|
#[derive(Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 8]
|
#[packet_id = 8]
|
||||||
enum EmptyEnum {}
|
enum EmptyEnum {}
|
||||||
|
|
||||||
#[derive(Encode, Decode, Packet)]
|
#[derive(Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0xbeef]
|
#[packet_id = 0xbeef]
|
||||||
enum EnumWithGenericsAndTags<'z, T = ()> {
|
enum EnumWithGenericsAndTags<'z, T = ()> {
|
||||||
#[tag = 5]
|
#[tag = 5]
|
||||||
|
@ -404,7 +399,7 @@ mod derive_tests {
|
||||||
#[allow(unconditional_recursion)]
|
#[allow(unconditional_recursion)]
|
||||||
fn has_impls<'a, T>()
|
fn has_impls<'a, T>()
|
||||||
where
|
where
|
||||||
T: Encode + Decode<'a> + DerivedPacketEncode + DerivedPacketDecode<'a> + Packet,
|
T: Encode + EncodePacket + Decode<'a> + DecodePacket<'a>,
|
||||||
{
|
{
|
||||||
has_impls::<RegularStruct>();
|
has_impls::<RegularStruct>();
|
||||||
has_impls::<UnitStruct>();
|
has_impls::<UnitStruct>();
|
||||||
|
|
|
@ -35,59 +35,38 @@ macro_rules! packet_enum {
|
||||||
}
|
}
|
||||||
)*
|
)*
|
||||||
|
|
||||||
impl<$enum_life> crate::Encode for $enum_name<$enum_life> {
|
impl<$enum_life> crate::EncodePacket for $enum_name<$enum_life> {
|
||||||
fn encode(&self, mut w: impl std::io::Write) -> crate::Result<()> {
|
fn encode_packet(&self, mut w: impl std::io::Write) -> crate::Result<()> {
|
||||||
use crate::DerivedPacketEncode;
|
use crate::{Encode, VarInt};
|
||||||
use crate::var_int::VarInt;
|
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
$(
|
$(
|
||||||
Self::$packet(pkt) => {
|
Self::$packet(pkt) => {
|
||||||
VarInt($packet::ID).encode(&mut w)?;
|
VarInt(<$packet as crate::EncodePacket>::PACKET_ID).encode(&mut w)?;
|
||||||
pkt.encode_without_id(w)?;
|
pkt.encode(w)?;
|
||||||
}
|
}
|
||||||
)*
|
)*
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encoded_len(&self) -> usize {
|
|
||||||
match self {
|
|
||||||
$(
|
|
||||||
Self::$packet(pkt) => {
|
|
||||||
pkt.encoded_len()
|
|
||||||
}
|
|
||||||
)*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<$enum_life> crate::Decode<$enum_life> for $enum_name<$enum_life> {
|
impl<$enum_life> crate::DecodePacket<$enum_life> for $enum_name<$enum_life> {
|
||||||
fn decode(r: &mut &$enum_life [u8]) -> crate::Result<Self> {
|
fn decode_packet(r: &mut &$enum_life [u8]) -> crate::Result<Self> {
|
||||||
use crate::DerivedPacketDecode;
|
use crate::{Decode, VarInt};
|
||||||
use crate::var_int::VarInt;
|
|
||||||
|
|
||||||
let id = VarInt::decode(r)?.0;
|
let id = VarInt::decode(r)?.0;
|
||||||
Ok(match id {
|
Ok(match id {
|
||||||
$(
|
$(
|
||||||
$packet::ID => Self::$packet($packet::decode_without_id(r)?),
|
<$packet as crate::DecodePacket>::PACKET_ID =>
|
||||||
|
Self::$packet($packet::decode(r)?),
|
||||||
)*
|
)*
|
||||||
id => anyhow::bail!("unknown packet id {}", id),
|
id => anyhow::bail!("unknown packet id {}", id),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<$enum_life> crate::Packet for $enum_name<$enum_life> {
|
|
||||||
fn packet_name(&self) -> &'static str {
|
|
||||||
match self {
|
|
||||||
$(
|
|
||||||
Self::$packet(pkt) => pkt.packet_name(),
|
|
||||||
)*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<$enum_life> std::fmt::Debug for $enum_name<$enum_life> {
|
impl<$enum_life> std::fmt::Debug for $enum_name<$enum_life> {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
|
@ -120,59 +99,38 @@ macro_rules! packet_enum {
|
||||||
}
|
}
|
||||||
)*
|
)*
|
||||||
|
|
||||||
impl crate::Encode for $enum_name {
|
impl crate::EncodePacket for $enum_name {
|
||||||
fn encode(&self, mut w: impl std::io::Write) -> crate::Result<()> {
|
fn encode_packet(&self, mut w: impl std::io::Write) -> crate::Result<()> {
|
||||||
use crate::DerivedPacketEncode;
|
use crate::{Encode, VarInt};
|
||||||
use crate::var_int::VarInt;
|
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
$(
|
$(
|
||||||
Self::$packet(pkt) => {
|
Self::$packet(pkt) => {
|
||||||
VarInt($packet::ID).encode(&mut w)?;
|
VarInt(<$packet as crate::EncodePacket>::PACKET_ID).encode(&mut w)?;
|
||||||
pkt.encode_without_id(w)?;
|
pkt.encode(w)?;
|
||||||
}
|
}
|
||||||
)*
|
)*
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encoded_len(&self) -> usize {
|
|
||||||
match self {
|
|
||||||
$(
|
|
||||||
Self::$packet(pkt) => {
|
|
||||||
pkt.encoded_len()
|
|
||||||
}
|
|
||||||
)*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl crate::Decode<'_> for $enum_name {
|
impl crate::DecodePacket<'_> for $enum_name {
|
||||||
fn decode(r: &mut &[u8]) -> crate::Result<Self> {
|
fn decode_packet(r: &mut &[u8]) -> crate::Result<Self> {
|
||||||
use crate::DerivedPacketDecode;
|
use crate::{Decode, VarInt};
|
||||||
use crate::var_int::VarInt;
|
|
||||||
|
|
||||||
let id = VarInt::decode(r)?.0;
|
let id = VarInt::decode(r)?.0;
|
||||||
Ok(match id {
|
Ok(match id {
|
||||||
$(
|
$(
|
||||||
$packet::ID => Self::$packet($packet::decode_without_id(r)?),
|
<$packet as crate::DecodePacket>::PACKET_ID =>
|
||||||
|
Self::$packet($packet::decode(r)?),
|
||||||
)*
|
)*
|
||||||
id => anyhow::bail!("unknown packet id {}", id),
|
id => anyhow::bail!("unknown packet id {}", id),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl crate::Packet for $enum_name {
|
|
||||||
fn packet_name(&self) -> &'static str {
|
|
||||||
match self {
|
|
||||||
$(
|
|
||||||
Self::$packet(pkt) => pkt.packet_name(),
|
|
||||||
)*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::fmt::Debug for $enum_name {
|
impl std::fmt::Debug for $enum_name {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
|
|
|
@ -15,12 +15,12 @@ use crate::types::{
|
||||||
use crate::username::Username;
|
use crate::username::Username;
|
||||||
use crate::var_int::VarInt;
|
use crate::var_int::VarInt;
|
||||||
use crate::var_long::VarLong;
|
use crate::var_long::VarLong;
|
||||||
use crate::{Decode, Encode, Packet};
|
use crate::{Decode, DecodePacket, Encode, EncodePacket};
|
||||||
|
|
||||||
pub mod handshake {
|
pub mod handshake {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x00]
|
#[packet_id = 0x00]
|
||||||
pub struct Handshake<'a> {
|
pub struct Handshake<'a> {
|
||||||
pub protocol_version: VarInt,
|
pub protocol_version: VarInt,
|
||||||
|
@ -29,7 +29,7 @@ pub mod handshake {
|
||||||
pub next_state: HandshakeNextState,
|
pub next_state: HandshakeNextState,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x00]
|
#[packet_id = 0x00]
|
||||||
pub struct HandshakeOwned {
|
pub struct HandshakeOwned {
|
||||||
pub protocol_version: VarInt,
|
pub protocol_version: VarInt,
|
||||||
|
@ -49,11 +49,11 @@ pub mod handshake {
|
||||||
pub mod status {
|
pub mod status {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x00]
|
#[packet_id = 0x00]
|
||||||
pub struct StatusRequest;
|
pub struct StatusRequest;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x01]
|
#[packet_id = 0x01]
|
||||||
pub struct PingRequest {
|
pub struct PingRequest {
|
||||||
pub payload: u64,
|
pub payload: u64,
|
||||||
|
@ -71,7 +71,7 @@ pub mod status {
|
||||||
pub mod login {
|
pub mod login {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x00]
|
#[packet_id = 0x00]
|
||||||
pub struct LoginStart<'a> {
|
pub struct LoginStart<'a> {
|
||||||
pub username: Username<&'a str>,
|
pub username: Username<&'a str>,
|
||||||
|
@ -79,14 +79,14 @@ pub mod login {
|
||||||
pub profile_id: Option<Uuid>,
|
pub profile_id: Option<Uuid>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x01]
|
#[packet_id = 0x01]
|
||||||
pub struct EncryptionResponse<'a> {
|
pub struct EncryptionResponse<'a> {
|
||||||
pub shared_secret: &'a [u8],
|
pub shared_secret: &'a [u8],
|
||||||
pub sig_or_token: MsgSigOrVerifyToken<'a>,
|
pub sig_or_token: MsgSigOrVerifyToken<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x02]
|
#[packet_id = 0x02]
|
||||||
pub struct LoginPluginResponse<'a> {
|
pub struct LoginPluginResponse<'a> {
|
||||||
pub message_id: VarInt,
|
pub message_id: VarInt,
|
||||||
|
@ -106,28 +106,28 @@ pub mod login {
|
||||||
pub mod play {
|
pub mod play {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x00]
|
#[packet_id = 0x00]
|
||||||
pub struct ConfirmTeleport {
|
pub struct ConfirmTeleport {
|
||||||
pub teleport_id: VarInt,
|
pub teleport_id: VarInt,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x01]
|
#[packet_id = 0x01]
|
||||||
pub struct QueryBlockEntityTag {
|
pub struct QueryBlockEntityTag {
|
||||||
pub transaction_id: VarInt,
|
pub transaction_id: VarInt,
|
||||||
pub position: BlockPos,
|
pub position: BlockPos,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x02]
|
#[packet_id = 0x02]
|
||||||
pub struct ChangeDifficulty(pub Difficulty);
|
pub struct ChangeDifficulty(pub Difficulty);
|
||||||
|
|
||||||
#[derive(Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x03]
|
#[packet_id = 0x03]
|
||||||
pub struct MessageAcknowledgmentC2s<'a>(pub MessageAcknowledgment<'a>);
|
pub struct MessageAcknowledgmentC2s<'a>(pub MessageAcknowledgment<'a>);
|
||||||
|
|
||||||
#[derive(Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x04]
|
#[packet_id = 0x04]
|
||||||
pub struct ChatCommand<'a> {
|
pub struct ChatCommand<'a> {
|
||||||
pub command: &'a str,
|
pub command: &'a str,
|
||||||
|
@ -138,7 +138,7 @@ pub mod play {
|
||||||
pub acknowledgement: MessageAcknowledgment<'a>,
|
pub acknowledgement: MessageAcknowledgment<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x05]
|
#[packet_id = 0x05]
|
||||||
pub struct ChatMessage<'a> {
|
pub struct ChatMessage<'a> {
|
||||||
pub message: &'a str,
|
pub message: &'a str,
|
||||||
|
@ -149,20 +149,20 @@ pub mod play {
|
||||||
pub acknowledgement: MessageAcknowledgment<'a>,
|
pub acknowledgement: MessageAcknowledgment<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x06]
|
#[packet_id = 0x06]
|
||||||
pub struct ChatPreviewC2s {
|
pub struct ChatPreviewC2s {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x07]
|
#[packet_id = 0x07]
|
||||||
pub enum ClientCommand {
|
pub enum ClientCommand {
|
||||||
PerformRespawn,
|
PerformRespawn,
|
||||||
RequestStats,
|
RequestStats,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x08]
|
#[packet_id = 0x08]
|
||||||
pub struct ClientInformation<'a> {
|
pub struct ClientInformation<'a> {
|
||||||
pub locale: &'a str,
|
pub locale: &'a str,
|
||||||
|
@ -175,21 +175,21 @@ pub mod play {
|
||||||
pub allow_server_listings: bool,
|
pub allow_server_listings: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x09]
|
#[packet_id = 0x09]
|
||||||
pub struct CommandSuggestionsRequest<'a> {
|
pub struct CommandSuggestionsRequest<'a> {
|
||||||
pub transaction_id: VarInt,
|
pub transaction_id: VarInt,
|
||||||
pub text: &'a str,
|
pub text: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x0a]
|
#[packet_id = 0x0a]
|
||||||
pub struct ClickContainerButton {
|
pub struct ClickContainerButton {
|
||||||
pub window_id: i8,
|
pub window_id: i8,
|
||||||
pub button_id: i8,
|
pub button_id: i8,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x0b]
|
#[packet_id = 0x0b]
|
||||||
pub struct ClickContainer {
|
pub struct ClickContainer {
|
||||||
pub window_id: u8,
|
pub window_id: u8,
|
||||||
|
@ -201,20 +201,20 @@ pub mod play {
|
||||||
pub carried_item: Option<ItemStack>,
|
pub carried_item: Option<ItemStack>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x0c]
|
#[packet_id = 0x0c]
|
||||||
pub struct CloseContainerC2s {
|
pub struct CloseContainerC2s {
|
||||||
pub window_id: i8,
|
pub window_id: i8,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x0d]
|
#[packet_id = 0x0d]
|
||||||
pub struct PluginMessageC2s<'a> {
|
pub struct PluginMessageC2s<'a> {
|
||||||
pub channel: Ident<&'a str>,
|
pub channel: Ident<&'a str>,
|
||||||
pub data: RawBytes<'a>,
|
pub data: RawBytes<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x0e]
|
#[packet_id = 0x0e]
|
||||||
pub struct EditBook<'a> {
|
pub struct EditBook<'a> {
|
||||||
pub slot: VarInt,
|
pub slot: VarInt,
|
||||||
|
@ -222,14 +222,14 @@ pub mod play {
|
||||||
pub title: Option<&'a str>,
|
pub title: Option<&'a str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x0f]
|
#[packet_id = 0x0f]
|
||||||
pub struct QueryEntityTag {
|
pub struct QueryEntityTag {
|
||||||
pub transaction_id: VarInt,
|
pub transaction_id: VarInt,
|
||||||
pub entity_id: VarInt,
|
pub entity_id: VarInt,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x10]
|
#[packet_id = 0x10]
|
||||||
pub struct Interact {
|
pub struct Interact {
|
||||||
pub entity_id: VarInt,
|
pub entity_id: VarInt,
|
||||||
|
@ -237,7 +237,7 @@ pub mod play {
|
||||||
pub sneaking: bool,
|
pub sneaking: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x11]
|
#[packet_id = 0x11]
|
||||||
pub struct JigsawGenerate {
|
pub struct JigsawGenerate {
|
||||||
pub position: BlockPos,
|
pub position: BlockPos,
|
||||||
|
@ -245,24 +245,24 @@ pub mod play {
|
||||||
pub keep_jigsaws: bool,
|
pub keep_jigsaws: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x12]
|
#[packet_id = 0x12]
|
||||||
pub struct KeepAliveC2s {
|
pub struct KeepAliveC2s {
|
||||||
pub id: u64,
|
pub id: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x13]
|
#[packet_id = 0x13]
|
||||||
pub struct LockDifficulty(pub bool);
|
pub struct LockDifficulty(pub bool);
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x14]
|
#[packet_id = 0x14]
|
||||||
pub struct SetPlayerPosition {
|
pub struct SetPlayerPosition {
|
||||||
pub position: [f64; 3],
|
pub position: [f64; 3],
|
||||||
pub on_ground: bool,
|
pub on_ground: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x15]
|
#[packet_id = 0x15]
|
||||||
pub struct SetPlayerPositionAndRotation {
|
pub struct SetPlayerPositionAndRotation {
|
||||||
pub position: [f64; 3],
|
pub position: [f64; 3],
|
||||||
|
@ -271,7 +271,7 @@ pub mod play {
|
||||||
pub on_ground: bool,
|
pub on_ground: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x16]
|
#[packet_id = 0x16]
|
||||||
pub struct SetPlayerRotation {
|
pub struct SetPlayerRotation {
|
||||||
pub yaw: f32,
|
pub yaw: f32,
|
||||||
|
@ -279,11 +279,11 @@ pub mod play {
|
||||||
pub on_ground: bool,
|
pub on_ground: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x17]
|
#[packet_id = 0x17]
|
||||||
pub struct SetPlayerOnGround(pub bool);
|
pub struct SetPlayerOnGround(pub bool);
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x18]
|
#[packet_id = 0x18]
|
||||||
pub struct MoveVehicleC2s {
|
pub struct MoveVehicleC2s {
|
||||||
pub position: [f64; 3],
|
pub position: [f64; 3],
|
||||||
|
@ -291,20 +291,20 @@ pub mod play {
|
||||||
pub pitch: f32,
|
pub pitch: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x19]
|
#[packet_id = 0x19]
|
||||||
pub struct PaddleBoat {
|
pub struct PaddleBoat {
|
||||||
pub left_paddle_turning: bool,
|
pub left_paddle_turning: bool,
|
||||||
pub right_paddle_turning: bool,
|
pub right_paddle_turning: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x1a]
|
#[packet_id = 0x1a]
|
||||||
pub struct PickItem {
|
pub struct PickItem {
|
||||||
pub slot_to_use: VarInt,
|
pub slot_to_use: VarInt,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x1b]
|
#[packet_id = 0x1b]
|
||||||
pub struct PlaceRecipe<'a> {
|
pub struct PlaceRecipe<'a> {
|
||||||
pub window_id: i8,
|
pub window_id: i8,
|
||||||
|
@ -312,7 +312,7 @@ pub mod play {
|
||||||
pub make_all: bool,
|
pub make_all: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x1c]
|
#[packet_id = 0x1c]
|
||||||
pub enum PlayerAbilitiesC2s {
|
pub enum PlayerAbilitiesC2s {
|
||||||
#[tag = 0b00]
|
#[tag = 0b00]
|
||||||
|
@ -321,7 +321,7 @@ pub mod play {
|
||||||
StartFlying,
|
StartFlying,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x1d]
|
#[packet_id = 0x1d]
|
||||||
pub struct PlayerAction {
|
pub struct PlayerAction {
|
||||||
pub status: DiggingStatus,
|
pub status: DiggingStatus,
|
||||||
|
@ -330,7 +330,7 @@ pub mod play {
|
||||||
pub sequence: VarInt,
|
pub sequence: VarInt,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x1e]
|
#[packet_id = 0x1e]
|
||||||
pub struct PlayerCommand {
|
pub struct PlayerCommand {
|
||||||
pub entity_id: VarInt,
|
pub entity_id: VarInt,
|
||||||
|
@ -338,7 +338,7 @@ pub mod play {
|
||||||
pub jump_boost: VarInt,
|
pub jump_boost: VarInt,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x1f]
|
#[packet_id = 0x1f]
|
||||||
pub struct PlayerInput {
|
pub struct PlayerInput {
|
||||||
pub sideways: f32,
|
pub sideways: f32,
|
||||||
|
@ -346,13 +346,13 @@ pub mod play {
|
||||||
pub flags: PlayerInputFlags,
|
pub flags: PlayerInputFlags,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x20]
|
#[packet_id = 0x20]
|
||||||
pub struct PongPlay {
|
pub struct PongPlay {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x21]
|
#[packet_id = 0x21]
|
||||||
pub struct ChangeRecipeBookSettings {
|
pub struct ChangeRecipeBookSettings {
|
||||||
pub book_id: RecipeBookId,
|
pub book_id: RecipeBookId,
|
||||||
|
@ -360,19 +360,19 @@ pub mod play {
|
||||||
pub filter_active: bool,
|
pub filter_active: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x22]
|
#[packet_id = 0x22]
|
||||||
pub struct SetSeenRecipe<'a> {
|
pub struct SetSeenRecipe<'a> {
|
||||||
pub recipe_id: Ident<&'a str>,
|
pub recipe_id: Ident<&'a str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x23]
|
#[packet_id = 0x23]
|
||||||
pub struct RenameItem<'a> {
|
pub struct RenameItem<'a> {
|
||||||
pub item_name: &'a str,
|
pub item_name: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x24]
|
#[packet_id = 0x24]
|
||||||
pub enum ResourcePackC2s {
|
pub enum ResourcePackC2s {
|
||||||
SuccessfullyLoaded,
|
SuccessfullyLoaded,
|
||||||
|
@ -381,33 +381,33 @@ pub mod play {
|
||||||
Accepted,
|
Accepted,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x25]
|
#[packet_id = 0x25]
|
||||||
pub enum SeenAdvancements<'a> {
|
pub enum SeenAdvancements<'a> {
|
||||||
OpenedTab { tab_id: Ident<&'a str> },
|
OpenedTab { tab_id: Ident<&'a str> },
|
||||||
ClosedScreen,
|
ClosedScreen,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x26]
|
#[packet_id = 0x26]
|
||||||
pub struct SelectTrade {
|
pub struct SelectTrade {
|
||||||
pub selected_slot: VarInt,
|
pub selected_slot: VarInt,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x27]
|
#[packet_id = 0x27]
|
||||||
pub struct SetBeaconEffect {
|
pub struct SetBeaconEffect {
|
||||||
pub primary_effect: Option<VarInt>,
|
pub primary_effect: Option<VarInt>,
|
||||||
pub secondary_effect: Option<VarInt>,
|
pub secondary_effect: Option<VarInt>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x28]
|
#[packet_id = 0x28]
|
||||||
pub struct SetHeldItemC2s {
|
pub struct SetHeldItemC2s {
|
||||||
pub slot: i16,
|
pub slot: i16,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x29]
|
#[packet_id = 0x29]
|
||||||
pub struct ProgramCommandBlock<'a> {
|
pub struct ProgramCommandBlock<'a> {
|
||||||
pub position: BlockPos,
|
pub position: BlockPos,
|
||||||
|
@ -416,7 +416,7 @@ pub mod play {
|
||||||
pub flags: CommandBlockFlags,
|
pub flags: CommandBlockFlags,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x2a]
|
#[packet_id = 0x2a]
|
||||||
pub struct ProgramCommandBlockMinecart<'a> {
|
pub struct ProgramCommandBlockMinecart<'a> {
|
||||||
pub entity_id: VarInt,
|
pub entity_id: VarInt,
|
||||||
|
@ -424,14 +424,14 @@ pub mod play {
|
||||||
pub track_output: bool,
|
pub track_output: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x2b]
|
#[packet_id = 0x2b]
|
||||||
pub struct SetCreativeModeSlot {
|
pub struct SetCreativeModeSlot {
|
||||||
pub slot: i16,
|
pub slot: i16,
|
||||||
pub clicked_item: Option<ItemStack>,
|
pub clicked_item: Option<ItemStack>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x2c]
|
#[packet_id = 0x2c]
|
||||||
pub struct ProgramJigsawBlock<'a> {
|
pub struct ProgramJigsawBlock<'a> {
|
||||||
pub position: BlockPos,
|
pub position: BlockPos,
|
||||||
|
@ -442,7 +442,7 @@ pub mod play {
|
||||||
pub joint_type: &'a str,
|
pub joint_type: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x2d]
|
#[packet_id = 0x2d]
|
||||||
pub struct ProgramStructureBlock<'a> {
|
pub struct ProgramStructureBlock<'a> {
|
||||||
pub position: BlockPos,
|
pub position: BlockPos,
|
||||||
|
@ -459,24 +459,24 @@ pub mod play {
|
||||||
pub flags: StructureBlockFlags,
|
pub flags: StructureBlockFlags,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x2e]
|
#[packet_id = 0x2e]
|
||||||
pub struct UpdateSign<'a> {
|
pub struct UpdateSign<'a> {
|
||||||
pub position: BlockPos,
|
pub position: BlockPos,
|
||||||
pub lines: [&'a str; 4],
|
pub lines: [&'a str; 4],
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x2f]
|
#[packet_id = 0x2f]
|
||||||
pub struct SwingArm(pub Hand);
|
pub struct SwingArm(pub Hand);
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x30]
|
#[packet_id = 0x30]
|
||||||
pub struct TeleportToEntity {
|
pub struct TeleportToEntity {
|
||||||
pub target: Uuid,
|
pub target: Uuid,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x31]
|
#[packet_id = 0x31]
|
||||||
pub struct UseItemOn {
|
pub struct UseItemOn {
|
||||||
pub hand: Hand,
|
pub hand: Hand,
|
||||||
|
@ -487,7 +487,7 @@ pub mod play {
|
||||||
pub sequence: VarInt,
|
pub sequence: VarInt,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x32]
|
#[packet_id = 0x32]
|
||||||
pub struct UseItem {
|
pub struct UseItem {
|
||||||
pub hand: Hand,
|
pub hand: Hand,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
use valence_derive::{Decode, Encode, Packet};
|
use valence_derive::{Decode, DecodePacket, Encode, EncodePacket};
|
||||||
use valence_nbt::Compound;
|
use valence_nbt::Compound;
|
||||||
|
|
||||||
use crate::block_pos::BlockPos;
|
use crate::block_pos::BlockPos;
|
||||||
|
@ -21,13 +21,13 @@ use crate::LengthPrefixedArray;
|
||||||
pub mod status {
|
pub mod status {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x00]
|
#[packet_id = 0x00]
|
||||||
pub struct StatusResponse<'a> {
|
pub struct StatusResponse<'a> {
|
||||||
pub json: &'a str,
|
pub json: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x01]
|
#[packet_id = 0x01]
|
||||||
pub struct PingResponse {
|
pub struct PingResponse {
|
||||||
pub payload: u64,
|
pub payload: u64,
|
||||||
|
@ -45,13 +45,13 @@ pub mod status {
|
||||||
pub mod login {
|
pub mod login {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x00]
|
#[packet_id = 0x00]
|
||||||
pub struct DisconnectLogin {
|
pub struct DisconnectLogin {
|
||||||
pub reason: Text,
|
pub reason: Text,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x01]
|
#[packet_id = 0x01]
|
||||||
pub struct EncryptionRequest<'a> {
|
pub struct EncryptionRequest<'a> {
|
||||||
pub server_id: &'a str,
|
pub server_id: &'a str,
|
||||||
|
@ -59,7 +59,7 @@ pub mod login {
|
||||||
pub verify_token: &'a [u8],
|
pub verify_token: &'a [u8],
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x02]
|
#[packet_id = 0x02]
|
||||||
pub struct LoginSuccess<'a> {
|
pub struct LoginSuccess<'a> {
|
||||||
pub uuid: Uuid,
|
pub uuid: Uuid,
|
||||||
|
@ -67,13 +67,13 @@ pub mod login {
|
||||||
pub properties: Vec<SignedProperty<'a>>,
|
pub properties: Vec<SignedProperty<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x03]
|
#[packet_id = 0x03]
|
||||||
pub struct SetCompression {
|
pub struct SetCompression {
|
||||||
pub threshold: VarInt,
|
pub threshold: VarInt,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x04]
|
#[packet_id = 0x04]
|
||||||
pub struct LoginPluginRequest<'a> {
|
pub struct LoginPluginRequest<'a> {
|
||||||
pub message_id: VarInt,
|
pub message_id: VarInt,
|
||||||
|
@ -96,7 +96,7 @@ pub mod login {
|
||||||
pub mod play {
|
pub mod play {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x00]
|
#[packet_id = 0x00]
|
||||||
pub struct SpawnEntity {
|
pub struct SpawnEntity {
|
||||||
pub entity_id: VarInt,
|
pub entity_id: VarInt,
|
||||||
|
@ -111,7 +111,7 @@ pub mod play {
|
||||||
pub velocity: [i16; 3],
|
pub velocity: [i16; 3],
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x01]
|
#[packet_id = 0x01]
|
||||||
pub struct SpawnExperienceOrb {
|
pub struct SpawnExperienceOrb {
|
||||||
pub entity_id: VarInt,
|
pub entity_id: VarInt,
|
||||||
|
@ -119,7 +119,7 @@ pub mod play {
|
||||||
pub count: i16,
|
pub count: i16,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x02]
|
#[packet_id = 0x02]
|
||||||
pub struct SpawnPlayer {
|
pub struct SpawnPlayer {
|
||||||
pub entity_id: VarInt,
|
pub entity_id: VarInt,
|
||||||
|
@ -129,20 +129,20 @@ pub mod play {
|
||||||
pub pitch: ByteAngle,
|
pub pitch: ByteAngle,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x03]
|
#[packet_id = 0x03]
|
||||||
pub struct EntityAnimationS2c {
|
pub struct EntityAnimationS2c {
|
||||||
pub entity_id: VarInt,
|
pub entity_id: VarInt,
|
||||||
pub animation: u8, // TODO: use Animation enum.
|
pub animation: u8, // TODO: use Animation enum.
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x05]
|
#[packet_id = 0x05]
|
||||||
pub struct AcknowledgeBlockChange {
|
pub struct AcknowledgeBlockChange {
|
||||||
pub sequence: VarInt,
|
pub sequence: VarInt,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x06]
|
#[packet_id = 0x06]
|
||||||
pub struct SetBlockDestroyStage {
|
pub struct SetBlockDestroyStage {
|
||||||
pub entity_id: VarInt,
|
pub entity_id: VarInt,
|
||||||
|
@ -150,7 +150,7 @@ pub mod play {
|
||||||
pub destroy_stage: u8,
|
pub destroy_stage: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x07]
|
#[packet_id = 0x07]
|
||||||
pub struct BlockEntityData {
|
pub struct BlockEntityData {
|
||||||
pub position: BlockPos,
|
pub position: BlockPos,
|
||||||
|
@ -159,41 +159,41 @@ pub mod play {
|
||||||
pub data: Compound,
|
pub data: Compound,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x09]
|
#[packet_id = 0x09]
|
||||||
pub struct BlockUpdate {
|
pub struct BlockUpdate {
|
||||||
pub position: BlockPos,
|
pub position: BlockPos,
|
||||||
pub block_id: VarInt,
|
pub block_id: VarInt,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x0a]
|
#[packet_id = 0x0a]
|
||||||
pub struct BossBar {
|
pub struct BossBar {
|
||||||
pub id: Uuid,
|
pub id: Uuid,
|
||||||
pub action: BossBarAction,
|
pub action: BossBarAction,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x0b]
|
#[packet_id = 0x0b]
|
||||||
pub struct SetDifficulty {
|
pub struct SetDifficulty {
|
||||||
pub difficulty: Difficulty,
|
pub difficulty: Difficulty,
|
||||||
pub locked: bool,
|
pub locked: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x0d]
|
#[packet_id = 0x0d]
|
||||||
pub struct ClearTitles {
|
pub struct ClearTitles {
|
||||||
pub reset: bool,
|
pub reset: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x10]
|
#[packet_id = 0x10]
|
||||||
pub struct CloseContainerS2c {
|
pub struct CloseContainerS2c {
|
||||||
/// Ignored by notchian clients.
|
/// Ignored by notchian clients.
|
||||||
pub window_id: u8,
|
pub window_id: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x11]
|
#[packet_id = 0x11]
|
||||||
pub struct SetContainerContent {
|
pub struct SetContainerContent {
|
||||||
pub window_id: u8,
|
pub window_id: u8,
|
||||||
|
@ -202,7 +202,7 @@ pub mod play {
|
||||||
pub carried_item: Option<ItemStack>,
|
pub carried_item: Option<ItemStack>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket)]
|
||||||
#[packet_id = 0x11]
|
#[packet_id = 0x11]
|
||||||
pub struct SetContainerContentEncode<'a> {
|
pub struct SetContainerContentEncode<'a> {
|
||||||
pub window_id: u8,
|
pub window_id: u8,
|
||||||
|
@ -211,7 +211,7 @@ pub mod play {
|
||||||
pub carried_item: &'a Option<ItemStack>,
|
pub carried_item: &'a Option<ItemStack>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x12]
|
#[packet_id = 0x12]
|
||||||
pub struct SetContainerProperty {
|
pub struct SetContainerProperty {
|
||||||
pub window_id: u8,
|
pub window_id: u8,
|
||||||
|
@ -219,7 +219,7 @@ pub mod play {
|
||||||
pub value: i16,
|
pub value: i16,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x13]
|
#[packet_id = 0x13]
|
||||||
pub struct SetContainerSlot {
|
pub struct SetContainerSlot {
|
||||||
pub window_id: i8,
|
pub window_id: i8,
|
||||||
|
@ -228,7 +228,7 @@ pub mod play {
|
||||||
pub slot_data: Option<ItemStack>,
|
pub slot_data: Option<ItemStack>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Encode, Packet)]
|
#[derive(Clone, Debug, Encode, EncodePacket)]
|
||||||
#[packet_id = 0x13]
|
#[packet_id = 0x13]
|
||||||
pub struct SetContainerSlotEncode<'a> {
|
pub struct SetContainerSlotEncode<'a> {
|
||||||
pub window_id: i8,
|
pub window_id: i8,
|
||||||
|
@ -237,21 +237,21 @@ pub mod play {
|
||||||
pub slot_data: Option<&'a ItemStack>,
|
pub slot_data: Option<&'a ItemStack>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x14]
|
#[packet_id = 0x14]
|
||||||
pub struct SetCooldown {
|
pub struct SetCooldown {
|
||||||
pub item_id: VarInt,
|
pub item_id: VarInt,
|
||||||
pub cooldown_ticks: VarInt,
|
pub cooldown_ticks: VarInt,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x16]
|
#[packet_id = 0x16]
|
||||||
pub struct PluginMessageS2c<'a> {
|
pub struct PluginMessageS2c<'a> {
|
||||||
pub channel: Ident<&'a str>,
|
pub channel: Ident<&'a str>,
|
||||||
pub data: RawBytes<'a>,
|
pub data: RawBytes<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x17]
|
#[packet_id = 0x17]
|
||||||
pub struct CustomSoundEffect<'a> {
|
pub struct CustomSoundEffect<'a> {
|
||||||
pub name: Ident<&'a str>,
|
pub name: Ident<&'a str>,
|
||||||
|
@ -262,34 +262,34 @@ pub mod play {
|
||||||
pub seed: u64,
|
pub seed: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x19]
|
#[packet_id = 0x19]
|
||||||
pub struct DisconnectPlay {
|
pub struct DisconnectPlay {
|
||||||
pub reason: Text,
|
pub reason: Text,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x1a]
|
#[packet_id = 0x1a]
|
||||||
pub struct EntityEvent {
|
pub struct EntityEvent {
|
||||||
pub entity_id: i32,
|
pub entity_id: i32,
|
||||||
pub entity_status: u8,
|
pub entity_status: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x1c]
|
#[packet_id = 0x1c]
|
||||||
pub struct UnloadChunk {
|
pub struct UnloadChunk {
|
||||||
pub chunk_x: i32,
|
pub chunk_x: i32,
|
||||||
pub chunk_z: i32,
|
pub chunk_z: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x1d]
|
#[packet_id = 0x1d]
|
||||||
pub struct GameEvent {
|
pub struct GameEvent {
|
||||||
pub reason: GameStateChangeReason,
|
pub reason: GameStateChangeReason,
|
||||||
pub value: f32,
|
pub value: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x1f]
|
#[packet_id = 0x1f]
|
||||||
pub struct WorldBorderInitialize {
|
pub struct WorldBorderInitialize {
|
||||||
pub x: f64,
|
pub x: f64,
|
||||||
|
@ -302,13 +302,13 @@ pub mod play {
|
||||||
pub warning_time: VarInt,
|
pub warning_time: VarInt,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x20]
|
#[packet_id = 0x20]
|
||||||
pub struct KeepAliveS2c {
|
pub struct KeepAliveS2c {
|
||||||
pub id: u64,
|
pub id: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x21]
|
#[packet_id = 0x21]
|
||||||
pub struct ChunkDataAndUpdateLight<'a> {
|
pub struct ChunkDataAndUpdateLight<'a> {
|
||||||
pub chunk_x: i32,
|
pub chunk_x: i32,
|
||||||
|
@ -325,7 +325,7 @@ pub mod play {
|
||||||
pub block_light_arrays: Vec<LengthPrefixedArray<u8, 2048>>,
|
pub block_light_arrays: Vec<LengthPrefixedArray<u8, 2048>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Encode, Packet)]
|
#[derive(Clone, Debug, Encode, EncodePacket)]
|
||||||
#[packet_id = 0x21]
|
#[packet_id = 0x21]
|
||||||
pub struct ChunkDataAndUpdateLightEncode<'a> {
|
pub struct ChunkDataAndUpdateLightEncode<'a> {
|
||||||
pub chunk_x: i32,
|
pub chunk_x: i32,
|
||||||
|
@ -342,7 +342,7 @@ pub mod play {
|
||||||
pub block_light_arrays: &'a [LengthPrefixedArray<u8, 2048>],
|
pub block_light_arrays: &'a [LengthPrefixedArray<u8, 2048>],
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x23]
|
#[packet_id = 0x23]
|
||||||
pub struct ParticleS2c<'a> {
|
pub struct ParticleS2c<'a> {
|
||||||
pub particle_id: VarInt,
|
pub particle_id: VarInt,
|
||||||
|
@ -354,7 +354,7 @@ pub mod play {
|
||||||
pub data: RawBytes<'a>,
|
pub data: RawBytes<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x25]
|
#[packet_id = 0x25]
|
||||||
pub struct LoginPlay<'a> {
|
pub struct LoginPlay<'a> {
|
||||||
pub entity_id: i32,
|
pub entity_id: i32,
|
||||||
|
@ -378,7 +378,7 @@ pub mod play {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: remove this.
|
// TODO: remove this.
|
||||||
#[derive(Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x25]
|
#[packet_id = 0x25]
|
||||||
pub struct LoginPlayOwned {
|
pub struct LoginPlayOwned {
|
||||||
pub entity_id: i32,
|
pub entity_id: i32,
|
||||||
|
@ -400,7 +400,7 @@ pub mod play {
|
||||||
pub last_death_location: Option<(Ident<String>, BlockPos)>,
|
pub last_death_location: Option<(Ident<String>, BlockPos)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x28]
|
#[packet_id = 0x28]
|
||||||
pub struct UpdateEntityPosition {
|
pub struct UpdateEntityPosition {
|
||||||
pub entity_id: VarInt,
|
pub entity_id: VarInt,
|
||||||
|
@ -408,7 +408,7 @@ pub mod play {
|
||||||
pub on_ground: bool,
|
pub on_ground: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x29]
|
#[packet_id = 0x29]
|
||||||
pub struct UpdateEntityPositionAndRotation {
|
pub struct UpdateEntityPositionAndRotation {
|
||||||
pub entity_id: VarInt,
|
pub entity_id: VarInt,
|
||||||
|
@ -418,7 +418,7 @@ pub mod play {
|
||||||
pub on_ground: bool,
|
pub on_ground: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x2a]
|
#[packet_id = 0x2a]
|
||||||
pub struct UpdateEntityRotation {
|
pub struct UpdateEntityRotation {
|
||||||
pub entity_id: VarInt,
|
pub entity_id: VarInt,
|
||||||
|
@ -427,7 +427,7 @@ pub mod play {
|
||||||
pub on_ground: bool,
|
pub on_ground: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x2d]
|
#[packet_id = 0x2d]
|
||||||
pub struct OpenScreen {
|
pub struct OpenScreen {
|
||||||
pub window_id: VarInt,
|
pub window_id: VarInt,
|
||||||
|
@ -435,14 +435,14 @@ pub mod play {
|
||||||
pub window_title: Text,
|
pub window_title: Text,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x33]
|
#[packet_id = 0x33]
|
||||||
pub struct PlayerChatMessage<'a> {
|
pub struct PlayerChatMessage<'a> {
|
||||||
// TODO: A _lot_ of fields
|
// TODO: A _lot_ of fields
|
||||||
pub data: RawBytes<'a>,
|
pub data: RawBytes<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x36]
|
#[packet_id = 0x36]
|
||||||
pub struct CombatDeath {
|
pub struct CombatDeath {
|
||||||
pub player_id: VarInt,
|
pub player_id: VarInt,
|
||||||
|
@ -451,7 +451,7 @@ pub mod play {
|
||||||
pub message: Text,
|
pub message: Text,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Debug, Encode, Decode, Packet)]
|
#[derive(Clone, PartialEq, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x37]
|
#[packet_id = 0x37]
|
||||||
pub enum PlayerInfo<'a> {
|
pub enum PlayerInfo<'a> {
|
||||||
AddPlayer(Vec<PlayerInfoAddPlayer<'a>>),
|
AddPlayer(Vec<PlayerInfoAddPlayer<'a>>),
|
||||||
|
@ -461,7 +461,7 @@ pub mod play {
|
||||||
RemovePlayer(Vec<Uuid>),
|
RemovePlayer(Vec<Uuid>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, PartialEq, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x39]
|
#[packet_id = 0x39]
|
||||||
pub struct SynchronizePlayerPosition {
|
pub struct SynchronizePlayerPosition {
|
||||||
pub position: [f64; 3],
|
pub position: [f64; 3],
|
||||||
|
@ -472,19 +472,19 @@ pub mod play {
|
||||||
pub dismount_vehicle: bool,
|
pub dismount_vehicle: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Debug, Encode, Decode, Packet)]
|
#[derive(Clone, PartialEq, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x3b]
|
#[packet_id = 0x3b]
|
||||||
pub struct RemoveEntities {
|
pub struct RemoveEntities {
|
||||||
pub entity_ids: Vec<VarInt>,
|
pub entity_ids: Vec<VarInt>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Debug, Encode, Packet)]
|
#[derive(Copy, Clone, PartialEq, Debug, Encode, EncodePacket)]
|
||||||
#[packet_id = 0x3b]
|
#[packet_id = 0x3b]
|
||||||
pub struct RemoveEntitiesEncode<'a> {
|
pub struct RemoveEntitiesEncode<'a> {
|
||||||
pub entity_ids: &'a [VarInt],
|
pub entity_ids: &'a [VarInt],
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Debug, Encode, Decode, Packet)]
|
#[derive(Clone, PartialEq, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x3d]
|
#[packet_id = 0x3d]
|
||||||
pub struct ResourcePackS2c<'a> {
|
pub struct ResourcePackS2c<'a> {
|
||||||
pub url: &'a str,
|
pub url: &'a str,
|
||||||
|
@ -493,7 +493,7 @@ pub mod play {
|
||||||
pub prompt_message: Option<Text>,
|
pub prompt_message: Option<Text>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Debug, Encode, Decode, Packet)]
|
#[derive(Clone, PartialEq, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x3e]
|
#[packet_id = 0x3e]
|
||||||
pub struct Respawn<'a> {
|
pub struct Respawn<'a> {
|
||||||
pub dimension_type_name: Ident<&'a str>,
|
pub dimension_type_name: Ident<&'a str>,
|
||||||
|
@ -508,7 +508,7 @@ pub mod play {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: remove
|
// TODO: remove
|
||||||
#[derive(Clone, PartialEq, Debug, Encode, Decode, Packet)]
|
#[derive(Clone, PartialEq, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x3e]
|
#[packet_id = 0x3e]
|
||||||
pub struct RespawnOwned {
|
pub struct RespawnOwned {
|
||||||
pub dimension_type_name: Ident<String>,
|
pub dimension_type_name: Ident<String>,
|
||||||
|
@ -522,14 +522,14 @@ pub mod play {
|
||||||
pub last_death_location: Option<(Ident<String>, BlockPos)>,
|
pub last_death_location: Option<(Ident<String>, BlockPos)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x3f]
|
#[packet_id = 0x3f]
|
||||||
pub struct SetHeadRotation {
|
pub struct SetHeadRotation {
|
||||||
pub entity_id: VarInt,
|
pub entity_id: VarInt,
|
||||||
pub head_yaw: ByteAngle,
|
pub head_yaw: ByteAngle,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x40]
|
#[packet_id = 0x40]
|
||||||
pub struct UpdateSectionBlocks {
|
pub struct UpdateSectionBlocks {
|
||||||
pub chunk_section_position: i64,
|
pub chunk_section_position: i64,
|
||||||
|
@ -537,7 +537,7 @@ pub mod play {
|
||||||
pub blocks: Vec<VarLong>,
|
pub blocks: Vec<VarLong>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Encode, Packet)]
|
#[derive(Clone, Debug, Encode, EncodePacket)]
|
||||||
#[packet_id = 0x40]
|
#[packet_id = 0x40]
|
||||||
pub struct UpdateSectionBlocksEncode<'a> {
|
pub struct UpdateSectionBlocksEncode<'a> {
|
||||||
pub chunk_section_position: i64,
|
pub chunk_section_position: i64,
|
||||||
|
@ -545,49 +545,49 @@ pub mod play {
|
||||||
pub blocks: &'a [VarLong],
|
pub blocks: &'a [VarLong],
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x43]
|
#[packet_id = 0x43]
|
||||||
pub struct SetActionBarText(pub Text);
|
pub struct SetActionBarText(pub Text);
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x4a]
|
#[packet_id = 0x4a]
|
||||||
pub struct SetHeldItemS2c {
|
pub struct SetHeldItemS2c {
|
||||||
pub slot: u8,
|
pub slot: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x4b]
|
#[packet_id = 0x4b]
|
||||||
pub struct SetCenterChunk {
|
pub struct SetCenterChunk {
|
||||||
pub chunk_x: VarInt,
|
pub chunk_x: VarInt,
|
||||||
pub chunk_z: VarInt,
|
pub chunk_z: VarInt,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x4c]
|
#[packet_id = 0x4c]
|
||||||
pub struct SetRenderDistance(pub VarInt);
|
pub struct SetRenderDistance(pub VarInt);
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x4d]
|
#[packet_id = 0x4d]
|
||||||
pub struct SetDefaultSpawnPosition {
|
pub struct SetDefaultSpawnPosition {
|
||||||
pub position: BlockPos,
|
pub position: BlockPos,
|
||||||
pub angle: f32,
|
pub angle: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x50]
|
#[packet_id = 0x50]
|
||||||
pub struct SetEntityMetadata<'a> {
|
pub struct SetEntityMetadata<'a> {
|
||||||
pub entity_id: VarInt,
|
pub entity_id: VarInt,
|
||||||
pub metadata: RawBytes<'a>,
|
pub metadata: RawBytes<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x52]
|
#[packet_id = 0x52]
|
||||||
pub struct SetEntityVelocity {
|
pub struct SetEntityVelocity {
|
||||||
pub entity_id: VarInt,
|
pub entity_id: VarInt,
|
||||||
pub velocity: [i16; 3],
|
pub velocity: [i16; 3],
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x54]
|
#[packet_id = 0x54]
|
||||||
pub struct SetExperience {
|
pub struct SetExperience {
|
||||||
pub bar: f32,
|
pub bar: f32,
|
||||||
|
@ -595,7 +595,7 @@ pub mod play {
|
||||||
pub total_xp: VarInt,
|
pub total_xp: VarInt,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x55]
|
#[packet_id = 0x55]
|
||||||
pub struct SetHealth {
|
pub struct SetHealth {
|
||||||
pub health: f32,
|
pub health: f32,
|
||||||
|
@ -603,11 +603,11 @@ pub mod play {
|
||||||
pub food_saturation: f32,
|
pub food_saturation: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x5b]
|
#[packet_id = 0x5b]
|
||||||
pub struct SetSubtitleText(pub Text);
|
pub struct SetSubtitleText(pub Text);
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x5c]
|
#[packet_id = 0x5c]
|
||||||
pub struct UpdateTime {
|
pub struct UpdateTime {
|
||||||
/// The age of the world in 1/20ths of a second.
|
/// The age of the world in 1/20ths of a second.
|
||||||
|
@ -618,11 +618,11 @@ pub mod play {
|
||||||
pub time_of_day: i64,
|
pub time_of_day: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x5d]
|
#[packet_id = 0x5d]
|
||||||
pub struct SetTitleText(pub Text);
|
pub struct SetTitleText(pub Text);
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x5e]
|
#[packet_id = 0x5e]
|
||||||
pub struct SetTitleAnimationTimes {
|
pub struct SetTitleAnimationTimes {
|
||||||
/// Ticks to spend fading in.
|
/// Ticks to spend fading in.
|
||||||
|
@ -633,7 +633,7 @@ pub mod play {
|
||||||
pub fade_out: i32,
|
pub fade_out: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x5f]
|
#[packet_id = 0x5f]
|
||||||
pub struct EntitySoundEffect {
|
pub struct EntitySoundEffect {
|
||||||
pub id: VarInt,
|
pub id: VarInt,
|
||||||
|
@ -643,7 +643,7 @@ pub mod play {
|
||||||
pub pitch: f32,
|
pub pitch: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x60]
|
#[packet_id = 0x60]
|
||||||
pub struct SoundEffect {
|
pub struct SoundEffect {
|
||||||
pub id: VarInt,
|
pub id: VarInt,
|
||||||
|
@ -654,7 +654,7 @@ pub mod play {
|
||||||
pub seed: i64,
|
pub seed: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x62]
|
#[packet_id = 0x62]
|
||||||
pub struct SystemChatMessage {
|
pub struct SystemChatMessage {
|
||||||
pub chat: Text,
|
pub chat: Text,
|
||||||
|
@ -662,14 +662,14 @@ pub mod play {
|
||||||
pub kind: VarInt,
|
pub kind: VarInt,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x63]
|
#[packet_id = 0x63]
|
||||||
pub struct SetTabListHeaderAndFooter {
|
pub struct SetTabListHeaderAndFooter {
|
||||||
pub header: Text,
|
pub header: Text,
|
||||||
pub footer: Text,
|
pub footer: Text,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Copy, Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x66]
|
#[packet_id = 0x66]
|
||||||
pub struct TeleportEntity {
|
pub struct TeleportEntity {
|
||||||
pub entity_id: VarInt,
|
pub entity_id: VarInt,
|
||||||
|
@ -679,7 +679,7 @@ pub mod play {
|
||||||
pub on_ground: bool,
|
pub on_ground: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Encode, Decode, Packet)]
|
#[derive(Clone, Debug, Encode, EncodePacket, Decode, DecodePacket)]
|
||||||
#[packet_id = 0x68]
|
#[packet_id = 0x68]
|
||||||
pub struct UpdateAttributes<'a> {
|
pub struct UpdateAttributes<'a> {
|
||||||
pub entity_id: VarInt,
|
pub entity_id: VarInt,
|
||||||
|
|
|
@ -3,7 +3,7 @@ use std::io::Write;
|
||||||
use crate::{Decode, Encode, Result};
|
use crate::{Decode, Encode, Result};
|
||||||
|
|
||||||
/// While [encoding], the contained slice is written directly to the output
|
/// While [encoding], the contained slice is written directly to the output
|
||||||
/// without any metadata.
|
/// without any length prefix or metadata.
|
||||||
///
|
///
|
||||||
/// While [decoding], the remainder of the input is returned as the contained
|
/// While [decoding], the remainder of the input is returned as the contained
|
||||||
/// slice. The input will be at the EOF state after this is finished.
|
/// slice. The input will be at the EOF state after this is finished.
|
||||||
|
@ -17,10 +17,6 @@ impl Encode for RawBytes<'_> {
|
||||||
fn encode(&self, mut w: impl Write) -> Result<()> {
|
fn encode(&self, mut w: impl Write) -> Result<()> {
|
||||||
Ok(w.write_all(self.0)?)
|
Ok(w.write_all(self.0)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encoded_len(&self) -> usize {
|
|
||||||
self.0.len()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Decode<'a> for RawBytes<'a> {
|
impl<'a> Decode<'a> for RawBytes<'a> {
|
||||||
|
|
|
@ -7,8 +7,7 @@ use std::io::Write;
|
||||||
use serde::de::Visitor;
|
use serde::de::Visitor;
|
||||||
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
|
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
|
||||||
|
|
||||||
use crate::byte_counter::ByteCounter;
|
use crate::{Decode, Encode, Ident, Result};
|
||||||
use crate::{Decode, Encode, Ident, Result, VarInt};
|
|
||||||
|
|
||||||
/// Represents formatted text in Minecraft's JSON text format.
|
/// Represents formatted text in Minecraft's JSON text format.
|
||||||
///
|
///
|
||||||
|
@ -732,18 +731,10 @@ impl fmt::Display for Text {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Encode implementation for Text is not very fast. Beware.
|
|
||||||
impl Encode for Text {
|
impl Encode for Text {
|
||||||
fn encode(&self, w: impl Write) -> Result<()> {
|
fn encode(&self, w: impl Write) -> Result<()> {
|
||||||
serde_json::to_string(self)?.encode(w)
|
serde_json::to_string(self)?.encode(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encoded_len(&self) -> usize {
|
|
||||||
let mut counter = ByteCounter::new();
|
|
||||||
let _ = serde_json::to_writer(&mut counter, self);
|
|
||||||
|
|
||||||
VarInt(counter.0.try_into().unwrap_or(i32::MAX)).encoded_len() + counter.0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decode<'_> for Text {
|
impl Decode<'_> for Text {
|
||||||
|
|
|
@ -133,10 +133,6 @@ where
|
||||||
fn encode(&self, w: impl Write) -> Result<()> {
|
fn encode(&self, w: impl Write) -> Result<()> {
|
||||||
self.0.encode(w)
|
self.0.encode(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encoded_len(&self) -> usize {
|
|
||||||
self.0.encoded_len()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, S> Decode<'a> for Username<S>
|
impl<'a, S> Decode<'a> for Username<S>
|
||||||
|
|
|
@ -8,6 +8,7 @@ use crate::{Decode, Encode};
|
||||||
|
|
||||||
/// An `i32` encoded with variable length.
|
/// An `i32` encoded with variable length.
|
||||||
#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||||
|
#[repr(transparent)]
|
||||||
pub struct VarInt(pub i32);
|
pub struct VarInt(pub i32);
|
||||||
|
|
||||||
impl VarInt {
|
impl VarInt {
|
||||||
|
@ -15,6 +16,15 @@ impl VarInt {
|
||||||
/// written to the Minecraft protocol.
|
/// written to the Minecraft protocol.
|
||||||
pub const MAX_SIZE: usize = 5;
|
pub const MAX_SIZE: usize = 5;
|
||||||
|
|
||||||
|
/// Returns the exact number of bytes this varint will write when
|
||||||
|
/// [`Encode::encode`] is called, assuming no error occurs.
|
||||||
|
pub fn written_size(self) -> usize {
|
||||||
|
match self.0 {
|
||||||
|
0 => 1,
|
||||||
|
n => (31 - n.leading_zeros() as usize) / 7 + 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn decode_partial(mut r: impl Read) -> Result<i32, VarIntDecodeError> {
|
pub fn decode_partial(mut r: impl Read) -> Result<i32, VarIntDecodeError> {
|
||||||
let mut val = 0;
|
let mut val = 0;
|
||||||
for i in 0..Self::MAX_SIZE {
|
for i in 0..Self::MAX_SIZE {
|
||||||
|
@ -49,14 +59,6 @@ impl Encode for VarInt {
|
||||||
val >>= 7;
|
val >>= 7;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn encoded_len(&self) -> usize {
|
|
||||||
match self.0 {
|
|
||||||
0 => 1,
|
|
||||||
n => (31 - n.leading_zeros() as usize) / 7 + 1,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decode<'_> for VarInt {
|
impl Decode<'_> for VarInt {
|
||||||
|
@ -92,7 +94,7 @@ mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn encoded_len_correct() {
|
fn varint_written_size() {
|
||||||
let mut rng = thread_rng();
|
let mut rng = thread_rng();
|
||||||
let mut buf = vec![];
|
let mut buf = vec![];
|
||||||
|
|
||||||
|
@ -103,12 +105,12 @@ mod tests {
|
||||||
{
|
{
|
||||||
buf.clear();
|
buf.clear();
|
||||||
n.encode(&mut buf).unwrap();
|
n.encode(&mut buf).unwrap();
|
||||||
assert_eq!(buf.len(), n.encoded_len());
|
assert_eq!(buf.len(), n.written_size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn encode_decode() {
|
fn varint_round_trip() {
|
||||||
let mut rng = thread_rng();
|
let mut rng = thread_rng();
|
||||||
let mut buf = vec![];
|
let mut buf = vec![];
|
||||||
|
|
||||||
|
|
|
@ -7,12 +7,22 @@ use crate::{Decode, Encode, Result};
|
||||||
|
|
||||||
/// An `i64` encoded with variable length.
|
/// An `i64` encoded with variable length.
|
||||||
#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||||
|
#[repr(transparent)]
|
||||||
pub struct VarLong(pub i64);
|
pub struct VarLong(pub i64);
|
||||||
|
|
||||||
impl VarLong {
|
impl VarLong {
|
||||||
/// The maximum number of bytes a `VarLong` can occupy when read from and
|
/// The maximum number of bytes a `VarLong` can occupy when read from and
|
||||||
/// written to the Minecraft protocol.
|
/// written to the Minecraft protocol.
|
||||||
pub const MAX_SIZE: usize = 10;
|
pub const MAX_SIZE: usize = 10;
|
||||||
|
|
||||||
|
/// Returns the exact number of bytes this varlong will write when
|
||||||
|
/// [`Encode::encode`] is called, assuming no error occurs.
|
||||||
|
pub fn written_size(self) -> usize {
|
||||||
|
match self.0 {
|
||||||
|
0 => 1,
|
||||||
|
n => (63 - n.leading_zeros() as usize) / 7 + 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Encode for VarLong {
|
impl Encode for VarLong {
|
||||||
|
@ -27,13 +37,6 @@ impl Encode for VarLong {
|
||||||
val >>= 7;
|
val >>= 7;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encoded_len(&self) -> usize {
|
|
||||||
match self.0 {
|
|
||||||
0 => 1,
|
|
||||||
n => (63 - n.leading_zeros() as usize) / 7 + 1,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decode<'_> for VarLong {
|
impl Decode<'_> for VarLong {
|
||||||
|
|
Loading…
Reference in a new issue