Expose the protocol API behind a feature flag

This could be useful for building proxies or clients in the future.
This commit is contained in:
Ryan 2022-06-30 11:53:57 -07:00
parent fa2241c038
commit 560163fd2e
20 changed files with 70 additions and 84 deletions

View file

@ -60,3 +60,7 @@ proc-macro2 = "1"
quote = "1" quote = "1"
serde = {version = "1", features = ["derive"]} serde = {version = "1", features = ["derive"]}
serde_json = "1" serde_json = "1"
[features]
# Exposes the raw protocol API
protocol = []

View file

@ -2150,11 +2150,11 @@ pub fn build() -> anyhow::Result<()> {
#getter_setters #getter_setters
pub(crate) fn initial_metadata(&self, data: &mut Vec<u8>) { pub(crate) fn initial_metadata(&self, #[allow(unused)] data: &mut Vec<u8>) {
#initial_metadata_fields #initial_metadata_fields
} }
pub(crate) fn updated_metadata(&self, data: &mut Vec<u8>) { pub(crate) fn updated_metadata(&self, #[allow(unused)] data: &mut Vec<u8>) {
if self.modified_flags == 0 { if self.modified_flags == 0 {
return; return;
} }

View file

@ -5,8 +5,7 @@ use std::io::{Read, Write};
use anyhow::Context; use anyhow::Context;
use crate::protocol::{Decode, Encode}; use crate::protocol::{Decode, Encode, VarInt};
use crate::var_int::VarInt;
include!(concat!(env!("OUT_DIR"), "/block.rs")); include!(concat!(env!("OUT_DIR"), "/block.rs"));

View file

@ -9,12 +9,10 @@ use num::Integer;
use rayon::iter::{IntoParallelRefIterator, IntoParallelRefMutIterator, ParallelIterator}; use rayon::iter::{IntoParallelRefIterator, IntoParallelRefMutIterator, ParallelIterator};
use crate::block::BlockState; use crate::block::BlockState;
use crate::packets::play::s2c::{ use crate::protocol::packets::play::s2c::{
BlockChange, ChunkDataAndUpdateLight, ChunkDataHeightmaps, MultiBlockChange, S2cPlayPacket, BlockChange, ChunkDataAndUpdateLight, ChunkDataHeightmaps, MultiBlockChange, S2cPlayPacket,
}; };
use crate::protocol::{Encode, Nbt}; use crate::protocol::{Encode, Nbt, VarInt, VarLong};
use crate::var_int::VarInt;
use crate::var_long::VarLong;
use crate::{BiomeId, BlockPos, ChunkPos, DimensionId, Server, Ticks}; use crate::{BiomeId, BlockPos, ChunkPos, DimensionId, Server, Ticks};
pub struct Chunks { pub struct Chunks {

View file

@ -11,14 +11,13 @@ use uuid::Uuid;
use vek::Vec3; use vek::Vec3;
use crate::biome::{Biome, BiomeGrassColorModifier, BiomePrecipitation}; use crate::biome::{Biome, BiomeGrassColorModifier, BiomePrecipitation};
use crate::block_pos::BlockPos;
use crate::byte_angle::ByteAngle;
use crate::dimension::{Dimension, DimensionEffects}; use crate::dimension::{Dimension, DimensionEffects};
use crate::entity::types::Player; use crate::entity::types::Player;
use crate::entity::{velocity_to_packet_units, EntityType}; use crate::entity::{velocity_to_packet_units, EntityType};
use crate::packets::play::c2s::{C2sPlayPacket, DiggingStatus}; use crate::player_textures::SignedPlayerTextures;
pub use crate::packets::play::s2c::ChatMessageType; use crate::protocol::packets::play::c2s::{C2sPlayPacket, DiggingStatus, InteractType};
use crate::packets::play::s2c::{ pub use crate::protocol::packets::play::s2c::ChatMessageType;
use crate::protocol::packets::play::s2c::{
AcknowledgeBlockChanges, Biome as BiomeRegistryBiome, BiomeAdditionsSound, BiomeEffects, AcknowledgeBlockChanges, Biome as BiomeRegistryBiome, BiomeAdditionsSound, BiomeEffects,
BiomeMoodSound, BiomeMusic, BiomeParticle, BiomeParticleOptions, BiomeProperty, BiomeRegistry, BiomeMoodSound, BiomeMusic, BiomeParticle, BiomeParticleOptions, BiomeProperty, BiomeRegistry,
ChangeGameState, ChangeGameStateReason, ChatTypeRegistry, DestroyEntities, DimensionType, ChangeGameState, ChangeGameStateReason, ChatTypeRegistry, DestroyEntities, DimensionType,
@ -28,15 +27,13 @@ use crate::packets::play::s2c::{
S2cPlayPacket, SpawnPosition, SystemChatMessage, UnloadChunk, UpdateViewDistance, S2cPlayPacket, SpawnPosition, SystemChatMessage, UnloadChunk, UpdateViewDistance,
UpdateViewPosition, UpdateViewPosition,
}; };
use crate::player_textures::SignedPlayerTextures; use crate::protocol::{BoundedInt, ByteAngle, Nbt, RawBytes, VarInt};
use crate::protocol::{BoundedInt, Nbt, RawBytes};
use crate::server::C2sPacketChannels; use crate::server::C2sPacketChannels;
use crate::slotmap::{Key, SlotMap}; use crate::slotmap::{Key, SlotMap};
use crate::util::{chunks_in_view_distance, is_chunk_in_view_distance}; use crate::util::{chunks_in_view_distance, is_chunk_in_view_distance};
use crate::var_int::VarInt;
use crate::{ use crate::{
ident, ChunkPos, Chunks, DimensionId, Entities, EntityId, NewClientData, Server, SpatialIndex, ident, BlockPos, ChunkPos, Chunks, DimensionId, Entities, EntityId, NewClientData, Server,
Text, Ticks, WorldMeta, LIBRARY_NAMESPACE, SpatialIndex, Text, Ticks, WorldMeta, LIBRARY_NAMESPACE,
}; };
pub struct Clients { pub struct Clients {
@ -441,7 +438,6 @@ impl Client {
// TODO: verify that the client has line of sight to the targeted entity and // TODO: verify that the client has line of sight to the targeted entity and
// that the distance is <=4 blocks. // that the distance is <=4 blocks.
use crate::packets::play::c2s::InteractType;
self.events.push(Event::InteractWithEntity { self.events.push(Event::InteractWithEntity {
id, id,
sneaking: p.sneaking, sneaking: p.sneaking,

View file

@ -2,9 +2,9 @@ use std::time::Duration;
use vek::Vec3; use vek::Vec3;
use crate::packets::play::c2s::BlockFace; use crate::protocol::packets::play::c2s::BlockFace;
pub use crate::packets::play::c2s::{ChatMode, DisplayedSkinParts, Hand, MainHand}; pub use crate::protocol::packets::play::c2s::{ChatMode, DisplayedSkinParts, Hand, MainHand};
pub use crate::packets::play::s2c::GameMode; pub use crate::protocol::packets::play::s2c::GameMode;
use crate::{BlockPos, EntityId}; use crate::{BlockPos, EntityId};
#[derive(Debug)] #[derive(Debug)]

View file

@ -12,14 +12,12 @@ pub use types::{EntityMeta, EntityType};
use uuid::Uuid; use uuid::Uuid;
use vek::{Aabb, Vec3}; use vek::{Aabb, Vec3};
use crate::byte_angle::ByteAngle; use crate::protocol::packets::play::s2c::{
use crate::packets::play::s2c::{
EntityMetadata, S2cPlayPacket, SpawnEntity, SpawnExperienceOrb, SpawnPlayer, EntityMetadata, S2cPlayPacket, SpawnEntity, SpawnExperienceOrb, SpawnPlayer,
}; };
use crate::protocol::RawBytes; use crate::protocol::{ByteAngle, RawBytes, VarInt};
use crate::slotmap::{Key, SlotMap}; use crate::slotmap::{Key, SlotMap};
use crate::util::aabb_from_bottom_and_size; use crate::util::aabb_from_bottom_and_size;
use crate::var_int::VarInt;
pub struct Entities { pub struct Entities {
sm: SlotMap<Entity>, sm: SlotMap<Entity>,

View file

@ -2,8 +2,7 @@
use std::io::Write; use std::io::Write;
use crate::protocol::Encode; use crate::protocol::{Encode, VarInt};
use crate::var_int::VarInt;
#[derive(Clone, Copy, Default, PartialEq, PartialOrd, Debug)] #[derive(Clone, Copy, Default, PartialEq, PartialOrd, Debug)]
pub struct ArmorStandRotations { pub struct ArmorStandRotations {

View file

@ -2,8 +2,7 @@
use crate::block::BlockState; use crate::block::BlockState;
use crate::entity::meta::*; use crate::entity::meta::*;
use crate::protocol::Encode; use crate::protocol::{Encode, VarInt};
use crate::var_int::VarInt;
use crate::{BlockPos, EntityId, Text, Uuid}; use crate::{BlockPos, EntityId, Text, Uuid};
include!(concat!(env!("OUT_DIR"), "/entity.rs")); include!(concat!(env!("OUT_DIR"), "/entity.rs"));

View file

@ -11,26 +11,24 @@ pub mod biome;
pub mod block; pub mod block;
mod block_pos; mod block_pos;
mod bvh; mod bvh;
mod byte_angle;
pub mod chunk; pub mod chunk;
mod chunk_pos; mod chunk_pos;
pub mod client; pub mod client;
mod codec;
pub mod config; pub mod config;
pub mod dimension; pub mod dimension;
pub mod entity; pub mod entity;
pub mod ident; pub mod ident;
mod packets;
mod player_list; mod player_list;
pub mod player_textures; pub mod player_textures;
#[cfg(not(feature = "protocol"))]
mod protocol; mod protocol;
#[cfg(feature = "protocol")]
pub mod protocol;
pub mod server; pub mod server;
mod slotmap; mod slotmap;
pub mod spatial_index; mod spatial_index;
pub mod text; pub mod text;
pub mod util; pub mod util;
mod var_int;
mod var_long;
pub mod world; pub mod world;
pub use async_trait::async_trait; pub use async_trait::async_trait;

View file

@ -5,12 +5,12 @@ use bitfield_struct::bitfield;
use uuid::Uuid; use uuid::Uuid;
use crate::client::GameMode; use crate::client::GameMode;
use crate::packets::play::s2c::{ use crate::player_textures::SignedPlayerTextures;
use crate::protocol::packets::play::s2c::{
PlayerInfo, PlayerInfoAddPlayer, PlayerListHeaderFooter, S2cPlayPacket, PlayerInfo, PlayerInfoAddPlayer, PlayerListHeaderFooter, S2cPlayPacket,
}; };
use crate::packets::Property; use crate::protocol::packets::Property;
use crate::player_textures::SignedPlayerTextures; use crate::protocol::VarInt;
use crate::var_int::VarInt;
use crate::Text; use crate::Text;
pub struct PlayerList { pub struct PlayerList {

View file

@ -1,16 +1,24 @@
mod byte_angle;
pub mod codec;
pub mod packets;
mod var_int;
mod var_long;
use std::io::{Read, Write}; use std::io::{Read, Write};
use std::mem; use std::mem;
use anyhow::{anyhow, ensure, Context}; use anyhow::{anyhow, ensure, Context};
use arrayvec::ArrayVec; use arrayvec::ArrayVec;
use bitvec::prelude::*; use bitvec::prelude::*;
pub use byte_angle::ByteAngle;
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt}; use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use serde::de::DeserializeOwned; use serde::de::DeserializeOwned;
use serde::Serialize; use serde::Serialize;
use uuid::Uuid; use uuid::Uuid;
pub use var_int::VarInt;
pub use var_long::VarLong;
use vek::{Vec2, Vec3, Vec4}; use vek::{Vec2, Vec3, Vec4};
use crate::var_int::VarInt;
use crate::EntityId; use crate::EntityId;
/// Trait for types that can be written to the Minecraft protocol. /// Trait for types that can be written to the Minecraft protocol.
@ -18,7 +26,7 @@ pub trait Encode {
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()>; fn encode(&self, w: &mut impl Write) -> anyhow::Result<()>;
} }
/// Trait for types that can be constructed from the Minecraft protocol. /// Trait for types that can be read from the Minecraft protocol.
pub trait Decode: Sized { pub trait Decode: Sized {
fn decode(r: &mut impl Read) -> anyhow::Result<Self>; fn decode(r: &mut impl Read) -> anyhow::Result<Self>;
} }

View file

@ -12,8 +12,7 @@ use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
use tokio::time::timeout; use tokio::time::timeout;
use super::packets::{DecodePacket, EncodePacket}; use super::packets::{DecodePacket, EncodePacket};
use crate::protocol::{Decode, Encode, MAX_PACKET_SIZE}; use crate::protocol::{Decode, Encode, VarInt, MAX_PACKET_SIZE};
use crate::var_int::VarInt;
pub struct Encoder<W> { pub struct Encoder<W> {
write: W, write: W,
@ -238,7 +237,7 @@ mod tests {
use tokio::sync::oneshot; use tokio::sync::oneshot;
use super::*; use super::*;
use crate::packets::test::TestPacket; use crate::protocol::packets::test::TestPacket;
#[tokio::test] #[tokio::test]
async fn encode_decode() { async fn encode_decode() {

View file

@ -16,10 +16,10 @@ use uuid::Uuid;
use vek::Vec3; use vek::Vec3;
use crate::block_pos::BlockPos; use crate::block_pos::BlockPos;
use crate::byte_angle::ByteAngle; use crate::protocol::{
use crate::protocol::{BoundedArray, BoundedInt, BoundedString, Decode, Encode, Nbt, RawBytes}; BoundedArray, BoundedInt, BoundedString, ByteAngle, Decode, Encode, Nbt, RawBytes, VarInt,
use crate::var_int::VarInt; VarLong,
use crate::var_long::VarLong; };
use crate::{Ident, Text}; use crate::{Ident, Text};
/// Trait for types that can be written to the Minecraft protocol as a complete /// Trait for types that can be written to the Minecraft protocol as a complete
@ -27,7 +27,7 @@ use crate::{Ident, Text};
/// ///
/// A complete packet is one that starts with a `VarInt` packet ID, followed by /// A complete packet is one that starts with a `VarInt` packet ID, followed by
/// the body of the packet. /// the body of the packet.
pub trait EncodePacket: fmt::Debug + private::Sealed { pub trait EncodePacket: fmt::Debug {
/// Writes a packet to the Minecraft protocol, including its packet ID. /// Writes a packet to the Minecraft protocol, including its packet ID.
fn encode_packet(&self, w: &mut impl Write) -> anyhow::Result<()>; fn encode_packet(&self, w: &mut impl Write) -> anyhow::Result<()>;
} }
@ -37,7 +37,7 @@ pub trait EncodePacket: fmt::Debug + private::Sealed {
/// ///
/// A complete packet is one that starts with a `VarInt` packet ID, followed by /// A complete packet is one that starts with a `VarInt` packet ID, followed by
/// the body of the packet. /// the body of the packet.
pub trait DecodePacket: Sized + fmt::Debug + private::Sealed { pub trait DecodePacket: Sized + fmt::Debug {
/// Reads a packet from the Minecraft protocol, including its packet ID. /// Reads a packet from the Minecraft protocol, including its packet ID.
fn decode_packet(r: &mut impl Read) -> anyhow::Result<Self>; fn decode_packet(r: &mut impl Read) -> anyhow::Result<Self>;
} }
@ -94,8 +94,6 @@ macro_rules! def_struct {
} }
$( $(
impl private::Sealed for $name {}
impl EncodePacket for $name { impl EncodePacket for $name {
fn encode_packet(&self, w: &mut impl Write) -> anyhow::Result<()> { fn encode_packet(&self, w: &mut impl Write) -> anyhow::Result<()> {
VarInt($id) VarInt($id)
@ -206,8 +204,6 @@ macro_rules! def_enum {
} }
$( $(
impl private::Sealed for $name {}
impl EncodePacket for $name { impl EncodePacket for $name {
fn encode_packet(&self, w: &mut impl Write) -> anyhow::Result<()> { fn encode_packet(&self, w: &mut impl Write) -> anyhow::Result<()> {
VarInt($id) VarInt($id)
@ -325,10 +321,6 @@ macro_rules! def_bitfield {
} }
} }
mod private {
pub trait Sealed {}
}
def_struct! { def_struct! {
#[derive(PartialEq, Serialize, Deserialize)] #[derive(PartialEq, Serialize, Deserialize)]
Property { Property {
@ -339,6 +331,14 @@ def_struct! {
} }
} }
def_struct! {
SignatureData {
timestamp: u64,
public_key: Vec<u8>,
signature: Vec<u8>,
}
}
/// Packets and types used during the handshaking state. /// Packets and types used during the handshaking state.
pub mod handshake { pub mod handshake {
use super::*; use super::*;
@ -440,14 +440,6 @@ pub mod login {
} }
} }
def_struct! {
SignatureData {
timestamp: i64,
public_key: Vec<u8>,
signature: Vec<u8>,
}
}
def_struct! { def_struct! {
EncryptionResponse 0x01 { EncryptionResponse 0x01 {
shared_secret: BoundedArray<u8, 16, 128>, shared_secret: BoundedArray<u8, 16, 128>,
@ -475,7 +467,6 @@ pub mod login {
pub mod play { pub mod play {
pub mod s2c { pub mod s2c {
use super::super::*; use super::super::*;
use crate::packets::login::c2s::SignatureData;
def_struct! { def_struct! {
SpawnEntity 0x00 { SpawnEntity 0x00 {
@ -1173,8 +1164,6 @@ pub mod play {
$($packet($packet)),* $($packet($packet)),*
} }
impl private::Sealed for S2cPlayPacket {}
$( $(
impl From<$packet> for S2cPlayPacket { impl From<$packet> for S2cPlayPacket {
fn from(p: $packet) -> S2cPlayPacket { fn from(p: $packet) -> S2cPlayPacket {
@ -1831,8 +1820,6 @@ pub mod play {
$($packet($packet)),* $($packet($packet)),*
} }
impl private::Sealed for C2sPlayPacket {}
impl DecodePacket for C2sPlayPacket { impl DecodePacket for C2sPlayPacket {
fn decode_packet(r: &mut impl Read) -> anyhow::Result<C2sPlayPacket> { fn decode_packet(r: &mut impl Read) -> anyhow::Result<C2sPlayPacket> {
let packet_id = VarInt::decode(r).context("failed to read c2s play packet ID")?.0; let packet_id = VarInt::decode(r).context("failed to read c2s play packet ID")?.0;
@ -1926,7 +1913,7 @@ pub mod play {
} }
#[cfg(test)] #[cfg(test)]
pub mod test { pub(crate) mod test {
use super::*; use super::*;
def_struct! { def_struct! {

View file

@ -26,20 +26,19 @@ use tokio::runtime::{Handle, Runtime};
use tokio::sync::{oneshot, Semaphore}; use tokio::sync::{oneshot, Semaphore};
use uuid::Uuid; use uuid::Uuid;
use crate::codec::{Decoder, Encoder};
use crate::config::{Config, ServerListPing}; use crate::config::{Config, ServerListPing};
use crate::packets::handshake::{Handshake, HandshakeNextState};
use crate::packets::login::c2s::{EncryptionResponse, LoginStart, VerifyTokenOrMsgSig};
use crate::packets::login::s2c::{EncryptionRequest, LoginSuccess, SetCompression};
use crate::packets::play::c2s::C2sPlayPacket;
use crate::packets::play::s2c::S2cPlayPacket;
use crate::packets::status::c2s::{Ping, Request};
use crate::packets::status::s2c::{Pong, Response};
use crate::packets::{login, Property};
use crate::player_textures::SignedPlayerTextures; use crate::player_textures::SignedPlayerTextures;
use crate::protocol::{BoundedArray, BoundedString}; use crate::protocol::codec::{Decoder, Encoder};
use crate::protocol::packets::handshake::{Handshake, HandshakeNextState};
use crate::protocol::packets::login::c2s::{EncryptionResponse, LoginStart, VerifyTokenOrMsgSig};
use crate::protocol::packets::login::s2c::{EncryptionRequest, LoginSuccess, SetCompression};
use crate::protocol::packets::play::c2s::C2sPlayPacket;
use crate::protocol::packets::play::s2c::S2cPlayPacket;
use crate::protocol::packets::status::c2s::{Ping, Request};
use crate::protocol::packets::status::s2c::{Pong, Response};
use crate::protocol::packets::{login, Property};
use crate::protocol::{BoundedArray, BoundedString, VarInt};
use crate::util::valid_username; use crate::util::valid_username;
use crate::var_int::VarInt;
use crate::world::Worlds; use crate::world::Worlds;
use crate::{ use crate::{
Biome, BiomeId, Client, Dimension, DimensionId, Ticks, PROTOCOL_VERSION, VERSION_NAME, Biome, BiomeId, Client, Dimension, DimensionId, Ticks, PROTOCOL_VERSION, VERSION_NAME,

View file

View file

@ -40,6 +40,7 @@ impl Key {
} }
} }
#[allow(unused)]
pub fn index(self) -> u32 { pub fn index(self) -> u32 {
self.index self.index
} }
@ -161,6 +162,7 @@ impl<T> SlotMap<T> {
} }
} }
#[allow(unused)]
pub fn clear(&mut self) { pub fn clear(&mut self) {
self.slots.clear(); self.slots.clear();
self.next_free_head = 0; self.next_free_head = 0;